From 2f8019b6105d88fbb2acebefcf36169c2744e6ec Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Thu, 2 Apr 2026 01:39:32 +0200 Subject: [PATCH] fix(ai): emit missing responses toolcall delta closes #2745 --- packages/ai/CHANGELOG.md | 1 + .../ai/src/providers/openai-responses-shared.ts | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index d9a7d9f1..e5bbf8a7 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixed - Fixed Anthropic context overflow detection to recognize HTTP 413 `request_too_large` errors, so callers can trigger compaction and retry instead of getting stuck on repeated oversized-image requests ([#2734](https://github.com/badlogic/pi-mono/issues/2734)) +- Fixed OpenAI Responses tool-call streaming to emit a `toolcall_delta` when function call arguments arrive only in `response.function_call_arguments.done`, and to emit only the missing suffix when `.done` extends earlier streamed arguments ([#2745](https://github.com/badlogic/pi-mono/issues/2745)) ## [0.64.0] - 2026-03-29 diff --git a/packages/ai/src/providers/openai-responses-shared.ts b/packages/ai/src/providers/openai-responses-shared.ts index 63858536..8d9f39a2 100644 --- a/packages/ai/src/providers/openai-responses-shared.ts +++ b/packages/ai/src/providers/openai-responses-shared.ts @@ -408,8 +408,21 @@ export async function processResponsesStream( } } else if (event.type === "response.function_call_arguments.done") { if (currentItem?.type === "function_call" && currentBlock?.type === "toolCall") { + const previousPartialJson = currentBlock.partialJson; currentBlock.partialJson = event.arguments; currentBlock.arguments = parseStreamingJson(currentBlock.partialJson); + + if (event.arguments.startsWith(previousPartialJson)) { + const delta = event.arguments.slice(previousPartialJson.length); + if (delta.length > 0) { + stream.push({ + type: "toolcall_delta", + contentIndex: blockIndex(), + delta, + partial: output, + }); + } + } } } else if (event.type === "response.output_item.done") { const item = event.item;