fix(agents): preserve stop-finished OpenAI tool calls#88804
Conversation
|
Codex review: needs maintainer review before merge. Reviewed May 31, 2026, 6:47 PM ET / 22:47 UTC. Summary PR surface: Source +16, Tests +143. Total +159 across 4 files. Reproducibility: yes. source-level reproduction is high-confidence: on current main a stream with tool-call blocks plus Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the focused finalizer fix after maintainer review and CI if the loopback proof is accepted, or request one reporter-provider smoke if maintainers want exact vLLM/Qwen confirmation before merge. Do we have a high-confidence way to reproduce the issue? Yes, source-level reproduction is high-confidence: on current main a stream with tool-call blocks plus Is this the best way to solve the issue? Yes, this is the right layer: finalization already owns the symmetric AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against bb673f47b207. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +16, Tests +143. Total +159 across 4 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
steipete
left a comment
There was a problem hiding this comment.
One blocking issue from CI/typecheck. The implementation shape looks right, but this branch cannot merge until the new visible-text check narrows the block shape far enough for tsgo.
Finding:
src/agents/openai-transport-stream.ts:2812usesblock.text.trim()after only checkingblock.type === "text". In this exported transport surface,output.contentis wide enough thatblock.textis stillunknown, and CI fails incheck-prod-types,check-test-types, plugin SDK boundary prep, and dependent lint/boundary lanes withTS18046: 'block.text' is of type 'unknown'. Please narrow with a string check or a small local predicate before callingtrim(), for example by requiringtypeof block.text === "string"in thehasVisibleTextpredicate.
No behavior concern with the stop/tool-call promotion itself after reading the finalizer and adjacent tests; this is a compile blocker only.
steipete
left a comment
There was a problem hiding this comment.
Approved after the type-narrow fix on src/agents/openai-transport-stream.ts.
Verification I ran on the fixed tree:
pnpm tsgo:prodnode scripts/run-vitest.mjs src/llm/providers/openai-completions.test.ts src/agents/openai-transport-stream.test.ts- loopback OpenAI-compatible SSE proof against the real
createOpenAICompletionsTransportStreamFn: silentfinish_reason: stoptool call returnedtoolUse; visible text plus spurious tool call stayedstop; missing finish reason dropped the unfinished tool call .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/mainreturned clean with no accepted/actionable findings
The remaining red CI jobs are outside this PR's changed files and match current-main/stale-base fallout, not this OpenAI-compatible stream change.
Fixes #88791
Summary
tool_callsbut finish withfinish_reason: stop.stopresponses,length/error completions, and transport streams that never emitted a final finish reason.openai-completionsprovider path.Verification
pnpm format -- src/agents/openai-transport-stream.ts src/agents/openai-transport-stream.test.ts src/llm/providers/openai-completions.ts src/llm/providers/openai-completions.test.tsnode scripts/run-vitest.mjs src/llm/providers/openai-completions.test.ts src/agents/openai-transport-stream.test.ts.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/mainReal behavior proof
Behavior addressed: structured
tool_callspaired withfinish_reason: stopno longer get stripped into a silent terminal assistant turn when there is no visible assistant text.Real environment tested: local OpenClaw worktree running the actual OpenAI-compatible transport stream function against a loopback OpenAI-compatible SSE endpoint, with no provider credentials. Proof run timestamp: 2026-05-31 15:27 PDT.
Exact steps or command run after this patch:
node --import tsx /private/tmp/openclaw-real-proof-88791.mjsEvidence after fix: terminal output copied from the after-fix runtime proof:
Observed result after fix: the OpenClaw runtime preserved the silent structured tool call as
toolUse, kept the visible-textstopresponse deliverable as text, and dropped the unfinished tool call when the stream ended without a final finish reason.What was not tested: external vLLM/Qwen provider behavior and broad CI.