From 5bc03e5de67378c4e273aff3fe62aed3b1b70071 Mon Sep 17 00:00:00 2001 From: "CJACK." Date: Fri, 20 Mar 2026 09:36:45 +0800 Subject: [PATCH 1/2] align vercel js stream toolcall delta behavior with go runtime --- internal/js/chat-stream/vercel_stream.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/internal/js/chat-stream/vercel_stream.js b/internal/js/chat-stream/vercel_stream.js index 439edb8..8030568 100644 --- a/internal/js/chat-stream/vercel_stream.js +++ b/internal/js/chat-stream/vercel_stream.js @@ -24,6 +24,8 @@ const { } = require('./token_usage'); const { resolveToolcallPolicy, + formatIncrementalToolCallDeltas, + filterIncrementalToolCallDeltasByAllowed, } = require('./toolcall_policy'); const { createChatCompletionEmitter, @@ -57,6 +59,7 @@ async function handleVercelStream(req, res, rawBody, payload) { const searchEnabled = toBool(prep.body.search_enabled); const toolPolicy = resolveToolcallPolicy(prep.body, payload.tools); const toolNames = toolPolicy.toolNames; + const emitEarlyToolDeltas = toolPolicy.emitEarlyToolDeltas; if (!model || !leaseID || !deepseekToken || !powHeader || !completionPayload) { writeOpenAIError(res, 500, 'invalid vercel prepare response'); @@ -132,6 +135,7 @@ async function handleVercelStream(req, res, rawBody, payload) { const toolSieveState = createToolSieveState(); let toolCallsEmitted = false; const streamToolCallIDs = new Map(); + const streamToolNames = new Map(); const decoder = new TextDecoder(); reader = completionRes.body.getReader(); let buffered = ''; @@ -255,6 +259,18 @@ async function handleVercelStream(req, res, rawBody, payload) { } const events = processToolSieveChunk(toolSieveState, p.text, toolNames); for (const evt of events) { + if (evt.type === 'tool_call_deltas') { + if (!emitEarlyToolDeltas) { + continue; + } + const filtered = filterIncrementalToolCallDeltasByAllowed(evt.deltas, toolNames, streamToolNames); + const formatted = formatIncrementalToolCallDeltas(filtered, streamToolCallIDs); + if (formatted.length > 0) { + toolCallsEmitted = true; + sendDeltaFrame({ tool_calls: formatted }); + } + continue; + } if (evt.type === 'tool_calls') { toolCallsEmitted = true; sendDeltaFrame({ tool_calls: formatOpenAIStreamToolCalls(evt.calls, streamToolCallIDs) }); From 17405be300a64bf90551ed1a24e881d7bc929ab2 Mon Sep 17 00:00:00 2001 From: "CJACK." Date: Fri, 20 Mar 2026 09:47:22 +0800 Subject: [PATCH 2/2] shrink vercel stream module under line gate limit --- internal/js/chat-stream/vercel_stream.js | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/internal/js/chat-stream/vercel_stream.js b/internal/js/chat-stream/vercel_stream.js index 8030568..4b1d6f3 100644 --- a/internal/js/chat-stream/vercel_stream.js +++ b/internal/js/chat-stream/vercel_stream.js @@ -1,35 +1,22 @@ 'use strict'; const { - extractToolNames, createToolSieveState, processToolSieveChunk, flushToolSieve, parseStandaloneToolCalls, formatOpenAIStreamToolCalls, } = require('../helpers/stream-tool-sieve'); -const { - BASE_HEADERS, -} = require('../shared/deepseek-constants'); - -const { - writeOpenAIError, -} = require('./error_shape'); -const { - parseChunkForContent, - isCitation, -} = require('./sse_parse'); -const { - buildUsage, -} = require('./token_usage'); +const { BASE_HEADERS } = require('../shared/deepseek-constants'); +const { writeOpenAIError } = require('./error_shape'); +const { parseChunkForContent, isCitation } = require('./sse_parse'); +const { buildUsage } = require('./token_usage'); const { resolveToolcallPolicy, formatIncrementalToolCallDeltas, filterIncrementalToolCallDeltasByAllowed, } = require('./toolcall_policy'); -const { - createChatCompletionEmitter, -} = require('./stream_emitter'); +const { createChatCompletionEmitter } = require('./stream_emitter'); const { asString, isAbortError,