feat: pin sessions to workspace revisions

This commit is contained in:
2026-08-04 05:05:20 +02:00
parent 90894176b6
commit 301db4bd85
14 changed files with 288 additions and 54 deletions
+11 -2
View File
@@ -6,16 +6,25 @@ import {
deleteSession, getSessionDocuments,
} from "./sessions";
test("createSession POSTs only {question} and returns the id", async () => {
test("createSession migrates legacy selections and POSTs browser preferences", async () => {
localStorage.clear();
let body: unknown = null;
server.use(
http.get("http://localhost:8787/settings", () => HttpResponse.json({
workspace: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low",
})),
http.post("http://localhost:8787/sessions", async ({ request }) => {
body = await request.json();
return HttpResponse.json({ id: "s1" });
}),
);
expect(await createSession({ question: "q" })).toEqual({ id: "s1" });
expect(body).toEqual({ question: "q" });
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({
workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low",
});
});
test.each([202, 204])("prewarmRuntime accepts a body-less %s response", async (status) => {
+26 -2
View File
@@ -1,10 +1,34 @@
import { apiFetch } from "./client";
import { getSettings } from "./settings";
import { workspacePreferences, type WorkspacePreference } from "../workspaces/preferences";
import type {
Principal, ResumeSessionResult, SessionScope, SessionSummary, SessionDocument, UiResponse,
} from "./types";
export const createSession = (i: { question: string; name?: string }) =>
apiFetch<{ id: string }>("/sessions", { method: "POST", body: JSON.stringify(i) });
type NewSessionInput = { question: string; name?: string } & Partial<WorkspacePreference>;
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.
const legacy = await getSettings();
return workspacePreferences.save({
workspaceId: saved.workspaceId ?? legacy.workspace,
provider: saved.provider ?? legacy.provider,
model: saved.model ?? legacy.model,
thinking: saved.thinking ?? legacy.thinking,
});
}
export async function createSession(i: NewSessionInput) {
const preferences = await selectedPreferences();
return apiFetch<{ id: string }>("/sessions", {
method: "POST",
body: JSON.stringify({ ...preferences, ...i }),
});
}
/** Best-effort warm-up; callers must not await it before showing the composer. */
export const prewarmRuntime = () =>