mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-23 10:57:44 +08:00
feat: implement trimContinuationOverlap utility to remove redundant stream prefixes and add associated tests.
This commit is contained in:
23
internal/js/chat-stream/dedupe.js
Normal file
23
internal/js/chat-stream/dedupe.js
Normal 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,
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user