fix(run-events): tool results carry parentMessageId like tool call starts - #4492
kojiwakayama wants to merge 2 commits into
Conversation
…arts (#4485) The conversation run event encoder named the assistant message on TOOL_CALL_START but not on TOOL_CALL_RESULT, so the API recovered a result's turn from the synthetic `<assistantMessageId>:tool:<toolCallId>` message id at ingest. State it explicitly instead: the tool-result payload schema gains an optional non-empty `parentMessageId`, and all four result branches (tool-input-error, tool-output-available, tool-output-error, tool-output-denied) set it to the active message id when one is open. The synthetic messageId is unchanged. The native run events contract fixture has no TOOL_CALL_RESULT sample, so it and its pinned hash are unchanged. Claude-Session: https://claude.ai/code/session_01CqY82FYm9aUkyawWmh4T9n
|
You have reached your Codex usage limits for security reviews. Please try again later. |
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
@codex review |
|
Warning Review limit reachedNext included review available in 43 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (5)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📦 Client bundle boundary
A server module in a client graph aborts hydration in the browser. New leaks fail CI; known leaks are tracked in |
Review: 92/100 — solid, minimal, well-tested fixSummary: Small, focused change that mirrors an existing pattern ( Strengths
Minor / non-blocking
Given the change is a narrow, additive, well-tested consistency fix with no behavioral risk to existing consumers, this is close to a model small PR. Nothing here blocks merge; the two notes above are just things to confirm, not required changes. Generated by Claude Code |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: feb3ebbd46
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
… reference getToolCallResultPayloadSchema is public, so its JSDoc and the generated API reference now say what `parentMessageId` means, matching the tool call start entry (codex review on #4492). Claude-Session: https://claude.ai/code/session_01CqY82FYm9aUkyawWmh4T9n
|
You have reached your Codex usage limits for security reviews. Please try again later. |
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
@codex review |
|
Codex Review: Didn't find any major issues. Nice work! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
|
Replaced by #4494, same change as a single commit. |



Why
The conversation run event encoder already names the assistant message on
TOOL_CALL_START(parentMessageId). It did not do the same onTOOL_CALL_RESULT, so the API had to work out a tool result's turn from the made-up message id<assistantMessageId>:tool:<toolCallId>when it ingests the event. Recovering it that way is a stopgap. The encoder should state the parent directly, the same way it does for starts.What changed
getToolCallResultPayloadSchema(src/run-events/payload.ts) now has an optionalparentMessageIdfield. It must be a non-empty string, the same ruleTOOL_CALL_STARTuses.ConversationRunEventEncoder(src/agent/conversation/run-events.ts) setsparentMessageIdto the active assistant message id on all four places that emit a tool result:tool-input-error,tool-output-available,tool-output-errorandtool-output-denied. When no message is open, the key is left out, which matchesTOOL_CALL_START.getToolCallResultPayloadSchemaand the generateddocs/api-reference/veryfront/run-events.mdnow describeparentMessageId.messageIdis unchanged, because consumers and the API's ingest-time recovery depend on its format.Contract fixture
No change.
tests/fixtures/contracts/native-run-events.jsononly covers the native frame types (for tool calls, that isTOOL_CALL_STATUS_CHANGED) and has noTOOL_CALL_RESULTsample. The fixture and its SHA-256 hash stay as they are, so veryfront-api needs no companion fixture PR. The API's typedTOOL_CALL_RESULTschema on its main branch already accepts an optionalparentMessageId.Tests
src/agent/conversation/run-events.test.ts: for each of the four branches, one test checks thatparentMessageIdequals the active message id inside an open message, and another checks that the key is missing when no message is open. Both tests also pin the made-upmessageId. These failed before the change and pass after it. The existing exact-shape test now includes the new key.src/run-events/payload.test.ts: the schema accepts a stringparentMessageIdand rejects a number or an empty string. This failed before the change, because the passthrough schema let a number through.Out of scope
lifecycle-run-event-adapter.tsbuilds its own tool records and uses a different shape:messageIdon starts and no parent on results. This PR leaves it unchanged; any change there is a separate piece of work.https://claude.ai/code/session_01CqY82FYm9aUkyawWmh4T9n