Repository navigation
refactor(tools): unify tool APIs and result handling - #38367
Merged
Merged
Conversation
kitlangton
force-pushed
the
canonical-tool-output
branch
from
July 23, 2026 03:32
977a1f0 to
ed35983
Compare
kitlangton
force-pushed
the
canonical-tool-output
branch
from
July 23, 2026 16:59
2db0991 to
e22395b
Compare
Materializing every assistant row at once was measured at ~4.9GB RSS and 105s on an 8.8GB production database. Keyset-paginated batches of 1000 inside the same transaction cut this to 843MB and 37s.
edit and patch never declared toMetadata, so the TUI diff renderer had nothing to draw for new calls, and the row migration dropped historical structured payloads (including subagent session joins). Both tools now emit { files }, migrated terminal states carry old structured objects as canonical metadata, and undecodable rows are skipped instead of failing the migration on every startup.
…tches Hosted provider result payloads are provider-format state, not model state. Gating providerResultState reuse on exact model identity broke Anthropic hosted replay after a model switch within the provider; the fallback result value is derived display content, not the typed block payload. Result-state reuse now requires only provider identity.
An untyped JS plugin after-hook could clear failed-call content to an empty array or set non-JSON metadata, producing an unencodable durable event that wedged the tool part in running. The JS boundary now revalidates through one shared Tool.jsonMetadata guard, which also applies the byte bound to failure-snapshot metadata that only the success path enforced before. Consolidates the duplicated stringify and metadata-validation helpers into tool.ts.
Read's canonical model content is the JSON page envelope, so ACP clients and text displays showed raw JSON instead of file text. toolOutputText and the ACP tool update now unwrap the envelope back to the clean content, replacing the dead metadata-based extraction.
Review cleanups: dead imports, contentFrom happy-path flattening, codemodeTool shadow rename, call-site param naming for toModelOutput/toMetadata, spec Context fields matching the code, progress-metadata leniency comment, and PLAN.md marked implemented.
kitlangton
force-pushed
the
canonical-tool-output
branch
from
July 23, 2026 20:05
664407f to
34ae3e3
Compare
kitlangton
enabled auto-merge (squash)
July 23, 2026 20:56
3 of 6 tasks
jinhuang712
pushed a commit
to jinhuang712/opencode
that referenced
this pull request
Sep 26, 2026
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.
What
Unifies the V2 tool stack from authored tools through provider schemas, local execution, hooks, clients, and persisted terminal results.
The canonical vocabulary is now:
Tool.Toolfor an authored tool andTool.Anyfor its erased form.toolfor runtime values, includingregistration.tool.executeas the sole local execution verb.LLM.ToolDefinitionfor the inert model-facing schema.A terminal response separates schema-validated machine
output, model-visiblecontent, and compact UImetadata. One registry boundary validates and bounds those values, runs hooks, and returns a canonicalcompleted | errorresult consumed by Code Mode, MCP, plugins, the runner, CLI, ACP, TUI, simulation, and durable session state.Shell follows the same split: progress publishes compact metadata such as
shellID; paginated shell output remains outside durable progress events; terminal completion or failure owns model content.How
Tool.make({ description, input, output?, execute }),Tool.Tool, andTool.Any. The standalone CLI exposes the same public tool facade to both plugin runtimes.content,metadata, and errors in V2 session messages and events. The migration rewrites projectedsession_messagerows only and leaves legacy durable events untouched.toolConfig.toolswhile omitting unsupportedtoolChoice: none, preserving thetools -> system -> messagesprompt-cache prefix.Scope
session.tool.success.1andsession.tool.failed.1durable rows are intentionally unchanged. Cleanup before V2 stable is tracked in V2: remove V1 event surface after cutover (tracking) #35054 (comment).nonetool choice; this PR omits only that unsupported field rather than removing tool definitions.Testing
tsc -p tsconfig.build.json.Flow