import test from "node:test";
import assert from "node:assert/strict";
const {
hasThinkTags,
extractThinkTags,
processStreamingThinkDelta,
flushThinkBuffer,
containsOrMayEndWithThinkOpenTag,
applyThinkTag,
} = await import("../../open-sse/utils/thinkTagParser.ts");
test("hasThinkTags detects opening tags and ignores empty input", () => {
assert.equal(hasThinkTags("before plan after"), true);
assert.equal(hasThinkTags("plain answer"), false);
assert.equal(hasThinkTags(""), false);
});
test("extractThinkTags returns reasoning and cleaned content", () => {
const result = extractThinkTags("Hello step 1 world");
assert.deepEqual(result, {
reasoning: "step 1",
content: "Hello world",
});
});
test("extractThinkTags concatenates multiple think blocks and handles unclosed tags", () => {
assert.deepEqual(extractThinkTags("A first B second C"), {
reasoning: "first\nsecond",
content: "A B C",
});
assert.deepEqual(extractThinkTags("prefix unfinished reasoning"), {
reasoning: "unfinished reasoning",
content: "prefix",
});
});
test("processStreamingThinkDelta extracts content and reasoning across split tags", () => {
const ctx = { insideThink: false, buffer: "" };
const first = processStreamingThinkDelta("Hello plan world", ctx);
assert.deepEqual(first, {
reasoningDelta: null,
contentDelta: "Hell",
});
assert.deepEqual(second, {
reasoningDelta: null,
contentDelta: "o ",
});
assert.deepEqual(third, {
reasoningDelta: "plan",
contentDelta: null,
});
assert.equal(ctx.insideThink, false);
assert.equal(ctx.buffer, " world");
const flushed = flushThinkBuffer(ctx);
assert.deepEqual(flushed, {
reasoningDelta: null,
contentDelta: " world",
});
});
test("containsOrMayEndWithThinkOpenTag flags a chunk ending on any partial open tag", () => {
for (const partial of ["<", "' across deltas", () => {
const ctx = { enabled: true, active: false, insideThink: false, buffer: "" };
const opening: { content: unknown; reasoning_content?: string } = { content: "plananswer",
};
assert.equal(applyThinkTag(ctx, rest), true);
assert.equal(rest.reasoning_content, "plan");
assert.equal(rest.content, "");
assert.deepEqual(flushThinkBuffer(ctx), {
reasoningDelta: null,
contentDelta: "answer",
});
});
test("processStreamingThinkDelta keeps partial closing tags buffered while inside think", () => {
const ctx = { insideThink: true, buffer: "" };
const result = processStreamingThinkDelta("reasoning {
const contentCtx = { insideThink: false, buffer: "tail" };
const reasoningCtx = { insideThink: true, buffer: "tail-thought" };
assert.deepEqual(flushThinkBuffer(contentCtx), {
reasoningDelta: null,
contentDelta: "tail",
});
assert.deepEqual(flushThinkBuffer(reasoningCtx), {
reasoningDelta: "tail-thought",
contentDelta: null,
});
assert.deepEqual(flushThinkBuffer({ insideThink: false, buffer: "" }), {
reasoningDelta: null,
contentDelta: null,
});
});