


























@@ -2440,22 +2440,25 @@ async function processOpenAICompletionsStream(
24402440const deepSeekTextFilter = shouldFilterDeepSeekDsmlText(compat)
24412441 ? createDeepSeekTextFilter()
24422442 : null;
2443+type ToolCallBlock = {
2444+type: "toolCall";
2445+id: string;
2446+name: string;
2447+arguments: Record<string, unknown>;
2448+partialArgs: string;
2449+thoughtSignature?: string;
2450+};
24432451let currentBlock:
24442452| { type: "text"; text: string }
24452453| { type: "thinking"; thinking: string; thinkingSignature?: string }
2446-| {
2447-type: "toolCall";
2448-id: string;
2449-name: string;
2450-arguments: Record<string, unknown>;
2451-partialArgs: string;
2452-thoughtSignature?: string;
2453-}
2454+| ToolCallBlock
24542455| null = null;
24552456let pendingPostToolCallDeltas: CompletionsReasoningDelta[] = [];
24562457let pendingPostToolCallBytes = 0;
2457-let currentToolCallArgumentBytes = 0;
24582458let isFlushingPendingPostToolCallDeltas = false;
2459+const toolCallBlocksByIndex = new Map<number, ToolCallBlock>();
2460+const toolCallBlocksById = new Map<string, ToolCallBlock>();
2461+const toolCallBlockBytes = new WeakMap<ToolCallBlock, number>();
24592462const blockIndex = () => output.content.length - 1;
24602463const measureUtf8Bytes = (text: string) => Buffer.byteLength(text, "utf8");
24612464const finishCurrentBlock = () => {
@@ -2464,11 +2467,11 @@ async function processOpenAICompletionsStream(
24642467}
24652468if (currentBlock.type === "toolCall") {
24662469currentBlock.arguments = parseStreamingJson(currentBlock.partialArgs);
2467- const completed = {
2468- ...currentBlock,
2469- arguments: parseStreamingJson(currentBlock.partialArgs),
2470- };
2471-output.content[blockIndex()] = completed;
2470+}
2471+};
2472+const finishAllToolCallBlocks = () => {
2473+for (const block of toolCallBlocksByIndex.values()) {
2474+block.arguments = parseStreamingJson(block.partialArgs);
24722475}
24732476};
24742477const queuePostToolCallDelta = (next: CompletionsReasoningDelta) => {
@@ -2646,57 +2649,61 @@ async function processOpenAICompletionsStream(
26462649}
26472650if (choiceDelta.tool_calls && choiceDelta.tool_calls.length > 0) {
26482651for (const toolCall of choiceDelta.tool_calls) {
2649-if (
2650-!currentBlock ||
2651-currentBlock.type !== "toolCall" ||
2652-(toolCall.id && currentBlock.id !== toolCall.id)
2653-) {
2652+const streamIndex = typeof toolCall.index === "number" ? toolCall.index : undefined;
2653+let block = streamIndex !== undefined ? toolCallBlocksByIndex.get(streamIndex) : undefined;
2654+if (!block && toolCall.id) {
2655+block = toolCallBlocksById.get(toolCall.id);
2656+}
2657+if (!block) {
26542658const switchingToolCall = currentBlock?.type === "toolCall";
26552659finishCurrentBlock();
26562660if (switchingToolCall) {
26572661currentBlock = null;
26582662flushPendingPostToolCallDeltas();
26592663}
26602664const initialSig = extractGoogleThoughtSignature(toolCall);
2661-currentBlock = {
2665+block = {
26622666type: "toolCall",
26632667id: toolCall.id || "",
26642668name: toolCall.function?.name || "",
26652669arguments: {},
26662670partialArgs: "",
26672671 ...(initialSig ? { thoughtSignature: initialSig } : {}),
26682672};
2669-currentToolCallArgumentBytes = 0;
2670-output.content.push(currentBlock);
2671-stream.push({ type: "toolcall_start", contentIndex: blockIndex(), partial: output });
2673+output.content.push(block);
2674+stream.push({
2675+type: "toolcall_start",
2676+contentIndex: output.content.indexOf(block),
2677+partial: output,
2678+});
26722679}
2673-if (currentBlock.type !== "toolCall") {
2674-continue;
2680+if (streamIndex !== undefined && !toolCallBlocksByIndex.has(streamIndex)) {
2681+toolCallBlocksByIndex.set(streamIndex, block);
26752682}
26762683if (toolCall.id) {
2677-currentBlock.id = toolCall.id;
2684+block.id = toolCall.id;
2685+toolCallBlocksById.set(toolCall.id, block);
26782686}
2687+currentBlock = block;
26792688if (toolCall.function?.name) {
2680-currentBlock.name = toolCall.function.name;
2689+block.name = toolCall.function.name;
26812690}
26822691const deltaSig = extractGoogleThoughtSignature(toolCall);
26832692if (deltaSig) {
2684-currentBlock.thoughtSignature = deltaSig;
2693+block.thoughtSignature = deltaSig;
26852694}
26862695if (toolCall.function?.arguments) {
26872696const nextArgumentBytes = measureUtf8Bytes(toolCall.function.arguments);
2688-if (
2689-currentToolCallArgumentBytes + nextArgumentBytes >
2690-MAX_TOOL_CALL_ARGUMENT_BUFFER_BYTES
2691-) {
2697+const currentBlockArgBytes = toolCallBlockBytes.get(block) ?? 0;
2698+if (currentBlockArgBytes + nextArgumentBytes > MAX_TOOL_CALL_ARGUMENT_BUFFER_BYTES) {
26922699throw new Error("Exceeded tool-call argument buffer limit");
26932700}
2694-currentToolCallArgumentBytes += nextArgumentBytes;
2695-currentBlock.partialArgs += toolCall.function.arguments;
2696-currentBlock.arguments = parseStreamingJson(currentBlock.partialArgs);
2701+toolCallBlockBytes.set(block, currentBlockArgBytes + nextArgumentBytes);
2702+block.partialArgs += toolCall.function.arguments;
2703+block.arguments = parseStreamingJson(block.partialArgs);
26972704stream.push({
26982705type: "toolcall_delta",
2699-contentIndex: blockIndex(),
2706+contentIndex: output.content.indexOf(block),
27002707delta: toolCall.function.arguments,
27012708partial: output,
27022709});
@@ -2707,10 +2714,8 @@ async function processOpenAICompletionsStream(
27072714await cooperativeScheduler.afterEvent();
27082715}
27092716flushDeepSeekTextFilterAtEnd();
2710-finishCurrentBlock();
2711-if (currentBlock?.type === "toolCall") {
2712-currentBlock = null;
2713-}
2717+finishAllToolCallBlocks();
2718+currentBlock = null;
27142719flushPendingPostToolCallDeltas();
27152720const hasToolCalls = output.content.some((block) => block.type === "toolCall");
27162721if (output.stopReason === "toolUse" && !hasToolCalls) {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。