feat: stream claude-code tokens (reland #6664) + fix the orphan reasoning-end that killed runs - #6670
Merged
Merged
Conversation
Base automatically changed from
revert-6664-feat/stream-reconnect-autocommit
to
main
August 28, 2026 01:41
added 2 commits
August 27, 2026 23:21
A streamed text/reasoning block was ended AFTER the `finish-step` the next assistant message pushes. The AI SDK reducer clears its open text/reasoning parts on `finish-step`, so that end arrived for a part it no longer knew and threw `Received reasoning-end for missing reasoning part with ID "stream-2"`. That throw killed the stream pump mid-run: no `finish` chunk ever reached the log, so `resolveCleanRunStatus(undefined)` read the truncated stream as a clean end and stored the thread `completed` while the sandbox kept working — the task board then advanced the card to In Review under a still-running agent.
pedrofrxncx
force-pushed
the
fix/claude-code-stream-block-ordering
branch
from
August 28, 2026 02:21
287cd32 to
ef3975d
Compare
decocms Bot
pushed a commit
that referenced
this pull request
Aug 28, 2026
PR: #6670 feat: stream claude-code tokens (reland #6664) + fix the orphan reasoning-end that killed runs Bump type: minor - decocms (apps/api/package.json): 4.288.1 -> 4.289.0 - @decocms/native (apps/native/package.json): 4.288.1 -> 4.289.0 - @decocms/harness-runner (packages/harness-runner/package.json): 0.8.1 -> 0.9.0 - @decocms/sandbox (packages/sandbox/package.json): 1.59.1 -> 1.60.0 - deploy/helm/sandbox-env (chart 0.16.29) (deploy/helm/sandbox-env/values.yaml deploy/helm/sandbox-env/Chart.yaml): image.tag/appVersion -> 1.60.0 Deploy-Scope: web
pedrofrxncx
added a commit
that referenced
this pull request
Aug 28, 2026
… error (#6675) fail() emitted finish-step without closing whatever stream_event had left open, unlike the assistant-message step boundary a few lines above, which closes it first (added earlier in #6670 for the same orphan-end hazard). An SDK throw mid-block leaves that text/reasoning part without its -end chunk, so it reads as still streaming forever after the run has already failed.
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.
Relands #6664 (reverted in #6669) with the bug that forced the revert fixed.
Stacked on #6669 — base is the revert branch, so this merges as: revert lands, then #6664 comes back fixed. Retarget to
mainif #6669 merges first.What broke
A streamed text/reasoning block was ended after the
finish-stepthat the next assistant message pushes (claude-code.tspushed the step boundary beforetranslator.translate(message), andtranslateAssistantis where the open block was closed). The AI SDK reducer clears its open text/reasoning parts onfinish-step(process-ui-message-stream.ts:770-774), so the end arrived for a part it no longer knew:That throw kills the pump mid-run. No
finishchunk ever reaches the JetStream log, soresolveCleanRunStatus(undefined)reads the truncated stream as a clean end: the thread is storedcompletedwhile the sandbox agent is still working, and the thread-finish hook advances the task board card to In Review. Observed in prod onboard_x5gk0kjwXRfgmf3TFZ_JS— the thread'sfinishpart carries nousage, unlike healthy runs.The fix
Close whatever
stream_eventleft open before pushingfinish-step.closeOpenStreamBlocks()becomes public for that;translateAssistantstill calls it (now a no-op on that path), so a block closed bycontent_block_stopis unaffected and the assistant restatement never emits a second end.Testing
bun test packages/harness-runner— 69 pass, incl. a new case: a block left open at the step boundary is closed once, and the assistant restatement adds nothing.bun run --cwd=packages/harness-runner check,bun run fmt.Summary by cubic
Relands token-level streaming for Claude Code runs: text now arrives as the model writes it instead of one large frame after the turn finishes, and the block-ordering bug that made the first merge unsafe is fixed — an interrupted stream no longer throws, kills the run mid-stream, and records the thread
completedwhile the agent keeps working. Also adds a live elapsed readout for long-running tool calls and two-minute working-tree checkpoints in the sandbox daemon.Claude Code streaming
includePartialMessages; the translator turns rawstream_eventmessages into text/reasoning start-delta-end chunks and skips the assistant message's restatement of blocks already streamed.finish-step; an end emitted after that lands on a part the AI SDK reducer has already cleared.UI and sandbox durability
.envvariants anywhere in the tree;.envrcis still committed.Written for commit ef3975d. Summary will update on new commits.