refactor(schema): remove recent from compaction messages and events by rekram1-node · Pull Request #57203 · anomalyco/opencode · GitHub
Skip to content

refactor(schema): remove recent from compaction messages and events - #57203

Merged
rekram1-node merged 4 commits into
v2.1from
remove-compaction-recent
Oct 20, 2026
Merged

rekram1-node merged 4 commits into
v2.1from
remove-compaction-recent

Conversation

@rekram1-node

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

Copy link
Copy Markdown
Collaborator

Problem

Since #56954, summary compactions reference their kept messages with metadata.firstKeptMessageID and always write recent: "". The field itself was still part of compaction messages and the session.compaction.started / .ended events, so every API reader, client, and plugin saw an empty string that only meant something for compactions saved before that change.

Change

recent is removed from the public contract: schema, OpenAPI, generated clients, plugins.

 CompactionRunning   { status: "running", reason, summary,
-                      recent }
 CompactionCompleted { status: "completed", reason, model?, native?, summary,
-                      recent,
                       providerContext?, cost?, tokens? }
 session.compaction.started { reason, inputID?
-                             recent }
 session.compaction.ended   { reason, model?, native?, providerContext?, text,
-                             recent,
                              cost?, tokens? }

The kept text that replay needs now lives in the compaction's free-form metadata:

new compaction    metadata.firstKeptMessageID ──► history rebuilds the text into metadata.recent (not stored)
old compaction    stored recent: "text"       ──► read as metadata.recent
                                                     │
                                                     ▼
                                        replay: <recent-context>…</recent-context>
  • SessionRecentText.kept(message) is the single reader, used by replay and compaction.
  • Where the text shows up: /session/:id/context and request hooks see the rebuilt text as metadata.recent, as they saw it in recent before. The message list shows it only for old compactions. Message metadata is never sent to providers.
  • Hooks: a compaction hook's free-form metadata is stored as-is, so a hook that sets metadata.recent without a kept-message reference has that text replayed.
  • The V1 importer writes the V1 kept tail to metadata.recent instead of recent.

Old data (@opencode/schema/session-legacy)

  • Messages: a stored recent with text moves into metadata.recent on read; an empty one is dropped. This applies to stored rows and imported exports.
  • Events: recent is dropped from stored compaction.started / .ended events on read. Nothing reads it: messages, not events, are what replay uses. Replay idempotency compares stored events in their upgraded shape, so old events still match.

Downgrades

Nothing writes recent for older versions; this follows the existing pattern of reading old shapes and never writing them. Versions before v2.1 require recent on compaction messages, so they cannot load a session that has a compaction created by this version. Sessions compacted only before the upgrade are unaffected.

Older clients

An older Effect client, or a pinned plugin or SDK built on it, requires recent when it decodes compaction messages and events. It fails against this server, as with any removed required field. Newer clients against an older server ignore the extra field.

Out of scope

  • Native compaction's shape (providerContext, the native written by the summary call but never read).

Verification

  • New tests:

    • packages/schema/test/session-legacy.test.ts: old recent text moves into metadata, and empty values and event fields are dropped.
    • packages/core/test/session-compaction.test.ts "summaries written before kept-message references keep their stored recent text": inserts a raw old-shape row. It fails without the legacy read.
    • packages/core/test/session-projector.test.ts and session-runner.test.ts: stored compaction rows and events have no recent.
    • packages/core/test/v1-migration.test.ts: the V1 kept tail lands in metadata.recent, with no recent.
    • packages/core/test/bus.test.ts "replays compaction events stored before v2.1 with recent, reading them without it": an old event with kept text replays idempotently and reads back without recent.
    • packages/server/test/session-import.test.ts: an old export's recent text comes back as metadata.recent.
  • Tests:

    Package Command Result
    core bun test 6643 pass, 8 fail (shell and preload tests, also failing on v2.1)
    schema bun test 86 pass
    cli bun test 331 pass
    server bun test 85 pass
    client bun test 229 pass
    tui bun test test/cli/tui/data.test.tsx test/cli/tui/session-rows.test.ts test/mini/stream-v2.transport.test.ts 144 pass
    session-ui bun test 251 pass, 21 fail (same count on v2.1)
  • Typecheck: bun typecheck passes in schema, protocol, core, client, cli, server, sdk, tui, plugin, app, and session-ui, apart from errors already on v2.1.

  • Generated files: check:generated passes in packages/protocol, packages/client, and services/www.

@rekram1-node
rekram1-node merged commit 0a73abd into v2.1 Oct 20, 2026
17 checks passed
@rekram1-node
rekram1-node deleted the remove-compaction-recent branch October 20, 2026 00:27
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