feat(core): emit more turn items instead of legacy begin/end events#30283
Open
owenlin0 wants to merge 1 commit into
Open
feat(core): emit more turn items instead of legacy begin/end events#30283owenlin0 wants to merge 1 commit into
owenlin0 wants to merge 1 commit into
Conversation
35c6ad7 to
ee54284
Compare
d581108 to
e9d6a09
Compare
883f6f7 to
2d0b556
Compare
acec956 to
f691f27
Compare
owenlin0
added a commit
that referenced
this pull request
Jun 26, 2026
Contributor
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f691f279c3
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
4304fa3 to
d2d5882
Compare
9fd1ae2 to
9f2d003
Compare
owenlin0
added a commit
that referenced
this pull request
Jun 26, 2026
d3204c7 to
3041d21
Compare
owenlin0
added a commit
that referenced
this pull request
Jun 26, 2026
## Description
This PR adds canonical core `TurnItem` shapes for command execution,
dynamic tool calls, collab agent tool calls, and sub-agent activity, to
be stored in the rollout file soon.
It also teaches app-server protocol / `ThreadHistoryBuilder` how to
render those items, and adds the small legacy fanout helpers needed for
existing event-based consumers. No core producer or rollout persistence
behavior changes here, that will be done in a followup.
## Making ThreadHistoryBuilder stateless
This is the first PR in a stack to make `ThreadHistoryBuilder` stateless
enough that we can materialize app-server `ThreadItem`s from only a
given slice of `RolloutItem` history, without ever needing to replay the
whole thread from the beginning.
The persisted legacy `RolloutItem::EventMsg` records are mostly shaped
like live UI events, not like materialized `ThreadItem`s. They work if
we replay the full rollout in order, but they often do not contain
enough stable identity or complete item state to project an arbitrary
suffix on its own.
A few examples:
- `UserMessageEvent` and `AgentMessageEvent` have content, but
historically do not carry the persisted app-server item ID that should
become the SQLite primary key.
- `AgentReasoningEvent` and `AgentReasoningRawContentEvent` are
fragments. `ThreadHistoryBuilder` currently merges them into the last
reasoning item, which means a slice starting in the middle of reasoning
cannot know whether to append to an earlier item or create a new one.
- `WebSearchEndEvent`, `McpToolCallEndEvent`, collab end events, and
similar legacy events can often render a final-looking item, but they
usually rely on prior replay state to know which turn owns the item.
- Begin/end legacy events are partial views of one logical item. The
builder correlates them by `call_id` and mutates prior state to
synthesize the final `ThreadItem`.
That is the problem this direction fixes. A persisted canonical
lifecycle record looks much closer to the read model we actually want
later:
```rust
ItemCompletedEvent {
turn_id,
item: TurnItem { id, ...full snapshot... },
completed_at_ms,
}
```
Once rollout has explicit `turn_id`, stable `item.id`, and a canonical
completed item snapshot, the future SQLite projector can reduce only the
new rollout suffix and upsert the affected `thread_items` rows. It no
longer needs to synthesize `item-N`, infer item ownership from the
active turn, or replay earlier events just to reconstruct the current
item snapshot.
## What changed
- Added core `TurnItem` variants and item structs for command execution,
dynamic tool calls, collab agent tool calls, and sub-agent activity.
- Added conversions from those canonical items back into the legacy
event shapes where current consumers still need them.
- Added app-server v2 `ThreadItem` conversion for the new core item
variants.
- Taught `ThreadHistoryBuilder` and rollout persistence metrics to
recognize the new item variants.
## Follow-up
The next PR #30283 switches the live
core producers for these item families onto canonical `ItemStarted` /
`ItemCompleted` events.
owenlin0
added a commit
that referenced
this pull request
Jun 26, 2026
3a6d87b to
0c3b191
Compare
This comment was marked as low quality.
This comment was marked as low quality.
This was referenced Jun 27, 2026
owenlin0
added a commit
that referenced
this pull request
Jul 2, 2026
10f74cd to
5de3e05
Compare
5de3e05 to
4f01798
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack
TurnItemlifecycle ← this PRDescription
This PR makes canonical
TurnItemlifecycle the live source of truth for these items:These are new TurnItems added in #30282, which only previously had the legacy-style
EventMsg::*Begin/Endevents. This PR switches core to emit these asItemStarted/ItemCompleted+TurnIteminstead, and app-server v2 handles those canonical item events directly.Core still fans canonical item events back out into the old legacy
EventMsgforms where we still need them for legacy rollout persistence, rollout trace, and raw core event consumers. App-server ignores that compatibility fanout so v2 clients do not get duplicate item notifications.Rollout persistence behavior is unchanged in this PR.
Legacy conversion code lives in
protocol/src/legacy_events.rsfrom #30956; this PR adds the projections for the migrated item families there.Why
This is the second PR in the stack for making ThreadHistoryBuilder stateless, which relies on using
TurnItem. First PR is at: #30282Follow-up
The next PR #30188 actually writes
TurnItemto rollout files when usingthread.history_mode = "paginated".