fix: skip streaming normalization on finish_reason length

Truncated tool calls (finish_reason: 'length') now preserve the raw
buffer instead of normalizing into executable commands, preventing
incomplete commands from becoming runnable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
gnanam1990
2026-04-06 18:08:01 +05:30
parent b20d878b76
commit 50efbe5614
2 changed files with 14 additions and 8 deletions

View File

@@ -1420,7 +1420,7 @@ test('does not normalize incomplete streamed Bash commands when finish_reason is
.map(event => (event.delta as Record<string, unknown>).partial_json) .map(event => (event.delta as Record<string, unknown>).partial_json)
.join('') .join('')
expect(streamedInput).toBe('{"command":"rg --fi"}') expect(streamedInput).toBe('rg --fi')
}) })
test('does not repair truncated Bash objects that do not contain command', async () => { test('does not repair truncated Bash objects that do not contain command', async () => {

View File

@@ -692,10 +692,15 @@ async function* openaiStreamToAnthropic(
// Close active tool calls // Close active tool calls
for (const [, tc] of activeToolCalls) { for (const [, tc] of activeToolCalls) {
if (tc.normalizeAtStop) { if (tc.normalizeAtStop) {
let partialJson: string
if (choice.finish_reason === 'length') {
// Truncated by max tokens — preserve raw buffer to avoid
// turning an incomplete tool call into an executable command
partialJson = tc.jsonBuffer
} else {
const repairedStructuredJson = repairPossiblyTruncatedObjectJson( const repairedStructuredJson = repairPossiblyTruncatedObjectJson(
tc.jsonBuffer, tc.jsonBuffer,
) )
let partialJson: string
if (repairedStructuredJson) { if (repairedStructuredJson) {
partialJson = repairedStructuredJson partialJson = repairedStructuredJson
} else { } else {
@@ -703,6 +708,7 @@ async function* openaiStreamToAnthropic(
normalizeToolArguments(tc.name, tc.jsonBuffer), normalizeToolArguments(tc.name, tc.jsonBuffer),
) )
} }
}
yield { yield {
type: 'content_block_delta', type: 'content_block_delta',