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)
.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 () => {

View File

@@ -692,10 +692,15 @@ async function* openaiStreamToAnthropic(
// Close active tool calls
for (const [, tc] of activeToolCalls) {
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(
tc.jsonBuffer,
)
let partialJson: string
if (repairedStructuredJson) {
partialJson = repairedStructuredJson
} else {
@@ -703,6 +708,7 @@ async function* openaiStreamToAnthropic(
normalizeToolArguments(tc.name, tc.jsonBuffer),
)
}
}
yield {
type: 'content_block_delta',