import { describe, expect, it } from "vitest" ;
import {
extractAssistantTextForPhase,
extractAssistantVisibleText,
extractFirstTextBlock,
resolveAssistantMessagePhase,
} from "./chat-message-content.js" ;
describe("shared/chat-message-content" , () => {
it("extracts the first text block from array content" , () => {
expect(
extractFirstTextBlock({
content: [{ text: "hello" }, { text: "world" }],
}),
).toBe("hello" );
});
it("returns plain string content" , () => {
expect(
extractFirstTextBlock({
content: "hello from string content" ,
}),
).toBe("hello from string content" );
});
it("preserves empty-string text in the first block" , () => {
expect(
extractFirstTextBlock({
content: [{ text: "" }, { text: "later" }],
}),
).toBe("" );
});
it("only considers the first content block even if later blocks have text" , () => {
expect(
extractFirstTextBlock({
content: [null , { text: "later" }],
}),
).toBeUndefined();
expect(
extractFirstTextBlock({
content: [{ type: "image" }, { text: "later" }],
}),
).toBeUndefined();
});
it("returns undefined for missing, empty, or non-text content" , () => {
expect(extractFirstTextBlock(null )).toBeUndefined();
expect(extractFirstTextBlock({ content: [] })).toBeUndefined();
expect(extractFirstTextBlock({ content: [{ type: "image" }] })).toBeUndefined();
expect(extractFirstTextBlock({ content: ["hello" ] })).toBeUndefined();
expect(extractFirstTextBlock({ content: [{ text: 1 }, { text: "later" }] })).toBeUndefined();
});
});
describe("extractAssistantVisibleText" , () => {
it("preserves boundary spacing when joining adjacent final_answer text blocks" , () => {
expect(
extractAssistantTextForPhase(
{
role: "assistant" ,
content: [
{
type: "text" ,
text: "Hi " ,
textSignature: JSON.stringify({ v: 1 , id: "msg_final_1" , phase: "final_answer" }),
},
{
type: "text" ,
text: "there" ,
textSignature: JSON.stringify({ v: 1 , id: "msg_final_2" , phase: "final_answer" }),
},
],
},
{ phase: "final_answer" , joinWith: "" },
),
).toBe("Hi there" );
});
it("prefers final_answer text over commentary text" , () => {
expect(
extractAssistantVisibleText({
role: "assistant" ,
content: [
{
type: "text" ,
text: "thinking like caveman" ,
textSignature: JSON.stringify({ v: 1 , id: "msg_commentary" , phase: "commentary" }),
},
{
type: "text" ,
text: "Actual final answer" ,
textSignature: JSON.stringify({ v: 1 , id: "msg_final" , phase: "final_answer" }),
},
],
}),
).toBe("Actual final answer" );
});
it("does not fall back to commentary-only text" , () => {
expect(
extractAssistantVisibleText({
role: "assistant" ,
content: [
{
type: "text" ,
text: "thinking like caveman" ,
textSignature: JSON.stringify({ v: 1 , id: "msg_commentary" , phase: "commentary" }),
},
],
}),
).toBeUndefined();
});
it("does not fall back to unphased legacy text when final_answer is empty" , () => {
expect(
extractAssistantVisibleText({
role: "assistant" ,
content: [
{ type: "text" , text: "Legacy answer" },
{
type: "text" ,
text: " " ,
textSignature: JSON.stringify({ v: 1 , id: "msg_final" , phase: "final_answer" }),
},
],
}),
).toBeUndefined();
});
it("falls back to unphased legacy text" , () => {
expect(
extractAssistantVisibleText({
role: "assistant" ,
content: [{ type: "text" , text: "Legacy answer" }],
}),
).toBe("Legacy answer" );
});
it("does not mix unphased legacy text into final_answer output" , () => {
expect(
extractAssistantVisibleText({
role: "assistant" ,
phase: "final_answer" ,
content: [
{ type: "text" , text: "Legacy answer" },
{
type: "text" ,
text: "Actual final answer" ,
textSignature: JSON.stringify({ v: 1 , id: "msg_final" , phase: "final_answer" }),
},
],
}),
).toBe("Actual final answer" );
});
});
describe("resolveAssistantMessagePhase" , () => {
it("prefers the top-level assistant phase when present" , () => {
expect(resolveAssistantMessagePhase({ role: "assistant" , phase: "commentary" })).toBe(
"commentary" ,
);
});
it("resolves a single explicit phase from textSignature metadata" , () => {
expect(
resolveAssistantMessagePhase({
role: "assistant" ,
content: [
{
type: "text" ,
text: "Actual final answer" ,
textSignature: JSON.stringify({ v: 1 , id: "msg_final" , phase: "final_answer" }),
},
],
}),
).toBe("final_answer" );
});
it("returns undefined when text blocks contain mixed explicit phases" , () => {
expect(
resolveAssistantMessagePhase({
role: "assistant" ,
content: [
{
type: "text" ,
text: "Working..." ,
textSignature: JSON.stringify({ v: 1 , id: "msg_commentary" , phase: "commentary" }),
},
{
type: "text" ,
text: "Done." ,
textSignature: JSON.stringify({ v: 1 , id: "msg_final" , phase: "final_answer" }),
},
],
}),
).toBeUndefined();
});
});
Messung V0.5 in Prozent C=100 H=97 G=98
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland