refactor: v2.1 minor breaking changes by rekram1-node · Pull Request #57260 · anomalyco/opencode · GitHub
Skip to content

refactor: v2.1 minor breaking changes - #57260

Merged
rekram1-node merged 13 commits into
devfrom
v2.1
Oct 20, 2026
Merged

rekram1-node merged 13 commits into
devfrom
v2.1

Conversation

@rekram1-node

@rekram1-node rekram1-node commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

v2.1 minor breaking changes

Small, intentional changes to make the public API's names and data shapes more consistent. SDK consumers need to use the new fields. Existing stored data and old session imports remain readable through boundary decoders, without database migrations.

1. One name for provider replay data: native

Provider-owned data was called state, providerState or resultState depending on the message or event. These are now consistently named native, distinct from a tool's execution state and UI metadata.

Surface Before After
Text/reasoning parts state native
Assistant, tool and compaction messages providerState native
Text/reasoning events and session.tool.called state native
Step terminal events and session.compaction.ended providerState native
session.tool.success / session.tool.failed resultState native

The exported schema name SessionMessage.ProviderState also becomes SessionMessage.Native.

2. Tool call and result replay data share one tool.native

 tool
-  providerState?        # call data
-  providerResultState?  # result data
+  native?               # call + result data, shallow-merged
   state                 # execution status and readable output: unchanged

Success and failure events merge their native into the tool's existing native. Missing result data preserves call data; result values win on duplicate keys. There is no state.native.

Replay passes the whole merged blob to the protocol, which reads the fields it needs:

Part Gets native when
Tool call same provider and model
Provider-run result same provider
Local result same provider and model, and the step didn't fail

This avoids a second nested native, a one-off resultNative field, or a tool-specific { call, result } envelope. Protocol implementations must use distinct keys for distinct call/result values. Current Anthropic hosted calls carry no replay data; Responses hosted calls and results carry the same itemId.

Old stored/imported providerResultState is merged into tool.native when read. Tool status and readable result content stay in state.

3. Key credential form answers use metadata

 Credential.Key
   type: "key"
   key
   metadata?        # now also holds setup-form answers
-  configuration?   # setup-form answers (Form.Answer)

Credential.Key.configuration is removed. Setup-form answers now go in the existing metadata field, rather than keeping two bags of provider configuration. Stored credentials and auth import accept the old shape: a legacy configuration is merged into metadata, and the configuration value wins when both have the same key. Public credential writes must use metadata.

4. Compactions reference kept messages instead of storing recent

 summary compaction
-  recent: "[User]: ... [Assistant]: ..."
+  metadata: { keepID: "msg_..." }

keepID identifies the first message retained verbatim beside the summary. History reconstructs the text from that message through the compaction boundary, avoiding a duplicated, flattened copy in storage. Forks remap the reference to their copied messages; compaction hooks can override it through metadata.

The recent field is removed from compaction messages and the started/ended events. Old stored recent text remains readable through the compatibility decoder. keepID is the only name for the new reference—there is no alias for its unreleased earlier name.

5. Remove unused session.compacted

The unused transitional event is removed from the public event surface. Current compaction lifecycle events remain.

6. Provider compaction windows live in native.messages

 completed compaction / session.compaction.ended
-  native?           # summary call's step data, never read
-  providerContext?  { version, provenance, messages }
+  native?           { messages, ... }   # `messages` is the window replayed instead of `summary`
  • A provider ("native") compaction replays its window only when the compaction's model has the current provider ID and model ID. That's the same rule assistant parts use. Otherwise history sends the original messages.
  • Provenance (route, protocol, endpoint hash) and the request-hook route guards are removed. As a result:
    • a request hook that rewrites the base URL no longer blocks native compaction or replay;
    • the same model behind a changed endpoint still replays its window.
  • Summary compactions no longer store the summary call's provider data in native. A compaction hook's result.native is still stored, and its native.messages is treated as a replay window.
  • Old providerContext rows and events are converted to native.messages when read, including the media format from before 2.0.15.

Other visible changes

  • Kept text from compactions saved before v2.1, and from V1 imports, is exposed as metadata.recent, which is where replay reads it. New compactions store only metadata.keepID.
  • Versions before v2.1 can't load a session that has a compaction created by v2.1. Downgrades aren't supported.
  • Older Effect SDK clients fail to decode compaction messages and events from a v2.1 server. Clients must match the server version.

Integration

Includes #56640, #56934, #56999, #56954, #57203, #57167, #57241 and #57286. Latest dev is merged into v2.1; the compaction conflict resolution retains both prompt-cache reuse and kept-message references. Generated client and OpenAPI files are updated.

The hosted-tool provider-switch fix remains separate in #57256. No release/version bump is included.

Verification

Run on v2.1 after #57241:

Check Result
Root bun run check 34/34 tasks pass
Core: native, native-compaction, runner, runner-message, compaction, bus, projector, V1 migration 387 pass
packages/schema bun test 89 pass
packages/server bun test 87 pass, 1 skipped
check:generated in protocol, client, www clean

Additional verification for #57286: root checks, changed-file lint and generated-file checks pass. Live Anthropic server-side web search, web fetch and failed web fetch all replayed successfully after restarting the CLI. Stored data uses only tool.native; captured result blocks matched the stored payloads, including encrypted search content.

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found nothing that blocks this. I read the legacy upgraders, the kept-message rebuild in history.ts, the fork ID remap, and the import and redaction paths. A quick script confirmed that old credentials, assistant messages, compactions and events are upgraded on read. The closest tests all pass (core 122, schema 89, server session-import 5, cli auth/import-export 18), and type checks are clean for core, cli and schema.

Public API: not backwards compatible for current consumers. Stored data and old export files are still upgraded on read.

  • Message parts:
    • Text and reasoning: state → native.
    • Tool: providerState → native, and providerResultState is removed; its data now lives in state.native on completed or errored tools.
    • Assistant message: providerState → native.
    • Compaction message: providerState → native, and recent is removed in favour of metadata.firstKeptMessageID.
    • Type Session.Message.ProviderState → Session.Message.Native.
  • Events:
    • session.text.ended, session.reasoning.started/ended, session.tool.called: state → native.
    • session.step.ended/failed: providerState → native.
    • session.tool.success/failed: resultState → native.
    • session.compaction.started/ended: recent removed, and ended renames providerState → native.
    • session.compacted is removed.
  • Credentials: Credential.Key.configuration is removed; its answers merge into metadata.
  • Plugin: SessionCompactionResult.providerState → native.
  • HTTP: experimental.session.import now also accepts transcripts exported before v2.1.

SDK clients, plugins and event consumers that read the old names will need to switch to native and metadata.

@rekram1-node rekram1-node changed the title refactor: unify provider data and compaction schemas for v2.1 refactor: v2.1 minor breaking changes Oct 20, 2026
@rekram1-node
rekram1-node merged commit acdcdb8 into dev Oct 20, 2026
22 checks passed
@rekram1-node
rekram1-node deleted the v2.1 branch October 20, 2026 05:42
vleonbonnet added a commit to vleonbonnet/opencode that referenced this pull request Oct 20, 2026
Upstream's 97 commits since the port include v2.1's breaking changes (anomalyco#57260) and a shared Code Mode runtime per tool inventory (anomalyco#57172).

- Code Mode fetch keeps asking for webfetch permission as the calling execute: with the runtime shared, the fetch global returns an Effect that reaches its execution's check through the runtime's per-execution Run service. The interpreter now runs a global's returned Effect in the execution's context, inside the extension hooks, and interrupts it when the execution ends, which withdraws a pending permission request and aborts the request.
- The tool snapshot keeps exposure across selectable agents and delegation ceilings, now also deciding upstream's cached catalog.
- The cache ledger and preflight follow v2.1's renames: native data (`state`, `providerState`) is `native`, and history is bounded by the model reference, as the runner does, now that the provider context module is gone.
- Summarized thinking still wraps the request after model hooks; the provider-context route check went with that module.
- Replayed dropped thinking and both sides' new event handlers and tests are kept; upstream's encoding test now expects permission reasons.
- Generated client types and OpenAPI documents are regenerated.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant