Skip to content

feat(core): bound tool and admitted event payloads via session blobs#37559

Open
armancharan wants to merge 17 commits into
anomalyco:v2from
armancharan:fix/bound-event-projections
Open

feat(core): bound tool and admitted event payloads via session blobs#37559
armancharan wants to merge 17 commits into
anomalyco:v2from
armancharan:fix/bound-event-projections

Conversation

@armancharan

@armancharan armancharan commented Jul 17, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #36444

#36444

Parent: #36441

✧ raised · ○ in review · ● approved · ✓ merged

#36441 epic: scope streams + bound payloads

Merge in order:
v2
└ ○ #37486 location interest
   └ ○ #37487 session interest + fan-out bench
      └ ○ #37585 stream ownership / diagnostics
         └ ○ #37586 reconnect herd

Siblings under the epic (not git parents of the stack tip):
└ ○ #37559 session blobs + payloadHash ← this PR
└ ○ #37570 ensure-on-first-failure → feeds #37586

Adjacent: #36524 (image dedupe only — complementary, not a substitute).

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Durable session.tool.success / progress and session.input.admitted events were carrying multi-megabyte bodies (tool output, inline base64 attachments). That multiplies encode/SSE/decode cost across every subscriber.

This PR makes those events bounded projections:

  • Full tool settlement and admitted attachment bytes live in session-scoped session_tool_payload (same lifetime as the session).
  • Events carry payloadHash plus small text previews only.
  • Encoded durable event data budget is 256 KiB UTF-8; over-budget settlement fails (no silent truncate).
  • Projectors hydrate session_message / session_pending from the blob so replay stays complete.
  • Clients that need the body use existing message/pending fetch APIs; TUI refetches when payloadHash is present.
  • ToolOutputStore.bound media rules are unchanged (provider channel only — not the durable event sidecar).

How did you verify your code works?

  • packages/core test/tool-payload.test.ts — multi-MB blob round-trip; thin event under budget; oversize thin fails
  • packages/core test/session-runner-tool-events.test.ts — thin success omits base64; over-budget → Failed
  • packages/core test/session-pending-attachments.test.ts — large admit thin + hydrate; text-only omits hash
  • packages/core test/session-tool-progress.test.ts — projector hydrates thin tool.success into session_message
  • packages/tui test/cli/tui/payload-hash.test.tsx — TUI refetch on payloadHash (message + pending); no refetch without hash
  • typecheck on push

Acceptance → test

  • Budget / fail-not-truncate → tool-payload + over-budget thin success fails settlement…
  • Multi-MB tool → thin event, full via message → hydrates thin tool success… + tool.success with payloadHash refetches…
  • Large attachment → thin admit, full via pending → admits a large attachment… + input.admitted with payloadHash refetches pending
  • Uninterested clients see thin frame only → thin event assertions (no mega/base64 on durable data)
  • TUI correct after thin success/admit → payload-hash.test.tsx

Screenshots / recordings

N/A — not a UI layout change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Persist large tool settlement and prompt attachment bodies in
session_tool_payload, publish thin durable events with payloadHash, and
hydrate projectors plus TUI fetches so SSE and the event log stay within
a 256 KiB event-data budget without changing ToolOutputStore media rules.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label Jul 17, 2026
armancharan and others added 6 commits July 18, 2026 07:11
Drop boolean/as escape hatches; assert then publish, recover OverBudgetError in-band.

Co-authored-by: Cursor <cursoragent@cursor.com>
Encode via Schema instead of casts, blob admits only when attachments
carry bytes, treat over-budget progress as a defect, and tighten
projector/SQL typing.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Cover projector rebuild of thin tool.success from session blobs, and
publisher fail-not-truncate when thin event data still exceeds budget.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use one local persistToolPayload for publisher settlement and progress.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread packages/core/test/session-runner-tool-events.test.ts Outdated
Use Schema.decodeUnknownSync for tool success and admitted event data.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Jul 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

optionalKey schemas reject explicit undefined; keep publishes and
Schema.decodeUnknownSync tests aligned.

Co-authored-by: Cursor <cursoragent@cursor.com>
@armancharan
armancharan marked this pull request as ready for review July 17, 2026 21:50
Cover thin tool.success and input.admitted refetching full bodies, and
assert events without payloadHash do not hit those endpoints.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread packages/core/test/session-runner-tool-events.test.ts Outdated
armancharan and others added 7 commits July 18, 2026 09:26
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
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