Commit 5f80dd6
feat(azure.ai.agents): add invoke-local secondary to init "everything ready" Next: (P5.1 C7)
Issue Azure#7975 lines 96-103 specify that the init "everything ready"
output should surface two commands, not one:
Next: azd ai agent run -- start the agent locally
azd ai agent invoke --local "Hello!" -- test it in another terminal
Pre-C7 the resolver emitted only `azd ai agent run` (plus the trailing
`azd deploy` reminder). Users hit the "now what?" wall after the agent
bound its port: they had to remember `azd ai agent invoke --local …`
and figure out the right payload for their protocol.
Source of truth: issue Azure#7975 lines 96-103. Spec example uses the
unqualified `azd ai agent invoke --local "Hello!"` form regardless of
how many services the project declares.
# Change
`ResolveAfterInit`'s default branch (everything-ready case) now appends
a second `Suggestion`:
Command: azd ai agent invoke --local <payload>
Description: test it in another terminal
The trailing `azd deploy` reminder stays in place (Priority 90,
Trailing:true), so the rendered block is three lines on a fresh,
fully-provisioned project.
Payload selection:
- `len(state.Services) == 1` → `defaultInvokePayload(&state.Services[0])`
which already maps `ProtocolInvocations` → `'{"message": "Hello!"}'`
(JSON envelope) and everything else → `"Hello!"`. So a single-agent
invocations-protocol project gets the JSON shape, single-agent
responses-protocol gets the literal, matching what `ResolveAfterRun`
has done since commit 2.3.
- `len(state.Services) != 1` (zero or multi-agent) → literal `"Hello!"`.
Multi-agent: the unqualified `azd ai agent invoke --local` doesn't
know which agent the user will pick at runtime, so picking one
service's protocol arbitrarily would be wrong half the time. The
responses-style literal is what the spec example uses.
The suppression branches are untouched:
- `hasPlaceholders` (case 2) — neither `run` nor `invoke --local`
emitted. Running locally with literal `{{NAME}}` values produces a
broken agent; the spec gates `run` on placeholder-clear state, and
the invoke secondary is paired with `run` so it inherits the gate.
- `len(state.MissingManualVars) > 0` (case 1 of the default-cases
block) — the manual-vars renderer ships its own `run` follow-up
("start the agent locally once the values above are set"). The
invoke-local secondary is NOT added there: the manual-vars example
in the spec (lines 119-127) deliberately stops at `run` to keep the
"set values → run" call-to-action focused.
# Renderer
Both init.go (`init.go:1643`) and init_from_code.go (`:148`) call
`nextstep.PrintAllNext`, which has NO line cap (uncapped renderer
per commit 4.7's G1 fix). The new third suggestion fits cleanly;
no truncation risk.
`PrintNext`'s `maxRendered = 2` cap is irrelevant here — it's used
by mid-flow resolvers (invoke, show) where ≤2 suggestions naturally
occur.
# Tests
resolver_test.go adds `TestResolveAfterInit_EverythingReady_EmitsInvokeLocalSecondary`
with five subcases:
1. Zero services → unqualified invoke with responses payload. Pins
the spec-mandated unqualified form. Asserts Priority ordering
(run < invoke) so the renderer always emits them in the
user-expected order.
2. Single-agent responses protocol → `azd ai agent invoke --local "Hello!"`.
3. Single-agent invocations protocol → `azd ai agent invoke --local '{"message": "Hello!"}'`.
Locks the protocol-aware shape.
4. Multi-agent (mixed protocols) → invoke stays unqualified with
responses payload. Anti-regression: protects against accidentally
picking `state.Services[0].Protocol` for a multi-agent project.
5. Placeholders present → neither `run` nor `invoke --local` emitted.
Anti-regression: pairs with the existing
`TestResolveAfterInit_UnresolvedPlaceholders` table.
Existing `TestResolveAfterInit` table cases (happy path,
"existing project chosen, all vars set") still pass without
modification — they assert `out[0].Command` (still
`azd ai agent run`) and `out[len(out)-1].Command` (still
`azd deploy`); the new invoke-local slot inserts in the middle
and they don't pin block length.
# Affected callers
`init.go` and `init_from_code.go` print the new line automatically
via `PrintAllNext`. `doctor.go:243`'s no-deploy branch flows through
`ResolveAfterInit` too — pre-deploy doctor guidance gets the same
upgrade.
# Verified
- gofmt -s -w . (clean)
- go vet ./... (clean)
- go test ./... -count=1 (all packages green; nextstep 6.5s,
cmd 17.3s, doctor 4.9s)
- golangci-lint run ./internal/cmd/... (0 issues)
- cspell lint internal/cmd/nextstep/**/*.go --config ../../.vscode/cspell.yaml (0 issues)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent f2528f1 commit 5f80dd6
2 files changed
Lines changed: 123 additions & 3 deletions
Lines changed: 35 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
68 | 68 | | |
69 | 69 | | |
70 | 70 | | |
71 | | - | |
72 | | - | |
73 | | - | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
74 | 85 | | |
75 | 86 | | |
76 | 87 | | |
| |||
149 | 160 | | |
150 | 161 | | |
151 | 162 | | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
152 | 184 | | |
153 | 185 | | |
154 | 186 | | |
| |||
Lines changed: 88 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
213 | 213 | | |
214 | 214 | | |
215 | 215 | | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
216 | 304 | | |
217 | 305 | | |
218 | 306 | | |
| |||
0 commit comments