feat: reasoning, web search, and thinking event support#62
feat: reasoning, web search, and thinking event support#62erezcor wants to merge 1 commit intoCopilotKit:mainfrom
Conversation
…d Claude thinking blocks
jpr5
left a comment
There was a problem hiding this comment.
Code Review — 7-Agent Standard CR
878 lines across 7 files reviewed by 7 specialized agents.
Overall the PR is well-structured — the data flows are correctly traced, output indices are managed properly, and backward compatibility is maintained. Two bugs and three critical test gaps need addressing before merge.
Bugs
1. webSearches silently dropped for Claude Messages API
handleMessages() in src/messages.ts passes response.reasoning but never response.webSearches. A fixture with webSearches served via /v1/messages silently drops them — zero warning, zero log, zero error.
A user who defines a fixture with webSearches and tests via the Responses API will see it work correctly, then switch to Claude Messages API and see the web searches vanish with no indication anything was omitted.
Fix (minimum): Log a warning in handleMessages when response.webSearches is present:
if (response.webSearches?.length) {
logger.warn("webSearches in fixture response are not supported for Claude Messages API — ignoring");
}Or add a fixture-loader validation warning that webSearches only applies to the Responses API.
2. reasoning: "" silently treated as no reasoning
Both buildTextStreamEvents and buildClaudeTextStreamEvents use if (reasoning) — empty string is falsy in JS, so reasoning: "" produces zero events. Meanwhile, fixture-loader.ts validates it as a legal string. Gap between validation and runtime.
Fix: Add a validation warning for reasoning: "":
if (response.reasoning === "") {
results.push({ severity: "warning", fixtureIndex: i, message: "reasoning is empty string — no reasoning events will be emitted" });
}Same pattern as existing content: "" validation.
Missing Test Coverage (critical gaps)
3. No stream-collapse tests for reasoning/webSearch extraction
collapseOpenAISSE gained reasoning delta accumulation + web search query extraction from response.output_item.done. collapseAnthropicSSE gained thinking_delta extraction. Zero tests cover any of this. These functions power record-and-replay — wrong extraction means silent data loss in recorded fixtures.
Need tests for:
collapseOpenAISSEwith reasoning summary events →result.reasoningcollapseOpenAISSEwith web searchoutput_item.doneevents →result.webSearchescollapseAnthropicSSEwiththinking_deltaevents →result.reasoning
4. No fixture-loader validation tests
27 lines of new validation logic (reasoning type check, webSearches array check, element type check) with zero tests.
Need tests for:
reasoning: 123→ errorwebSearches: "not-array"→ errorwebSearches: ["valid", 42]→ error on element- Valid values → no errors
5. No WebSocket reasoning passthrough test
ws-responses.ts was modified to pass reasoning/webSearches through to buildTextStreamEvents — untested plumbing.
PR Description Fix
The PR body lists src/index.ts as changed with "Removed unexported builders from public API" — but index.ts is not in the diff. buildTextStreamEvents is still exported. Please update the description.
Non-blocking Notes
buildReasoningStreamEventshardcodesoutput_index: 0whilebuildWebSearchStreamEventstakesstartOutputIndex— asymmetric but correct today since reasoning is always firstwebSearches: string[]could beArray<{ query: string }>for extensibility — noted for future- Consider
webSearches: []andwebSearches: [""]validation warnings (empty array / empty string elements)
Summary
Adds support for reasoning and web search events in fixture responses across multiple providers:
reasoningfield onTextResponseemitsresponse.reasoning_summary_text.deltaevents before text content. OptionalwebSearchesfield emitsresponse.web_search_callevents.reasoningfield emitsthinkingcontent blocks before text in/v1/messages.Closes #60
Changes
src/types.ts:TextResponseextended with optionalreasoning?: stringandwebSearches?: string[]src/responses.ts:buildTextStreamEventsaccepts optional reasoning/webSearches and prepends the appropriate events with correctoutput_indexadjustment. Private helpersbuildReasoningStreamEventsandbuildWebSearchStreamEventshandle individual event sequences. Non-streamingbuildTextResponseincludes reasoning and web search output items.src/messages.ts: Emitsthinkingcontent blocks whenreasoningis present (both streaming and non-streaming)src/ws-responses.ts: Passes reasoning/webSearches through tobuildTextStreamEvents(no duplicated logic)src/fixture-loader.ts: Validatesreasoning(string) andwebSearches(array of strings)src/stream-collapse.ts: Extracts reasoning fromresponse.reasoning_summary_text.deltaand web searches fromresponse.output_item.doneweb_search_call events. Claude collapse extracts reasoning fromthinking_deltaevents.src/index.ts: Removed unexported builders from public APIExample
Test plan