feat: display toggles, smart session resume, fix stale transcript pane (#8)

This commit was merged in pull request #8.
This commit is contained in:
2026-10-03 21:22:04 +00:00
parent ffe2c6b7ed
commit ee96f1ee61
8 changed files with 304 additions and 73 deletions
+87
View File
@@ -0,0 +1,87 @@
import { describe, expect, it } from "vitest";
import { DEFAULT_HOST, DEFAULT_MODEL } from "../lib/constants";
import { describeResumeTimeout, resolvePreferences, resolveResumeTimeout } from "../lib/preferences";
const MINUTE = 60_000;
const HOUR = 60 * MINUTE;
const DAY = 24 * HOUR;
describe("resolveResumeTimeout", () => {
it("maps each configured window", () => {
expect(resolveResumeTimeout("15m")).toBe(15 * MINUTE);
expect(resolveResumeTimeout("1h")).toBe(HOUR);
expect(resolveResumeTimeout("6h")).toBe(6 * HOUR);
expect(resolveResumeTimeout("1d")).toBe(DAY);
});
it("returns undefined for 'never', which means always reopen the last chat", () => {
expect(resolveResumeTimeout("never")).toBeUndefined();
});
it("returns undefined for missing or unrecognised values rather than guessing", () => {
expect(resolveResumeTimeout(undefined)).toBeUndefined();
expect(resolveResumeTimeout("")).toBeUndefined();
expect(resolveResumeTimeout("banana")).toBeUndefined();
});
it("tolerates surrounding whitespace", () => {
expect(resolveResumeTimeout(" 15m ")).toBe(15 * MINUTE);
});
});
describe("describeResumeTimeout", () => {
it("names the never case rather than showing a number", () => {
expect(describeResumeTimeout(undefined)).toContain("Never");
});
it("describes minutes, hours, and days", () => {
expect(describeResumeTimeout(15 * MINUTE)).toBe("After 15 minutes");
expect(describeResumeTimeout(HOUR)).toBe("After 1 hour");
expect(describeResumeTimeout(6 * HOUR)).toBe("After 6 hours");
expect(describeResumeTimeout(DAY)).toBe("After 1 day");
});
});
describe("resolvePreferences", () => {
it("fills in every optional value", () => {
const resolved = resolvePreferences({});
expect(resolved.model).toBe(DEFAULT_MODEL);
expect(resolved.host).toBe(DEFAULT_HOST);
expect(resolved.webEnabled).toBe(true);
expect(resolved.showToolCalls).toBe(true);
expect(resolved.showReasoning).toBe(true);
expect(resolved.think).toBeUndefined();
expect(resolved.resumeTimeoutMs).toBe(HOUR);
});
it("honours the display toggles being switched off", () => {
const resolved = resolvePreferences({ showToolCalls: false, showReasoning: false });
expect(resolved.showToolCalls).toBe(false);
expect(resolved.showReasoning).toBe(false);
});
it("treats an unknown model or host as unset", () => {
const resolved = resolvePreferences({ model: " ", ollamaHost: "" });
expect(resolved.model).toBe(DEFAULT_MODEL);
expect(resolved.host).toBe(DEFAULT_HOST);
});
it("keeps a local Ollama host", () => {
expect(resolvePreferences({ ollamaHost: "http://localhost:11434" }).host).toBe(
"http://localhost:11434",
);
});
it("treats reasoning 'off' as disabled", () => {
expect(resolvePreferences({ thinking: "off" }).think).toBeUndefined();
expect(resolvePreferences({ thinking: "high" }).think).toBe("high");
});
it("carries the resume window through, including never", () => {
expect(resolvePreferences({ resumeTimeout: "15m" }).resumeTimeoutMs).toBe(15 * MINUTE);
expect(resolvePreferences({ resumeTimeout: "never" }).resumeTimeoutMs).toBeUndefined();
});
});