feat: deploy portable workspace registry
This commit is contained in:
@@ -91,10 +91,29 @@ export function sessionRoutes(
|
||||
const locateSession = async (principal: PrincipalContext, id: string): Promise<LocatedSession | undefined> => {
|
||||
const runner = runnerFor(principal);
|
||||
// Dependency-injected runners in legacy route tests may model only the mutation under test.
|
||||
if (typeof runner.sessionShow !== "function") return {
|
||||
manifest: {}, workspaceConfigPath: (await d.workspaceRegistry.list())[0]?.snapshotPath ?? "",
|
||||
if (typeof runner.sessionShow !== "function") return { manifest: {}, workspaceConfigPath: "" };
|
||||
const legacySession = async (): Promise<LocatedSession | undefined> => {
|
||||
try {
|
||||
const manifest = await runner.sessionShow(id);
|
||||
return manifest && !manifest.workspace_id && !manifest.workspace_revision
|
||||
? { manifest, workspaceConfigPath: "" }
|
||||
: undefined;
|
||||
} catch (error) {
|
||||
if (isNotFound(error)) return undefined;
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
const revisions = await d.workspaceRegistry.list();
|
||||
let revisions: Awaited<ReturnType<typeof d.workspaceRegistry.list>>;
|
||||
try {
|
||||
revisions = await d.workspaceRegistry.list();
|
||||
} catch (registryError) {
|
||||
// Sessions created before revision pinning still live under the installation's legacy
|
||||
// default config. Keep that compatibility path available when a fresh installation has
|
||||
// no registry snapshot yet; a pinned session remains fail-closed below.
|
||||
const legacy = await legacySession();
|
||||
if (legacy) return legacy;
|
||||
throw registryError;
|
||||
}
|
||||
for (const revision of revisions) {
|
||||
if (revision.state !== "operational") continue;
|
||||
try {
|
||||
@@ -105,7 +124,7 @@ export function sessionRoutes(
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
return await legacySession();
|
||||
};
|
||||
|
||||
/** Read the durable pinned descriptor only after the owner-visible manifest is located. */
|
||||
@@ -240,15 +259,19 @@ export function sessionRoutes(
|
||||
|
||||
app.post("/sessions", async (req, reply) => {
|
||||
const b = req.body as {
|
||||
question: string; name?: string; workspaceId?: string;
|
||||
question: string; name?: string; workspace?: string; workspaceId?: string;
|
||||
provider?: string; model?: string; thinking?: string;
|
||||
};
|
||||
const principal = getPrincipal(req);
|
||||
let s: Settings;
|
||||
try { s = await d.getSettings(principal); } catch { return storageFailure(reply); }
|
||||
const runner = runnerFor(principal);
|
||||
const requestedWorkspaceId = b.workspaceId ?? s.workspace;
|
||||
if (!requestedWorkspaceId) {
|
||||
// `workspace` was the legacy request field before browser-local registry preferences.
|
||||
// It opts a pre-registry caller into the existing installation-default config only; modern
|
||||
// `workspaceId` and saved preferences must continue to resolve an immutable snapshot.
|
||||
const legacyWorkspaceRequest = typeof b.workspace === "string" && b.workspace.length > 0;
|
||||
const requestedWorkspaceId = b.workspaceId ?? (legacyWorkspaceRequest ? undefined : s.workspace);
|
||||
if (!requestedWorkspaceId && !legacyWorkspaceRequest) {
|
||||
return reply.code(409).send({
|
||||
error: WORKSPACE_REVISION_UNAVAILABLE_MESSAGE,
|
||||
code: "workspace_revision_unavailable",
|
||||
@@ -258,23 +281,25 @@ export function sessionRoutes(
|
||||
let workspaceId: string | undefined;
|
||||
let workspaceRevision: string | undefined;
|
||||
let allowedModels: readonly string[] | undefined;
|
||||
try {
|
||||
const resolved = await d.workspaceRegistry.read(requestedWorkspaceId);
|
||||
if (resolved.revision.state !== "operational") {
|
||||
if (requestedWorkspaceId) {
|
||||
try {
|
||||
const resolved = await d.workspaceRegistry.read(requestedWorkspaceId);
|
||||
if (resolved.revision.state !== "operational") {
|
||||
return reply.code(409).send({
|
||||
error: WORKSPACE_REVISION_UNAVAILABLE_MESSAGE,
|
||||
code: "workspace_revision_unavailable",
|
||||
});
|
||||
}
|
||||
workspaceConfigPath = resolved.revision.snapshotPath;
|
||||
workspaceId = resolved.revision.id;
|
||||
workspaceRevision = resolved.revision.commit;
|
||||
allowedModels = resolved.workspace.llm_policy.allowed;
|
||||
} catch {
|
||||
return reply.code(409).send({
|
||||
error: WORKSPACE_REVISION_UNAVAILABLE_MESSAGE,
|
||||
code: "workspace_revision_unavailable",
|
||||
});
|
||||
}
|
||||
workspaceConfigPath = resolved.revision.snapshotPath;
|
||||
workspaceId = resolved.revision.id;
|
||||
workspaceRevision = resolved.revision.commit;
|
||||
allowedModels = resolved.workspace.llm_policy.allowed;
|
||||
} catch {
|
||||
return reply.code(409).send({
|
||||
error: WORKSPACE_REVISION_UNAVAILABLE_MESSAGE,
|
||||
code: "workspace_revision_unavailable",
|
||||
});
|
||||
}
|
||||
const provider = b.provider ?? s.provider;
|
||||
const model = b.model ?? s.model;
|
||||
|
||||
Reference in New Issue
Block a user