1import { describe, expect, it } from "vite-plus/test";
2import { formatThreadTitleContext, limitTitleMessage } from "./threadTitleContext.ts";
3
4describe("thread title context", () => {
5 it("keeps a user's scope change despite long assistant output", () => {
6 const result = formatThreadTitleContext([
7 { role: "user", text: "Review QR sharing" },
8 { role: "assistant", text: "Old findings. ".repeat(2_000) },
9 { role: "user", text: "Focus on pairing expiry instead. Keep remote access working." },
10 { role: "assistant", text: "Implementation details. ".repeat(2_000) },
11 { role: "user", text: "Merge it when green." },
12 ]);
13 expect(result.message.length).toBeLessThanOrEqual(8_000);
14 expect(result.message).toContain("USER:\nReview QR sharing");
15 expect(result.message).toContain(
16 "USER:\nFocus on pairing expiry instead. Keep remote access working.",
17 );
18 expect(result.message).toContain("USER:\nMerge it when green.");
19 expect(result.message).toContain("ASSISTANT:\nImplementation details.");
20 });
21
22 it("retains both ends and role labels in long user messages", () => {
23 const result = formatThreadTitleContext([
24 { role: "system", text: "System instructions" },
25 { role: "user", text: `Fix Android pairing. ${"logs ".repeat(3_000)}Keep iOS behavior.` },
26 { role: "assistant", text: "Found the cause." },
27 ]);
28 expect(result.message).toContain("USER:\nFix Android pairing.");
29 expect(result.message).toContain("Keep iOS behavior.");
30 expect(result.message).toContain("ASSISTANT:\nFound the cause.");
31 expect(result.message).not.toContain("System instructions");
32 expect(result.message.match(/USER:/g)).toHaveLength(1);
33 });
34
35 it("preserves short conversations unchanged and handles tiny budgets", () => {
36 expect(
37 formatThreadTitleContext([
38 { role: "user", text: "Fix pairing" },
39 { role: "assistant", text: "The QR token expired." },
40 ]).message,
41 ).toBe("USER:\nFix pairing\n\nASSISTANT:\nThe QR token expired.");
42 expect(limitTitleMessage("x".repeat(100), 0)).toBe("");
43 for (let budget = 1; budget < 40; budget++) {
44 expect(limitTitleMessage("x".repeat(100), budget).length).toBeLessThanOrEqual(budget);
45 }
46 expect(formatThreadTitleContext([])).toEqual({ message: "", attachments: [] });
47 });
48
49 it("omits reasoning traces from generated titles", () => {
50 expect(
51 formatThreadTitleContext([
52 { role: "user", text: "Fix pairing" },
53 { role: "reasoning", text: "Consider token expiry, then the QR payload." },
54 { role: "assistant", text: "The QR token expired." },
55 ]).message,
56 ).toBe("USER:\nFix pairing\n\nASSISTANT:\nThe QR token expired.");
57 });
58});