feat: implement trimContinuationOverlap utility to remove redundant stream prefixes and add associated tests.

This commit is contained in:
CJACK
2026-04-06 02:23:28 +08:00
parent 4d36afea4c
commit 49012a227c
10 changed files with 66878 additions and 23 deletions

View File

@@ -0,0 +1,23 @@
'use strict';
const MIN_CONTINUATION_SNAPSHOT_LEN = 32;
function trimContinuationOverlap(existing, incoming) {
if (!incoming) {
return '';
}
if (!existing) {
return incoming;
}
if (incoming.length >= MIN_CONTINUATION_SNAPSHOT_LEN && incoming.startsWith(existing)) {
return incoming.slice(existing.length);
}
if (incoming.length >= MIN_CONTINUATION_SNAPSHOT_LEN && existing.startsWith(incoming)) {
return '';
}
return incoming;
}
module.exports = {
trimContinuationOverlap,
};

View File

@@ -34,6 +34,9 @@ const {
const {
handleVercelStream,
} = require('./vercel_stream');
const {
trimContinuationOverlap,
} = require('./dedupe');
async function handler(req, res) {
setCorsHeaders(res);
@@ -119,4 +122,5 @@ module.exports.__test = {
extractAccumulatedTokenUsage,
isNodeStreamSupportedPath,
extractPathname,
trimContinuationOverlap,
};

View File

@@ -27,6 +27,9 @@ const {
relayPreparedFailure,
createLeaseReleaser,
} = require('./http_internal');
const {
trimContinuationOverlap,
} = require('./dedupe');
const DEEPSEEK_COMPLETION_URL = 'https://chat.deepseek.com/api/v0/chat/completion';
@@ -245,21 +248,29 @@ async function handleVercelStream(req, res, rawBody, payload) {
if (!p.text) {
continue;
}
if (searchEnabled && isCitation(p.text)) {
continue;
}
if (p.type === 'thinking') {
if (thinkingEnabled) {
thinkingText += p.text;
sendDeltaFrame({ reasoning_content: p.text });
const trimmed = trimContinuationOverlap(thinkingText, p.text);
if (!trimmed) {
continue;
}
thinkingText += trimmed;
sendDeltaFrame({ reasoning_content: trimmed });
}
} else {
outputText += p.text;
if (!toolSieveEnabled) {
sendDeltaFrame({ content: p.text });
const trimmed = trimContinuationOverlap(outputText, p.text);
if (!trimmed) {
continue;
}
const events = processToolSieveChunk(toolSieveState, p.text, toolNames);
if (searchEnabled && isCitation(trimmed)) {
continue;
}
outputText += trimmed;
if (!toolSieveEnabled) {
sendDeltaFrame({ content: trimmed });
continue;
}
const events = processToolSieveChunk(toolSieveState, trimmed, toolNames);
for (const evt of events) {
if (evt.type === 'tool_call_deltas') {
if (!emitEarlyToolDeltas) {