feat: project turn_id onto folded chat-history entries - #1057
Open
akandola wants to merge 1 commit into
Open
Conversation
The turnId that ties a turn's user+assistant messages together is already persisted on ChatMessage and is the id the live stream stamps on the turn's wire frames (WireFrame.turnId) — per convergence/README.md, precisely so a client resyncing across a turn boundary can match refetched history to a live turn. The history fold (historyToFeed) never projected it onto the FeedFrame / ChatHistoryEntry it emits, so backfilled entries had no per-turn identity. Thread the source ChatMessage.turnId through every folded frame as turn_id (mirroring how ts is already carried), and declare the optional field on both twin types. Strictly additive, client-SDK only — no server, wire, or protocol change. Absent for pre-turn-id transcripts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
What
Project each folded history frame's source
ChatMessage.turnIdonto the feed entry asturn_id. The foldhistoryToFeedcurrently drops it.Why — completing an existing design
convergence/README.md(the resumable-stream design) states the intent already:turnIdis "persisted on the turn's user+assistantChatMessages … so a client resyncing across a turn boundary can match history to a live turn," withsync{resync:true}telling the client to "refetch history."The data is already there —
ChatMessage.turnIdis persisted on both messages of a turn (packages/protocol/src/conversation.ts), and it's the same id the live stream stamps on wire frames (WireFrame.turnId).settleFromHistoryalready aligns a resync against history byturnId. The only gap is that the history fold never projectedturnIdonto theFeedFrame/ChatHistoryEntryit emits, so backfilled entries carried no per-turn identity. This PR closes that gap.Consumer motivation (secondary)
For a client that ingests the live SSE stream and uses REST history as its recovery path: when a sleeping pod makes the resume cursor unserviceable, the server sends
sync{resync:true}and the client refetches history.turn_idon the folded entries is what lets that refetched history be aligned to the turns already received live, instead of guessing.Scope
turnIdon everyChatMessage.FeedFrame(packages/sdk/src/modules/turns/history.ts) and its twinChatHistoryEntry(ui/engine-client/src/types.ts) each gainturn_id?: string;historyToFeedthreads it through every folded frame, mirroring howtsis already carried.Tests
@houston/sdk: 371/371 — unit tests assertturn_idis projected onto every frame of a turn (user bubble + assistant frames share one id) and isundefinedfor a pre-turn-id transcript.turn_id, and that a whole settled turn folds under a singleturn_id.houston-web: 218/218 (translate + history-cache unaffected). Fullpnpm -r typecheckclean; Biome clean.Naming
turn_id(snake) to matchfeed_typeon the same object — consistency within the entry. Trivial to flip toturnId(matching the source field) if maintainers prefer.