refactor(schema): rename provider replay data to native by rekram1-node · Pull Request #56640 · anomalyco/opencode · GitHub
Skip to content

refactor(schema): rename provider replay data to native - #56640

Merged
rekram1-node merged 6 commits into
v2.1from
native-state
Oct 18, 2026
Merged

rekram1-node merged 6 commits into
v2.1from
native-state

Conversation

@rekram1-node

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

Copy link
Copy Markdown
Collaborator

Problem

Provider replay data appeared in messages and events under the names state and providerState, typed as ProviderState. On tool parts, state already means the tool's lifecycle status (streaming, running, completed, error), while on text and reasoning parts the same state key held provider data.

Change

Provider replay data is now native, typed as SessionMessage.Native.

 Session.Message.Assistant
-  providerState            # step finish diagnostics
+  native
   content[]
     text
-      state
+      native
     reasoning
-      state
+      native
     tool
-      providerState
+      native
       providerResultState  # unchanged
       state                # tool status, unchanged

 Session.Message.Compaction (completed)
-  providerState
+  native
Event Before After
session.text.ended, session.reasoning.started, session.reasoning.ended, session.tool.called state native
session.step.ended, session.step.failed, session.compaction.ended providerState native
session.tool.success, session.tool.failed resultState unchanged

Durable event versions are unchanged. The result-side fields keep their names; only their type reference changes from ProviderState to Native. The plugin SessionCompactionResult.providerState is now native, and the plugin docs are updated.

Existing data

There is no database migration. Stored events, projected messages, and exported sessions keep whatever shape they were written in. @opencode/schema/session-legacy upgrades old field names before decoding, and each source has a single entry point:

event row            ──► Bus decodeStoredData (log reads, replay)           ──► SessionLegacy.event
                         Bus replay idempotency check (compares upgraded stored row)
session_message row  ──► SessionHistory.decodeMessageRow(Sync)              ──► SessionLegacy.message
                         (store, projector, revert, inbox)
import request       ──► POST /api/experimental/session/import payload schema ──► SessionLegacy.messages
  • When a payload carries both names, the current name wins.
  • A tool part's own state (its status) is never touched.
  • When the projector updates a legacy message row, it writes the row back in the current shape.
  • The V1 importer now writes native on text, reasoning, and tool parts.
  • POST /api/experimental/session/import keeps messages as plain JSON on the wire, so OpenAPI and the promise client accept any export file. The payload schema upgrades transcripts from earlier releases, then decodes them against the current message schema. Invalid messages fail through the shared schema-error middleware as a 400 InvalidRequestError with kind: "Payload". The Effect client's import input is still typed SessionMessage.Info, so an export round-trips. The handler is unchanged. The CLI and the app send export files unchanged.

The CLI --format json output keeps its V1-style providerCall: { executed, state } and providerResult: { executed, state } keys; only the source of the values changed.

Out of scope

  • Result-side provider data: providerResultState and resultState are left for a follow-up.

Verification

  • packages/schema/test/session-legacy.test.ts checks that:

    • every renamed event type, upgraded and then decoded through its durable definition, comes out with native;
    • session.message.content.updated parts are upgraded and the tool status is left alone;
    • assistant and compaction messages are upgraded;
    • exported sessions are upgraded;
    • current and unrelated payloads pass through unchanged;
    • when both names are present, the current one wins.
  • packages/core/test/session-projector.test.ts "reads and replays native data stored under its pre-v2.1 names":

    • inserts legacy session_message and event rows, then checks SessionStore.messages and Bus.log;
    • re-replays the stored legacy events and checks the replay stays idempotent;
    • replays a new legacy session.step.ended event, then checks it is stored as native and projected onto the legacy row;
    • checks the row was rewritten in the current shape with native intact.

    The replay assertion fails with Replay diverged without the idempotency fix.

  • packages/server/test/session-import.test.ts:

    • "upgrades native data in transcripts exported before v2.1" covers text, reasoning, tool, assistant, compaction, and a location-switched message, and fails without the payload-schema upgrade;
    • "rejects an invalid imported message without creating the session" checks the 400 response.
  • packages/cli/test/import-export.test.ts "import sends the file unchanged to the resolved location": legacy fields reach the server intact.

  • bun typecheck passes in schema, protocol, core, client, cli, tui, server, plugin, sdk, session-ui, and app, apart from errors that were already on v2.1 in tui/dialog-workspaces.tsx, tui/prompt/autocomplete.tsx, app/runtime/server/persistence.ts, and app/settings/model.tsx.

  • Tests:

    Package Command Result
    core bun test test/session* test/v1-migration.test.ts test/bus*.test.ts test/database-migration.test.ts 761 pass
    schema bun test 81 pass
    client bun test 229 pass
    server bun test 85 pass
    cli bun test test/run test/acp test/import-export.test.ts 116 pass
    tui bun test test/cli/tui/data.test.tsx test/mini test/app-lifecycle.test.tsx 497 pass
    app test:unit 760 pass
  • check:generated passes in packages/protocol, packages/client, and services/www.

@rekram1-node
rekram1-node merged commit e1d8a45 into v2.1 Oct 18, 2026
21 checks passed
@rekram1-node
rekram1-node deleted the native-state branch October 18, 2026 17:36
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