mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-24 08:02:14 +03:00
Merged after conflict resolution against the tip's #11109 (per-call tool_call tracking): scanOpenAiSseText keeps the per-call finish_reason special-case AND gains reasoningText + literal finishReason; canContinue uses the in-flight predicate with the new reasoning-only-clean-stop escape. One integration fix on the branch: the PR's hallucinatedEmptyStop referenced emittedToolCall, which #11109 had renamed — the branch now tracks emittedSawToolCall at the emitted level (any tool_call delta, complete or not), preserving the PR's don't-recover-after-tool-calls intent. Chain suites green: stream-continuation-wiring + stream-continuation + stream-recovery-toolcall 29/29. Thank you @maxmad64bis!
119 lines
5.7 KiB
TypeScript
119 lines
5.7 KiB
TypeScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import {
|
|
scanOpenAiSseText,
|
|
makeContinuationBody,
|
|
trimContinuationOverlap,
|
|
} from "../../open-sse/services/streamRecovery.ts";
|
|
|
|
// ── scanOpenAiSseText ─────────────────────────────────────────────────────────
|
|
|
|
test("scanOpenAiSseText accumulates content deltas and flags an OpenAI-compat stream", () => {
|
|
const sse =
|
|
'data: {"choices":[{"delta":{"role":"assistant"}}]}\n\n' +
|
|
'data: {"choices":[{"delta":{"content":"Hello"}}]}\n\n' +
|
|
'data: {"choices":[{"delta":{"content":" world"}}]}\n\n';
|
|
const r = scanOpenAiSseText(sse);
|
|
assert.equal(r.text, "Hello world");
|
|
assert.equal(r.parsedOpenAi, true);
|
|
assert.equal(r.sawToolCall, false);
|
|
assert.equal(r.terminal, false);
|
|
});
|
|
|
|
test("scanOpenAiSseText accumulates reasoning_content deltas separately from content", () => {
|
|
const sse =
|
|
'data: {"choices":[{"delta":{"role":"assistant"}}]}\n\n' +
|
|
'data: {"choices":[{"delta":{"reasoning_content":"thinking..."}}]}\n\n' +
|
|
'data: {"choices":[{"delta":{"reasoning_content":" more"}}]}\n\n';
|
|
const r = scanOpenAiSseText(sse);
|
|
assert.equal(r.reasoningText, "thinking... more");
|
|
assert.equal(r.text, "", "reasoning_content must never leak into the visible text field");
|
|
assert.equal(r.parsedOpenAi, true);
|
|
});
|
|
|
|
test("scanOpenAiSseText captures the literal finish_reason value", () => {
|
|
const stop = scanOpenAiSseText('data: {"choices":[{"delta":{},"finish_reason":"stop"}]}\n\n');
|
|
assert.equal(stop.finishReason, "stop");
|
|
|
|
const length = scanOpenAiSseText(
|
|
'data: {"choices":[{"delta":{"content":"x"},"finish_reason":"length"}]}\n\n'
|
|
);
|
|
assert.equal(length.finishReason, "length");
|
|
|
|
const none = scanOpenAiSseText('data: {"choices":[{"delta":{"content":"x"}}]}\n\n');
|
|
assert.equal(none.finishReason, null, "no finish_reason seen means null, not a guessed default");
|
|
});
|
|
|
|
test("scanOpenAiSseText detects the terminal [DONE] marker", () => {
|
|
const r = scanOpenAiSseText('data: {"choices":[{"delta":{"content":"hi"}}]}\n\ndata: [DONE]\n\n');
|
|
assert.equal(r.text, "hi");
|
|
assert.equal(r.terminal, true);
|
|
});
|
|
|
|
test("scanOpenAiSseText detects a finish_reason as terminal", () => {
|
|
const r = scanOpenAiSseText('data: {"choices":[{"delta":{"content":"x"},"finish_reason":"stop"}]}\n\n');
|
|
assert.equal(r.terminal, true);
|
|
});
|
|
|
|
test("scanOpenAiSseText flags tool_call deltas (never continue those)", () => {
|
|
const r = scanOpenAiSseText('data: {"choices":[{"delta":{"tool_calls":[{"index":0,"function":{"name":"f"}}]}}]}\n\n');
|
|
assert.equal(r.sawToolCall, true);
|
|
});
|
|
|
|
test("scanOpenAiSseText reports non-OpenAI bodies as not parsed (e.g. Anthropic events)", () => {
|
|
const anthropic =
|
|
"event: content_block_delta\n" +
|
|
'data: {"type":"content_block_delta","delta":{"type":"text_delta","text":"hi"}}\n\n';
|
|
const r = scanOpenAiSseText(anthropic);
|
|
assert.equal(r.parsedOpenAi, false, "Anthropic format yields no OpenAI delta → not continuable here");
|
|
assert.equal(r.text, "");
|
|
});
|
|
|
|
// ── makeContinuationBody ──────────────────────────────────────────────────────
|
|
|
|
test("makeContinuationBody appends the partial assistant turn (OpenAI shape)", () => {
|
|
const body = { model: "x", stream: true, messages: [{ role: "user", content: "hi" }] };
|
|
const out = makeContinuationBody(body, "partial answer");
|
|
assert.ok(out, "returns a continuation body");
|
|
assert.notEqual(out, body, "does not mutate the original");
|
|
assert.equal(out!.messages.length, 2);
|
|
assert.deepEqual(out!.messages[1], { role: "assistant", content: "partial answer" });
|
|
assert.equal(out!.stream, true, "stays streaming");
|
|
assert.deepEqual(body.messages.length, 1, "original is untouched");
|
|
});
|
|
|
|
test("makeContinuationBody refuses bodies without a messages array or empty text", () => {
|
|
assert.equal(makeContinuationBody({ model: "x", input: [] } as never, "t"), null);
|
|
assert.equal(makeContinuationBody({ model: "x", messages: [] }, ""), null);
|
|
assert.equal(makeContinuationBody(null as never, "t"), null);
|
|
});
|
|
|
|
test("makeContinuationBody accepts an empty prefill by re-sending the messages unchanged", () => {
|
|
const body = { model: "x", stream: true, messages: [{ role: "user", content: "hi" }] };
|
|
const out = makeContinuationBody(body, "");
|
|
assert.ok(out, "an empty prefill must still produce a re-request body, not null");
|
|
assert.equal(out!.messages.length, 1, "no empty assistant turn is appended");
|
|
assert.deepEqual(out!.messages[0], { role: "user", content: "hi" });
|
|
assert.equal(out!.stream, true);
|
|
});
|
|
|
|
// ── trimContinuationOverlap ───────────────────────────────────────────────────
|
|
|
|
test("trimContinuationOverlap removes a duplicated seam so the join is append-only", () => {
|
|
// model repeats the last words it already emitted
|
|
assert.equal(trimContinuationOverlap("The quick brown", " brown fox jumps"), " fox jumps");
|
|
assert.equal(trimContinuationOverlap("Hello wor", "world!"), "ld!");
|
|
});
|
|
|
|
test("trimContinuationOverlap is a no-op when there is no overlap", () => {
|
|
assert.equal(trimContinuationOverlap("abc", "def"), "def");
|
|
assert.equal(trimContinuationOverlap("", "def"), "def");
|
|
assert.equal(trimContinuationOverlap("abc", ""), "");
|
|
});
|
|
|
|
test("trimContinuationOverlap drops a continuation fully contained in what was emitted", () => {
|
|
// continuation re-sends only text already shown → nothing new to append
|
|
assert.equal(trimContinuationOverlap("Hello world", "world"), "");
|
|
});
|