Uh oh!
There was an error while loading. Please reload this page.
feat(cli): stream incremental reasoning/text deltas in run --format json - #38504
feat(cli): stream incremental reasoning/text deltas in run --format json#38504mustafa3rsan wants to merge 1 commit into
Conversation
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
Automated PR Cleanup Thank you for contributing to opencode. Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions. This PR was closed because it matched the following cleanup criteria:
PRs created within the last month are not affected by this cleanup. If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate. Thanks again for taking the time to contribute. |
Issue for this PR
N/A — no existing issue.
Type of change
What does this PR do?
opencode run --format json --thinkingnever streams reasoning. During a long thinking phase the JSON stream is silent, then the whole reasoning block appears at once when it ends.The loop in
run.tsonly handlesmessage.part.updated, and gatesreasoning/textonpart.time?.end, which is only set once the part finishes (SessionProcessor.finishReasoning). The incremental tokens are published asmessage.part.delta(session.updatePartDelta), butrunnever listens for them, so they're dropped.This adds one branch that emits
message.part.deltaaspart_deltaevents when--format json. ApartID -> part.typemap (filled frommessage.part.updated) tags each delta so consumers know whether it's reasoning or text:{"type":"part_delta","partID":"prt_...","field":"text","delta":"...","partType":"reasoning"}emit()is a no-op unless--format json, so the formatted/TTY output is untouched (it still waits for the whole part on purpose). It's a new event type, so existing JSON consumers ignore it; the finalreasoning/textevents are still emitted attime.end.How did you verify your code works?
Ran the patched build from source against a real model:
The JSON stream now includes
part_deltaevents (it didn't before):4 part_delta / 2 reasoning / 2 text / 1 step_start / 1 step_finish. Reasoning tokens arrive incrementally instead of only at block end, e.g.:bun run typecheck(tsgo --noEmit) passes andoxlintreports 0 errors on the file.Screenshots / recordings
N/A — not a UI change.
Checklist