feat: harden runtime readiness and session workflow
This commit is contained in:
@@ -28,6 +28,7 @@ test("POST /sessions usa i settings (workspace/provider/model/thinking) e crea+a
|
||||
}), {
|
||||
thtRunner: {
|
||||
ollamaEnsure: async () => ({ ok: true }),
|
||||
searchPack: async () => {},
|
||||
sessionNew: async (o: any) => { sessionNewArg = o; return { id: "s1" }; },
|
||||
sessionList: async () => [{ id: "s1" }],
|
||||
} as any,
|
||||
@@ -50,6 +51,7 @@ test("POST /sessions/:id/response inoltra al bridge (no error)", async () => {
|
||||
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
||||
thtRunner: {
|
||||
ollamaEnsure: async () => ({ ok: true }),
|
||||
searchPack: async () => {},
|
||||
sessionNew: async () => ({ id: "s1" }),
|
||||
sessionList: async () => [],
|
||||
} as any,
|
||||
@@ -134,6 +136,7 @@ test("POST /sessions refuses with 503 when ollamaEnsure fails (no session create
|
||||
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
||||
thtRunner: {
|
||||
ollamaEnsure: async () => ({ ok: false, stage: "model", error: "modello non installato" }),
|
||||
searchPack: async () => {},
|
||||
sessionNew: async () => { createdCalled = true; return { id: "s1" }; },
|
||||
} as any,
|
||||
getSettings: () => ({ workspace: "psd" }) as any,
|
||||
@@ -150,6 +153,7 @@ test("POST /sessions proceeds when ollamaEnsure succeeds", async () => {
|
||||
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
||||
thtRunner: {
|
||||
ollamaEnsure: async (ws: string) => { ensureWs = ws; return { ok: true }; },
|
||||
searchPack: async () => {},
|
||||
sessionNew: async () => ({ id: "s1" }),
|
||||
} as any,
|
||||
getSettings: () => ({ workspace: "psd" }) as any,
|
||||
@@ -183,3 +187,59 @@ test("POST /sessions/:id/resume refuses with 503 when ollamaEnsure fails", async
|
||||
const res = await app.inject({ method: "POST", url: "/sessions/s1/resume" });
|
||||
expect(res.statusCode).toBe(503);
|
||||
});
|
||||
|
||||
test("POST /runtime/prewarm returns 202 without awaiting readiness", async () => {
|
||||
let workspace: string | undefined;
|
||||
let finish!: (value: any) => void;
|
||||
const pending = new Promise((resolve) => { finish = resolve; });
|
||||
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
||||
thtRunner: {} as any,
|
||||
readiness: {
|
||||
ensure: (ws: string) => { workspace = ws; return pending; },
|
||||
} as any,
|
||||
getSettings: () => ({ workspace: "psd" }) as any,
|
||||
});
|
||||
const res = await app.inject({ method: "POST", url: "/runtime/prewarm" });
|
||||
expect(res.statusCode).toBe(202);
|
||||
expect(res.json()).toEqual({ status: "warming" });
|
||||
expect(workspace).toBe("psd");
|
||||
finish({ ok: true });
|
||||
});
|
||||
|
||||
test("POST /sessions returns after bridge attachment but starts only after retrieval", async () => {
|
||||
let finishPack!: () => void;
|
||||
const pack = new Promise<void>((resolve) => { finishPack = resolve; });
|
||||
let bridgeAttached = false;
|
||||
let started = false;
|
||||
const bridge = {
|
||||
onClientEvent: () => { bridgeAttached = true; },
|
||||
emitClientEvent: () => {},
|
||||
};
|
||||
const runtime = { bridge } as any;
|
||||
const mgr = {
|
||||
createFor: () => runtime,
|
||||
configure: async () => {},
|
||||
start: () => {
|
||||
expect(bridgeAttached).toBe(true);
|
||||
started = true;
|
||||
},
|
||||
teardown: () => {},
|
||||
} as any;
|
||||
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
||||
mgr,
|
||||
thtRunner: {
|
||||
ollamaEnsure: async () => ({ ok: true }),
|
||||
sessionNew: async () => ({ id: "s-early" }),
|
||||
searchPack: async () => pack,
|
||||
} as any,
|
||||
getSettings: () => ({ workspace: "psd" }) as any,
|
||||
});
|
||||
|
||||
const res = await app.inject({ method: "POST", url: "/sessions", payload: { question: "q" } });
|
||||
expect(res.json()).toEqual({ id: "s-early" });
|
||||
expect(bridgeAttached).toBe(true);
|
||||
expect(started).toBe(false);
|
||||
finishPack();
|
||||
await new Promise((resolve) => setImmediate(resolve));
|
||||
expect(started).toBe(true);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user