fix(translator): coerce submit_pr_review functionalChanges/findings to arrays - #2242
Conversation
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 11.14.0 to 11.15.0. - [Release notes](https://github.com/mermaid-js/mermaid/releases) - [Commits](https://github.com/mermaid-js/mermaid/compare/mermaid@11.14.0...mermaid@11.15.0) --- updated-dependencies: - dependency-name: mermaid dependency-version: 11.15.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…o arrays Some strict-schema downstream tools (e.g. submit_pr_review with required `functionalChanges`/`findings` array fields) hard-reject when those fields arrive as null, plain object, empty string, or stringified array — malformation modes that can emerge from OpenAI-shape upstream models routed through the streaming openai-to-claude translator. Without defense, the caller enters a retry loop it cannot recover from. Adds a small `TOOL_SHIMS` registry that the SSE translator applies on the streaming OpenAI -> Anthropic tool_use path. For registered tools the shim buffers raw args, suppresses passthrough `input_json_delta` events, then emits one corrective delta with the fully patched JSON just before `content_block_stop`. Handles five malformation modes per field. Zero overhead for non-shimmed tools. Side benefit: neutralises the collateral damage from the strip-empty heuristic in diegosouzapw#1852 when legitimate empty arrays are required by the tool schema. Adding another strict-schema tool to the registry is one entry. 20/20 unit + streaming integration tests in `tests/unit/translator-tool-call-shim.test.ts`. Adjacent translator suites stay green. Verified stable for ~24h on a downstream deploy under heavy review-harness traffic.
There was a problem hiding this comment.
Code Review
This pull request implements a shimming layer for tool calls to handle cases where upstream models emit malformed data, specifically ensuring that fields in the submit_pr_review tool are coerced into arrays. The implementation involves buffering tool arguments and re-emitting a corrected JSON delta at the end of the stream. A review comment correctly identified a potential memory performance issue where arguments are buffered for all tool calls regardless of whether they require shimming; the reviewer suggested limiting buffering to shimmed tools and removing a redundant string check.
| // Always buffer the raw stream so shimmed tools can re-emit a | ||
| // corrected JSON at stop time. | ||
| toolInfo.argBuffer = (toolInfo.argBuffer || "") + tc.function.arguments; | ||
|
|
||
| if (toolInfo.shimmed) { | ||
| // Suppress passthrough; we emit one corrective delta at finish. | ||
| continue; | ||
| } |
There was a problem hiding this comment.
The current implementation buffers tool arguments for all tool calls, which introduces significant memory overhead for non-shimmed tools. For large tool outputs (e.g., file contents or large data sets), this could lead to excessive memory consumption or OOM errors in high-traffic environments. Buffering should be restricted to only those tools that require shimming.
Additionally, since argBuffer is initialized to "" at line 175, the (toolInfo.argBuffer || "") check is redundant.
if (toolInfo.shimmed) {
// Buffer the raw stream for shimmed tools to re-emit corrected JSON at stop time.
toolInfo.argBuffer += tc.function.arguments;
// Suppress passthrough; we emit one corrective delta at finish.
continue;
}52285d8
into
diegosouzapw:release/v3.8.0
|
Thanks @NomenAK — squash-merged into |
Deep audit of all 320 commits since v3.7.9 found: - 18 merged PRs not documented in CHANGELOG (4 features, 10 bug fixes, 1 security, 2 chores, 1 debug improvement) - 3 contributors entirely missing from credits table (@NomenAK with 12 PRs, @kang-heewon, @one-vs) - 4 existing contributors with inaccurate PR counts (@oyi77 8→12, @ddarkr 2→3, @andrewmunsell 2→3, @nickwizard 2→3) New entries added: - feat: #2135 (1proxy settings), #2227 (antigravity project ID), #2238 (Z.AI Search), #2240 (CLI Suite) - fix: #2217, #2218, #2219, #2221, #2222, #2223, #2224, #2231, #2233, #2236, #2242, #2243 - security: #2209 (stack trace exposure) - chore: #2228, #2234 Total contributors updated from 50+ to 55+.
…o arrays (diegosouzapw#2242) Integrated into release/v3.8.0 — surgical streaming translator shim for submit_pr_review functionalChanges/findings array fields.
Deep audit of all 320 commits since v3.7.9 found: - 18 merged PRs not documented in CHANGELOG (4 features, 10 bug fixes, 1 security, 2 chores, 1 debug improvement) - 3 contributors entirely missing from credits table (@NomenAK with 12 PRs, @kang-heewon, @one-vs) - 4 existing contributors with inaccurate PR counts (@oyi77 8→12, @ddarkr 2→3, @andrewmunsell 2→3, @nickwizard 2→3) New entries added: - feat: diegosouzapw#2135 (1proxy settings), diegosouzapw#2227 (antigravity project ID), diegosouzapw#2238 (Z.AI Search), diegosouzapw#2240 (CLI Suite) - fix: diegosouzapw#2217, diegosouzapw#2218, diegosouzapw#2219, diegosouzapw#2221, diegosouzapw#2222, diegosouzapw#2223, diegosouzapw#2224, diegosouzapw#2231, diegosouzapw#2233, diegosouzapw#2236, diegosouzapw#2242, diegosouzapw#2243 - security: diegosouzapw#2209 (stack trace exposure) - chore: diegosouzapw#2228, diegosouzapw#2234 Total contributors updated from 50+ to 55+.
…o arrays (diegosouzapw#2242) Integrated into release/v3.8.0 — surgical streaming translator shim for submit_pr_review functionalChanges/findings array fields.
Deep audit of all 320 commits since v3.7.9 found: - 18 merged PRs not documented in CHANGELOG (4 features, 10 bug fixes, 1 security, 2 chores, 1 debug improvement) - 3 contributors entirely missing from credits table (@NomenAK with 12 PRs, @kang-heewon, @one-vs) - 4 existing contributors with inaccurate PR counts (@oyi77 8→12, @ddarkr 2→3, @andrewmunsell 2→3, @nickwizard 2→3) New entries added: - feat: diegosouzapw#2135 (1proxy settings), diegosouzapw#2227 (antigravity project ID), diegosouzapw#2238 (Z.AI Search), diegosouzapw#2240 (CLI Suite) - fix: diegosouzapw#2217, diegosouzapw#2218, diegosouzapw#2219, diegosouzapw#2221, diegosouzapw#2222, diegosouzapw#2223, diegosouzapw#2224, diegosouzapw#2231, diegosouzapw#2233, diegosouzapw#2236, diegosouzapw#2242, diegosouzapw#2243 - security: diegosouzapw#2209 (stack trace exposure) - chore: diegosouzapw#2228, diegosouzapw#2234 Total contributors updated from 50+ to 55+.
Problem
Some strict-schema downstream tools (e.g.
submit_pr_reviewwith requiredfunctionalChanges/findingsarray fields) hard-reject when those fields arrive asnull, plain object, empty string, or stringified array — malformation modes that can emerge from OpenAI-shape upstream models routed through the streamingopenai-to-claudetranslator.When the downstream tool rejects, the caller often enters a retry loop it cannot recover from on its own.
Root cause
The streaming OpenAI → Anthropic translator at
open-sse/translator/response/openai-to-claude.tspasses tool-call deltas through verbatim. When the upstream model emits a malformed required-array field, the assembled tool args land downstream in the rejected shape.A related side effect: the strip-empty heuristic from #1852 — correct in the general case — strips legitimate empty
[]from these tools' args, so the field appears omitted to the strict-schema validator.Fix
Adds a small
TOOL_SHIMSregistry underopen-sse/translator/helpers/toolCallShim.ts. The SSE translator applies it on the streaming OpenAI → Anthropic tool_use path. For a registered tool the shim:input_json_deltaevents for those tools while buffering.input_json_deltacarrying the fully-patched JSON just beforecontent_block_stop.Handles five malformation modes per field: omitted,
null, plain object, empty string, stringified array. Zero overhead for non-shimmed tools.Adding another strict-schema tool to the registry is one entry.
Test plan
tests/unit/translator-tool-call-shim.test.ts(new, 263 lines)translator-resp-openai-to-claude,openai-to-claude-strip-empty,empty-tool-name-loop,context-pinning-tool-calls(23 tests combined)tsconfig.typecheck-core.jsonScope and trade-offs
Intentionally surgical:
submit_pr_review). Open to making it config-driven if you'd prefer.Happy to split into smaller commits, revise, or scope down further.