fix(backend): check read-only 409 before the Ollama preflight on resume

This commit is contained in:
2026-06-29 20:06:03 +02:00
parent 90a26dafce
commit a791919925
3 changed files with 17 additions and 5 deletions
+2 -2
View File
@@ -50,12 +50,12 @@ export function sessionRoutes(
});
app.post("/sessions/:id/resume", async (req, reply) => {
const id = (req.params as any).id;
const ensure = await d.tht.ollamaEnsure(d.getSettings().workspace ?? "", d.ollamaEnsureTimeoutSec);
if (!ensure.ok) return reply.code(503).send({ error: ensure.error ?? "Ollama/embeddings non disponibili" });
const manifest = (await d.tht.sessionShow(id)) as { status?: string; archived?: boolean } | null;
if (manifest?.status === "finalized" || manifest?.archived) {
return reply.code(409).send({ error: "sessione in sola lettura (finalizzata o archiviata)" });
}
const ensure = await d.tht.ollamaEnsure(d.getSettings().workspace ?? "", d.ollamaEnsureTimeoutSec);
if (!ensure.ok) return reply.code(503).send({ error: ensure.error ?? "Ollama/embeddings non disponibili" });
const rt = await d.mgr.resume(id, d.tht);
rt.bridge.onClientEvent((e) => d.hub.publish(id, e.type, e));
return reply.code(200).send({ id });
+11
View File
@@ -152,6 +152,17 @@ test("POST /sessions proceeds when ollamaEnsure succeeds", async () => {
expect(ensureWs).toBe("psd");
});
test("POST /sessions/:id/resume returns 409 for a read-only session without calling ollamaEnsure", async () => {
let ensureCalled = false;
const app = mutApp({
sessionShow: async () => ({ status: "finalized", archived: false }),
ollamaEnsure: async () => { ensureCalled = true; return { ok: false, error: "down" }; },
});
const res = await app.inject({ method: "POST", url: "/sessions/s1/resume" });
expect(res.statusCode).toBe(409);
expect(ensureCalled).toBe(false);
});
test("POST /sessions/:id/resume refuses with 503 when ollamaEnsure fails", async () => {
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
thtRunner: {
@@ -103,9 +103,10 @@ and the start spawn behind a seam.
The preflight runs **first**, before any session is created or resumed:
- `POST /sessions`: `const r = await tht.ollamaEnsure(settings.workspace, timeout)`. If `!r.ok`
→ `reply.code(503).send({ error: r.error })` and **return** (do NOT call `sessionNew`/`spawnFor`).
- `POST /sessions/:id/resume`: same preflight **before** the existing finalized/archived guard
and `mgr.resume`. On failure → 503, no spawn. (Uses the session's workspace — the current
configured/settings workspace, consistent with how resume resolves the session.)
- `POST /sessions/:id/resume`: the finalized/archived guard runs **first** — a read-only session
is rejected with 409 without touching Ollama. The preflight runs **after** that guard and
**before** `mgr.resume`. On failure → 503, no spawn. (Uses the session's workspace — the
current configured/settings workspace, consistent with how resume resolves the session.)
### Config ([config.ts](../../../backend/src/config.ts))
- `ollamaEnsureTimeoutMs: number` from `OLLAMA_ENSURE_TIMEOUT_MS` (default `60000`); passed to