Skip to content

fix(agent): emit a reasoning start when a v2 delta finds no span open - #3481

Merged
kwakayama merged 1 commit into
mainfrom
fix/ag-ui-v2-orphan-reasoning-delta
Aug 8, 2026
Merged

kwakayama merged 1 commit into
mainfrom
fix/ag-ui-v2-orphan-reasoning-delta

Conversation

@kwakayama

@kwakayama kwakayama commented Aug 8, 2026 •

Copy link
Copy Markdown
Contributor

Closes veryfront/veryfront-issue-inbox#408.

Bug

On the v2 stream-lifecycle path (VF_STREAM_LIFECYCLE_MODE), a reasoning_content arriving with no span open mints a span id but emits only Content:

const continueReasoning = (): string => activeReasoningMessageId ?? startReasoning();

No ReasoningMessageStart is ever emitted for that id. Per veryfront/veryfront-issue-inbox#152, the API canonicalizer and Studio stream decoder key strictly on the reasoning lifecycle, so content whose start never arrived is dropped — silently missing reasoning text.

browser-encoder.ts (v1) already synthesizes the missing start. This makes v2 match.

Fix

One case in lifecycle-browser-adapter.ts: emit the start first when a delta finds no span open. No other paths touched.

Tests

One test, opens a reasoning span visibly when a delta arrives with none open, asserting the full Start → Content → End sequence on one id. Confirmed red before the fix, green after.

src/agent/ag-ui/ 29 passed / 158 steps. deno check / fmt / lint / docs check clean.

Note

Needs a provider that emits reasoning content without a preceding start; I have not confirmed one does. This fixes a real v1/v2 divergence, not a proven live incident.

Summary by CodeRabbit

  • Bug Fixes

    • Reasoning content received without an active reasoning span now starts one automatically.
    • Reasoning messages consistently emit start, content, and end events with a stable message identifier.
    • Automatically opened reasoning spans close correctly when the corresponding end event arrives.
  • Tests

    • Added coverage for orphan reasoning content events and their complete lifecycle.

On the v2 stream-lifecycle path, a reasoning_content with no span open
minted a span id via continueReasoning() but emitted only Content, so
consumers got content for a messageId they never saw start and drop it.

browser-encoder already synthesizes the missing start; v2 now matches.

Closes veryfront/veryfront-issue-inbox#408
@kwakayama
kwakayama requested a review from kojiwakayama as a code owner August 8, 2026 19:24
@coderabbitai

coderabbitai Bot commented Aug 8, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 558139cf-5af9-40ab-a609-07564150f6c0

📥 Commits

Reviewing files that changed from the base of the PR and between 396477b and 2f8e83f.

📒 Files selected for processing (2)
  • src/agent/ag-ui/lifecycle-browser-adapter.test.ts
  • src/agent/ag-ui/lifecycle-browser-adapter.ts

📝 Walkthrough

Walkthrough

The lifecycle adapter now opens a reasoning span when content arrives without an active span. Tests verify the start, content, and end events and the stable generated message ID.

Changes

Reasoning lifecycle

Layer / File(s) Summary
Implicit reasoning span opening
src/agent/ag-ui/lifecycle-browser-adapter.ts, src/agent/ag-ui/lifecycle-browser-adapter.test.ts
The adapter emits a reasoning start before orphan reasoning content. Tests verify event ordering, message ID reuse, and the matching reasoning end event.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: kojiwakayama

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: emitting a reasoning start when a v2 delta has no open span.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ag-ui-v2-orphan-reasoning-delta

Comment @coderabbitai help to get the list of available commands.

@kwakayama
kwakayama added this pull request to the merge queue Aug 8, 2026
Merged via the queue into main with commit 4a0b63e Aug 8, 2026
31 checks passed
@kwakayama
kwakayama deleted the fix/ag-ui-v2-orphan-reasoning-delta branch August 8, 2026 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant