refactor: stop persisting workspace state in the browser

This commit is contained in:
2026-08-14 17:43:10 +02:00
parent 3978008aed
commit fd3b62ce6f
11 changed files with 101 additions and 310 deletions
+15 -13
View File
@@ -6,8 +6,9 @@ import {
renameSession, setSessionGroup, archiveSession, unarchiveSession,
deleteSession, getSessionDocuments,
} from "./sessions";
import { workspacePreferences } from "../workspaces/preferences";
test("createSession migrates legacy selections and POSTs browser preferences", async () => {
test("createSession seeds ephemeral selections and posts them", async () => {
localStorage.clear();
let body: unknown = null;
server.use(
@@ -33,15 +34,16 @@ test("createSession migrates legacy selections and POSTs browser preferences", a
expect(body).toEqual({
question: "q", workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low",
});
expect(JSON.parse(localStorage.getItem("thothii.workspace-registry.v1.preferences")!)).toEqual({
expect(workspacePreferences.load()).toEqual({
workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low",
});
expect(localStorage.getItem("thothii.workspace-registry.v1.preferences")).toBeNull();
});
test("createSession does not POST when a selected summary aliases another workspace name", async () => {
localStorage.setItem("thothii.workspace-registry.v1.preferences", JSON.stringify({
workspacePreferences.save({
workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low",
}));
});
let posted = false;
server.use(
http.get("/api/workspaces", () => HttpResponse.json([{
@@ -74,9 +76,9 @@ test.each([
["an unknown revision field", { generation: 1 }],
["a malformed revision", { commit: "not-a-commit" }],
])("createSession does not POST when the selected summary revision has %s", async (_case, revisionPatch) => {
localStorage.setItem("thothii.workspace-registry.v1.preferences", JSON.stringify({
workspacePreferences.save({
workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low",
}));
});
const revision = {
id: "psd-clinical", commit: "a".repeat(40), blob: "b".repeat(40),
snapshotPath: "/snapshot", ...revisionPatch,
@@ -107,10 +109,10 @@ test.each([
expect(posted).toBe(false);
});
test("createSession replaces a stale browser workspace with the current installation default", async () => {
localStorage.setItem("thothii.workspace-registry.v1.preferences", JSON.stringify({
test("createSession replaces a stale ephemeral workspace with the current installation default", async () => {
workspacePreferences.save({
workspaceId: "retired-workspace", provider: "zai", model: "glm-5.2", thinking: "low",
}));
});
let body: unknown;
server.use(
http.get("/api/settings", () => HttpResponse.json({ workspace: "psd-clinical" })),
@@ -137,15 +139,15 @@ test("createSession replaces a stale browser workspace with the current installa
question: "q", workspaceId: "psd-clinical",
provider: "zai", model: "glm-5.2", thinking: "low",
});
expect(JSON.parse(localStorage.getItem("thothii.workspace-registry.v1.preferences")!)).toEqual({
expect(workspacePreferences.load()).toEqual({
workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low",
});
});
test("createSession preserves a local legacy selection when the registry is empty", async () => {
localStorage.setItem("thothii.workspace-registry.v1.preferences", JSON.stringify({
workspacePreferences.save({
workspaceId: "legacy-workspace", provider: "zai", model: "glm-5.2", thinking: "low",
}));
});
let body: unknown;
server.use(
http.get("/api/workspaces", () => HttpResponse.json([])),
@@ -182,7 +184,7 @@ test("createSession rejects a workspace summary that omits the canonical revisio
);
await expect(createSession({ question: "q" })).rejects.toMatchObject({
message: "Could not load selected workspace policy. Please retry.",
message: "Could not load workspace registry. Please retry.",
});
expect(posted).toBe(false);
});
+2 -2
View File
@@ -15,8 +15,8 @@ async function selectedPreferences(): Promise<WorkspacePreference> {
const saved = workspacePreferences.load();
if (saved.workspaceId && saved.provider && saved.model && saved.thinking) return saved;
// A direct new-session entry point can run before the composer has mounted. Seed its
// browser-local preferences from the legacy read-only defaults once, then keep them local.
// A direct new-session entry point can run before the composer has mounted. Seed current
// application memory from the installation defaults once, then keep choices ephemeral.
const legacy = await getSettings();
return workspacePreferences.save({
workspaceId: saved.workspaceId ?? legacy.workspace,