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
+45
View File
@@ -17,6 +17,9 @@ export interface LamPreferences {
systemPrompt?: string;
webSearchEnabled?: boolean;
thinking?: string;
showToolCalls?: boolean;
showReasoning?: boolean;
resumeTimeout?: string;
}
/** Preferences with every optional value filled in, so callers never branch on undefined. */
@@ -28,6 +31,43 @@ export interface ResolvedPreferences {
webEnabled: boolean;
/** Undefined when reasoning is off, which is what the API client expects. */
think?: string;
/** Whether the transcript lists the tools Lam called. */
showToolCalls: boolean;
/** Whether the transcript includes the model's thinking trace. */
showReasoning: boolean;
/** Idle time after which opening the command starts a fresh chat. Undefined means never. */
resumeTimeoutMs?: number;
}
const MINUTE = 60_000;
const HOUR = 60 * MINUTE;
const DAY = 24 * HOUR;
/** Keep in sync with the `resumeTimeout` dropdown in `package.json`. */
const RESUME_TIMEOUTS: Record<string, number> = {
"15m": 15 * MINUTE,
"1h": HOUR,
"6h": 6 * HOUR,
"1d": DAY,
};
/** `undefined` for "never" and for anything unrecognised, which both mean "always reopen the last chat". */
export function resolveResumeTimeout(value: string | undefined): number | undefined {
return RESUME_TIMEOUTS[(value ?? "").trim()];
}
/** Human-readable form of {@link ResolvedPreferences.resumeTimeoutMs}, for the setup screen. */
export function describeResumeTimeout(milliseconds: number | undefined): string {
if (milliseconds === undefined) return "Never — always reopen the last chat";
const minutes = Math.round(milliseconds / MINUTE);
if (minutes < 60) return `After ${minutes} minutes`;
const hours = Math.round(minutes / 60);
if (hours < 24) return `After ${hours} hour${hours === 1 ? "" : "s"}`;
const days = Math.round(hours / 24);
return `After ${days} day${days === 1 ? "" : "s"}`;
}
export function resolvePreferences(raw: LamPreferences): ResolvedPreferences {
@@ -41,6 +81,11 @@ export function resolvePreferences(raw: LamPreferences): ResolvedPreferences {
// Defaults to on: the preference is a checkbox the user has to actively untick.
webEnabled: raw.webSearchEnabled ?? true,
think: thinking && thinking !== "off" ? thinking : undefined,
showToolCalls: raw.showToolCalls ?? true,
showReasoning: raw.showReasoning ?? true,
// Falls back to the manifest's declared default, so a missing preference
// behaves the same whether Vicinae substitutes it or not.
resumeTimeoutMs: resolveResumeTimeout(raw.resumeTimeout ?? "1h"),
};
}