2e14873f2d
Track application source and tests; exclude local env, user workspaces, and runtime data via .gitignore. Co-authored-by: Cursor <cursoragent@cursor.com>
67 lines
1.8 KiB
JavaScript
67 lines
1.8 KiB
JavaScript
/**
|
|
* Merge streaming assistant chunks from SSE Message events.
|
|
* Upstream may send deltas, cumulative snapshots, or multi-part content arrays.
|
|
*/
|
|
export function mergeStreamingChunk(previous, incoming) {
|
|
const prev = String(previous ?? '');
|
|
const next = String(incoming ?? '');
|
|
if (!next) return prev;
|
|
if (!prev) return next;
|
|
if (next === prev) return prev;
|
|
if (next.startsWith(prev)) return next;
|
|
if (prev.startsWith(next)) return prev;
|
|
if (prev.endsWith(next)) return prev;
|
|
|
|
const maxOverlap = Math.min(prev.length, next.length);
|
|
for (let size = maxOverlap; size > 0; size -= 1) {
|
|
if (prev.endsWith(next.slice(0, size))) {
|
|
return prev + next.slice(size);
|
|
}
|
|
}
|
|
|
|
return prev + next;
|
|
}
|
|
|
|
function findLastContentIndex(content, type) {
|
|
for (let index = content.length - 1; index >= 0; index -= 1) {
|
|
if (content[index]?.type === type) return index;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
function mergeTextLikeBlock(block, incomingValue, field) {
|
|
block[field] = mergeStreamingChunk(block[field], incomingValue);
|
|
}
|
|
|
|
export function mergeMessageContent(existingContent, incomingContent) {
|
|
const merged = [...existingContent];
|
|
|
|
for (const item of incomingContent) {
|
|
if (item.type === 'text') {
|
|
const index = findLastContentIndex(merged, 'text');
|
|
if (index >= 0) {
|
|
mergeTextLikeBlock(merged[index], item.text, 'text');
|
|
continue;
|
|
}
|
|
merged.push({ ...item });
|
|
continue;
|
|
}
|
|
|
|
if (item.type === 'thinking') {
|
|
const index = findLastContentIndex(merged, 'thinking');
|
|
if (index >= 0) {
|
|
mergeTextLikeBlock(merged[index], item.thinking, 'thinking');
|
|
continue;
|
|
}
|
|
merged.push({ ...item });
|
|
continue;
|
|
}
|
|
|
|
const tail = merged[merged.length - 1];
|
|
if (tail && JSON.stringify(tail) === JSON.stringify(item)) continue;
|
|
merged.push({ ...item });
|
|
}
|
|
|
|
return merged;
|
|
}
|