feat(opencode): native Anthropic advisor tool - #48438
Open
alohaninja wants to merge 5 commits into
Open
Conversation
Add `agent.<name>.advisor` (`{ model, maxUses } | false`) to the shared
schema, the V1/V2 agent configs, markdown agent frontmatter, and the V1
migration. Partial objects merge across config layers and are validated
once at request time. The native V2 session runner rejects an enabled
advisor with UnsupportedApiError instead of silently dropping it.
Register Anthropic's server-side advisor tool (`advisor_20260301`) for agents that opt in, on the direct Messages API with API-key auth only. Consultations arrive inside the executor's own response stream; OpenCode never issues a second request for the advice. - Persist the result on the originating tool part and a response-order ledger on the receiving step-finish so later turns replay the native blocks at their original position. Ledger references survive `Session.fork`; unresolvable references fall back to text. - Resume `pause_turn` automatically, at most three advisor-only resumptions per turn. Pending calls are terminal on cancel, crash, or restart: they are marked abandoned and never resumed, and a resumption request is never retried once its response has started. - Price advisor usage from `usage.iterations` with the advisor model's catalog cost, add it once to step/session cost, and keep it out of the executor's context tokens. Missing pricing surfaces a partial-cost notice. - Replay advice as plain text when the model, route, or credentials can no longer carry the beta, and for export/share (encrypted content is never emitted). Compaction keeps a consultation's call and result together. - Reject `ask` permission, tool-name collisions, unsupported routes, and incomplete settings with explicit errors before anything is sent. Includes a scripted-transport fixture (`test/fixture/advisor-*.ts`) that boots the real server and drives pause, encrypted, error, and cancel scenarios without paid inference, plus a manual smoke harness.
Render only identifier-shaped advisor error codes into replayed history, decode each advisor part once during history conversion, reset the per-step result flag on step start, and name the tier-selection token sum for what it is.
alohaninja
marked this pull request as ready for review
September 11, 2026 13:03
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 #23058
Type of change
What does this PR do?
Adds per-agent opt-in for Anthropic's server-side advisor tool (
advisor_20260301):{ "agent": { "build": { "advisor": { "model": "claude-opus-4-6", "maxUses": 1 } } } }The executor (e.g. Sonnet) can pause mid-turn and ask a stronger model; Anthropic runs that consultation and returns the advice in the same response. OpenCode never sends a second request.
What had to exist for this to work correctly:
metadata.opencodeAdvisor.entries). Message conversion follows that ledger. Fork remaps the part references.pause_turnis resumed in-process, capped at 3 advisor-only resumptions per turn. A pending call is terminal on cancel/crash/restart: marked abandoned, replayed as a text marker, never resumed. A resumption request is not retried once its response starts, because a retry re-runs (and re-bills) the consultation.usage.iterationsand are priced with the advisor model's catalog cost, added once to the step/session, and kept out of the executor's context total. Missing pricing shows a partial-cost notice rather than understating.baseURL,advisor: false), advice is replayed as plain text so the session keeps working. Export and share redact the payload; encrypted content never leaves the DB.permission.advisormust beallow/deny(askcan't pause a server-side call). Incomplete settings error with the agent name before anything is sent. The V2 native runtime rejects it explicitly instead of dropping it.Config, schema, and V2 guard are in
packages/core+packages/schema; everything runtime is inpackages/opencode/src/session. Thechore: generatecommit is only the newadvisorfield in the SDK/client types. Docs: new "Advisor" section inagents.mdx(English only; locale sync is automated).I don't have a live capture of
pause_turnusage accounting — the fixture assumes Anthropic reports the advisor iteration once per response, not cumulatively across a pause/resume. If that's wrong, cost would double-count on paused turns. Flagging rather than guessing.How did you verify your code works?
bun turbo typecheck --force(30/30),check:generated,test:httpapi(208/208),core:test(1114/1114),opencode:test, prettier on all changed files.advisor: false.test/fixture/advisor-server.tsboots the real server with scripted SSE (pause,complete,encrypted,error,cancel) and logs each request'sadvertised/pending/completed+ beta header. Ran every scenario, a restart mid-session, and theadvisor: falsefollow-up through a client on the server API. Procedure intest/fixtures/advisor-smoke/README.md.srvtoolu_…call, plaintext result, advisor cost0.087inside a0.102step (matches Opus list price on the reported iteration tokens), executor context excluded the advisor tokens, restart + follow-up replayed cleanly,advisor: falsefollow-up produced no tool.Screenshots / recordings
No UI changes in this repo; the advisor renders through the existing tool-part path.
Checklist