fix: resolve agent by id across web UI, SDK types, and ACP#18803
Open
filipeandre wants to merge 6 commits intoanomalyco:devfrom
Open
fix: resolve agent by id across web UI, SDK types, and ACP#18803filipeandre wants to merge 6 commits intoanomalyco:devfrom
filipeandre wants to merge 6 commits intoanomalyco:devfrom
Conversation
The OpenAPI generator omitted the id field from the Agent schema even though the runtime response always included it. This made app-side agent lookup rely on an unsafe cast to read the stable id at runtime. - Add id to components.schemas.Agent properties and required array in openapi.json so generated types are correct going forward - Add id: string to the generated Agent type in v2/gen/types.gen.ts - Patch build.ts to inject Agent.id into the spec before @hey-api/openapi-ts runs, so future regenerations preserve the fix automatically
…message - Store and resolve agent selection by canonical id (falling back to name for legacy persisted values) so renamed plan/build agents map correctly - Add message id tracking to local session state so restore() re-seeds the dropdown whenever a newer backend user message arrives (e.g. plan_exit) instead of skipping updates once any saved selection exists - Export pickAgentItem and syncSessionState as pure helpers for unit testing - Add focused tests covering id-first lookup, legacy name fallback, same- message skip, and newer-message update
Two bugs in ACP caused the 'default agent not found' error when using
custom named agents (e.g. default_agent: "Pulse") from IDEs like IntelliJ:
1. AgentModule.defaultAgent() was called without Instance.provide(), so
config/agent resolution ran outside the project instance context. Wrap
both call sites (resolveModeState and prompt fallback) with
Instance.provide({ directory, fn }).
2. loadAvailableModes built ModeOption with id: agent.name instead of
id: agent.id. This broke mode selection and session history restore for
any agent whose display name differs from its canonical id. Switch to
id: agent.id and update the comparison in resolveModeState to match
against mode.id.
Add ACP mode-resolution tests covering:
- default_agent display name resolves to canonical mode id
- prompt sends canonical agent id rather than display name
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue for this PR
Closes #9296 (follow-up to #18163)
Type of change
What does this PR do?
Three related bugs where agent names were used as stable identifiers instead of agent ids, causing failures when agents are renamed via config (e.g.
agent.build.name = "Forge"ordefault_agent: "Pulse").1. Web UI dropdown does not switch after leaving plan mode (
fix(local))local.session.restore()bailed out as soon as any saved session state existed, so theplan_exitsynthetic user message (which carriesagent: "build") could never update the dropdown. Also, agent selection was keyed on display name rather than stable id.restore()re-seeds the dropdown whenever a newer backend user message arrives, instead of skipping all updates after the first.2. SDK
Agenttype missingidfield (fix(sdk))The OpenAPI generator dropped
idfrom theAgentschema even though the server always returns it. This forced the app to use an unsafe runtime cast to read agent ids.idtocomponents.schemas.Agentinopenapi.jsonand to the generatedv2/gen/types.gen.tstype.sdk/js/script/build.tsto injectAgent.idinto the spec before@hey-api/openapi-tsruns, so future regenerations preserve the fix.3. ACP init fails with
default agent "Pulse" not found(fix(acp))Two bugs in
src/acp/agent.ts:AgentModule.defaultAgent()was called withoutInstance.provide(), so config/agent resolution ran outside the project instance context. The custom agent only defined in the project config was never found.loadAvailableModesbuiltModeOptionwithid: agent.nameinstead ofid: agent.id, breaking mode selection and session history restore for any agent with a custom display name.Fixed by wrapping both
defaultAgent()call sites withInstance.provide({ directory, fn })and switching mode construction to use canonical ids. New ACP tests cover default display-name resolution and prompt agent-id forwarding.How did you verify your code works?
npm run typecheckpasses inpackages/opencode,packages/app, andpackages/sdk/js.local.tsx(agent pick helpers, session state sync) and ACP mode resolution.plan_exit→ agent dropdown switches to build agent; IntelliJ ACP init withdefault_agent: "Pulse"no longer throws.Screenshots / recordings
Not a visual change.
Checklist