Skip to content

refactor(core): avoid redundant payload decoding in session inbox and prompt - #57946

Merged
rekram1-node merged 1 commit into
devfrom
session-inbox-prompt-decode
Oct 22, 2026
Merged

rekram1-node merged 1 commit into
devfrom
session-inbox-prompt-decode

Conversation

@rekram1-node

Copy link
Copy Markdown
Contributor

Problem

Several paths in packages/core/src/session/ redundantly validate or decode values that are already validated at the boundary or decoded in a downstream projector:

  • SessionInbox.publish calls fromRow(row) to read id, type, and delivery before publishing SessionEvent.InboxDelivered, even though those fields are top-level columns on SessionInboxTable and projectDelivered already decodes the deleted row via fromRow(deleted).
  • SessionInbox.fromRow and SessionInbox.admitCompaction re-wrap already-typed row.id, row.session_id, and input.delivery values in .make(...) before passing them to schema constructors that validate them again.
  • SessionPrompt.prepare spreads Prompt.make(...) into SessionInbox.UserPayload.make(...), validating all prompt fields and base64 attachments twice, and re-wraps event.delivery with SessionInbox.Delivery.make(...).
  • SessionMessageUpdater.update rebuilds Schema.decodeUnknownSync(Schema.Array(SessionMessage.AssistantContent)) inside update() on every session.message.content.updated event.

Change

Pass already-typed columns and fields directly to the owning schema constructors, avoid decoding inbox payloads prior to InboxDelivered projection, and hoist the assistant content array decoder to module scope.

 SessionPrompt.prepare
-  Prompt.make({ text, agents, files, skills })
   SessionInbox.UserPayload.make({ text, agents, files, skills, metadata })
-  SessionInbox.Delivery.make(event.delivery)

 SessionInbox.promote -> publish(rows)
-  fromRow(row)                        # decoded payload before publish
+  guard row.type in {move, user, synthetic}
   bus.publish(InboxDelivered, { sessionID, inboxID: row.id })
     projectDelivered
       fromRow(deleted)                # single payload decode on consumption

 SessionMessageUpdater.update
   "session.message.content.updated"
-    Schema.decodeUnknownSync(Schema.Array(AssistantContent))(content)
+    decodeAssistantContent(content)   # hoisted to module scope

Out of scope

  • Schema definitions for Prompt and SessionInbox in @opencode/schema.

@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.

No problems found; the refactor keeps the same behaviour. Effect make already validates its input, so dropping the nested Prompt.make/Delivery.make/ID make calls still validates each value once. The type check in publish matches the old fromRow plus compaction rejection, and a malformed payload now fails in projectDelivered with the same defect result. Hoisting decodeAssistantContent is safe.

Checked with the session tests in packages/core (prompt, move, compact, skill, execution, runner, owned: 352 pass, 0 fail) and bun run typecheck, which passed.

Public API unchanged (internal packages/core session code only).

@rekram1-node
rekram1-node merged commit 7012c9d into dev Oct 22, 2026
13 checks passed
@rekram1-node
rekram1-node deleted the session-inbox-prompt-decode branch October 22, 2026 01:00
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