feat: strip speaker labels from the transcript, add a plain-prose prompt (#9)
This commit was merged in pull request #9.
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
ASSISTANT_LABEL,
|
||||
STREAMING_CURSOR,
|
||||
USER_LABEL,
|
||||
buildThreadMarkdown,
|
||||
quote,
|
||||
sessionToPlainText,
|
||||
@@ -38,12 +36,29 @@ describe("buildThreadMarkdown", () => {
|
||||
message({ role: "assistant", text: "4" }),
|
||||
]);
|
||||
|
||||
expect(markdown).toContain("**You**");
|
||||
expect(markdown).toContain("> What is 2+2?");
|
||||
expect(markdown).toContain("**Lam**");
|
||||
expect(markdown).toContain("4");
|
||||
});
|
||||
|
||||
it("labels no speaker, so only the answer carries weight", () => {
|
||||
// A `**You**` / `**Lam**` header on each exchange gave both speakers the
|
||||
// same visual weight and pushed the answer behind chrome.
|
||||
const markdown = buildThreadMarkdown([
|
||||
message({ role: "user", text: "q" }),
|
||||
message({ role: "assistant", text: "a" }),
|
||||
]);
|
||||
|
||||
expect(markdown).not.toContain("You");
|
||||
expect(markdown).not.toContain("Lam");
|
||||
// Nothing bold at all, other than an error.
|
||||
expect(markdown).not.toContain("**");
|
||||
});
|
||||
|
||||
it("identifies the question by styling alone", () => {
|
||||
const markdown = buildThreadMarkdown([message({ role: "user", text: "just a question" })]);
|
||||
expect(markdown.trim()).toBe("> just a question");
|
||||
});
|
||||
|
||||
it("groups an answer with its question, dividing only between exchanges", () => {
|
||||
const markdown = buildThreadMarkdown([
|
||||
message({ id: "t2:assistant", role: "assistant", text: "second answer" }),
|
||||
@@ -59,17 +74,6 @@ describe("buildThreadMarkdown", () => {
|
||||
expect(markdown.indexOf("second question")).toBeLessThan(markdown.indexOf("first answer"));
|
||||
});
|
||||
|
||||
it("labels each speaker, in order", () => {
|
||||
const markdown = buildThreadMarkdown([
|
||||
message({ role: "user", text: "q" }),
|
||||
message({ role: "assistant", text: "a" }),
|
||||
]);
|
||||
|
||||
expect(markdown).toContain(`**${USER_LABEL}**`);
|
||||
expect(markdown).toContain(`**${ASSISTANT_LABEL}**`);
|
||||
expect(markdown.indexOf(USER_LABEL)).toBeLessThan(markdown.indexOf(ASSISTANT_LABEL));
|
||||
});
|
||||
|
||||
it("renders no images, because markdown cannot resolve them", () => {
|
||||
// Images render block-level and centred at up to 200px (`MdImage.qml`), and
|
||||
// every candidate icon source fails. Keep the transcript text-only.
|
||||
@@ -123,7 +127,7 @@ describe("buildThreadMarkdown", () => {
|
||||
expect(markdown).toContain("Ollama rejected the API key.");
|
||||
});
|
||||
|
||||
it("lists tools that were used, flagging failures", () => {
|
||||
it("lists tools on one quiet line, flagging failures", () => {
|
||||
const markdown = buildThreadMarkdown([
|
||||
message({
|
||||
role: "assistant",
|
||||
@@ -135,8 +139,9 @@ describe("buildThreadMarkdown", () => {
|
||||
}),
|
||||
]);
|
||||
|
||||
expect(markdown).toContain("`web_search`");
|
||||
expect(markdown).toContain("`web_fetch` — failed");
|
||||
expect(markdown).toContain("_Tools: `web_search`, `web_fetch` (failed)_");
|
||||
// Italic, not a bold header, so it stays below the answer.
|
||||
expect(markdown).not.toContain("**Tools");
|
||||
});
|
||||
|
||||
it("omits tools and reasoning when the preferences are off", () => {
|
||||
@@ -151,7 +156,7 @@ describe("buildThreadMarkdown", () => {
|
||||
|
||||
const hidden = buildThreadMarkdown(messages, { showToolCalls: false, showReasoning: false });
|
||||
|
||||
expect(hidden).not.toContain("Tools used");
|
||||
expect(hidden).not.toContain("_Tools:");
|
||||
expect(hidden).not.toContain("web_search");
|
||||
expect(hidden).not.toContain("Reasoning");
|
||||
expect(hidden).not.toContain("let me think");
|
||||
@@ -170,11 +175,11 @@ describe("buildThreadMarkdown", () => {
|
||||
];
|
||||
|
||||
const toolsOnly = buildThreadMarkdown(messages, { showToolCalls: true, showReasoning: false });
|
||||
expect(toolsOnly).toContain("Tools used");
|
||||
expect(toolsOnly).toContain("_Tools:");
|
||||
expect(toolsOnly).not.toContain("Reasoning");
|
||||
|
||||
const reasoningOnly = buildThreadMarkdown(messages, { showToolCalls: false, showReasoning: true });
|
||||
expect(reasoningOnly).not.toContain("Tools used");
|
||||
expect(reasoningOnly).not.toContain("_Tools:");
|
||||
expect(reasoningOnly).toContain("Reasoning");
|
||||
});
|
||||
|
||||
@@ -198,12 +203,25 @@ describe("sessionToPlainText", () => {
|
||||
it("keeps every question and answer", () => {
|
||||
const text = sessionToPlainText([turn("q1", "a1"), turn("q2", "a2")]);
|
||||
|
||||
expect(text).toContain("## q1");
|
||||
expect(text).toContain("q1");
|
||||
expect(text).toContain("a1");
|
||||
expect(text).toContain("## q2");
|
||||
expect(text).toContain("q2");
|
||||
expect(text).toContain("a2");
|
||||
});
|
||||
|
||||
it("labels the speakers, because the transcript's styling does not survive a clipboard", () => {
|
||||
const text = sessionToPlainText([turn("q1", "a1")]);
|
||||
|
||||
expect(text).toContain("**You**");
|
||||
expect(text).toContain("**Lam**");
|
||||
expect(text.indexOf("q1")).toBeLessThan(text.indexOf("a1"));
|
||||
});
|
||||
|
||||
it("reads oldest first, unlike the transcript", () => {
|
||||
const text = sessionToPlainText([turn("first", "a1"), turn("second", "a2")]);
|
||||
expect(text.indexOf("first")).toBeLessThan(text.indexOf("second"));
|
||||
});
|
||||
|
||||
it("includes the failure when a turn errored", () => {
|
||||
expect(sessionToPlainText([turn("q", "", "Ollama rejected the API key.")])).toContain(
|
||||
"Ollama rejected the API key.",
|
||||
|
||||
Reference in New Issue
Block a user