fix(studio): move AI generation behind short-lived job requests

This commit is contained in:
Clintchiz committed 2026-10-19 20:11:49 +05:30
1 parent e8c0f06d8f
commit 58687d8679
7 files changed
+248 -8

No files matched your search

+88
View File
@@ -319,3 +319,91 @@ test("a retry followed by an invalid design does not spend a third request or mi
expect(batch.diagnostics[0].code).toBe("WRN-STUDIO-PROPOSAL");
expect(batch.diagnostics[0].message).toContain("schema");
});
test("async generation acknowledges immediately and polling retrieves the validated batch", async () => {
let finish!: () => void;
let entered!: () => void;
const started = new Promise<void>((resolve) => {
entered = resolve;
});
const blocked = new Promise<void>((resolve) => {
finish = resolve;
});
const handler = studioAI(
"test-secret",
mockFetch(async () => {
entered();
await blocked;
return completion();
}),
);
const original = await request();
const headers = new Headers(original.headers);
headers.set("prefer", "respond-async");
const accepted = await handler(new Request(original, { headers }));
expect(accepted!.status).toBe(202);
const { job } = await accepted!.json();
await started;
const url = `https://components.example/design-studio/api/generate/jobs/${job.id}`;
expect((await (await handler(new Request(url)))!.json()).status).toBe(
"pending",
);
expect(
(await handler(
new Request(url, { headers: { origin: "https://other.example" } }),
))!.status,
).toBe(403);
finish();
let result: any;
for (let i = 0; i < 50; i++) {
result = await (await handler(new Request(url)))!.json();
if (result.status !== "pending") break;
await Bun.sleep(10);
}
expect(result.status).toBe("complete");
expect(result.result.alternatives).toHaveLength(3);
expect(
(await handler(
new Request(url.replace(job.id, "00000000-0000-4000-8000-000000000000")),
))!.status,
).toBe(410);
});
test("background generation cancellation aborts the provider and leaves no proposals", async () => {
let entered!: () => void;
const started = new Promise<void>((resolve) => {
entered = resolve;
});
let aborted = false;
const handler = studioAI(
"test-secret",
mockFetch(async (_url, init) => {
entered();
return await new Promise<Response>((_, reject) => {
init!.signal!.addEventListener(
"abort",
() => {
aborted = true;
reject(new DOMException("cancelled", "AbortError"));
},
{ once: true },
);
});
}),
);
const original = await request();
const headers = new Headers(original.headers);
headers.set("prefer", "respond-async");
const { job } = await (await handler(
new Request(original, { headers }),
))!.json();
await started;
const response = await handler(
new Request(
`https://components.example/design-studio/api/generate/jobs/${job.id}`,
{ method: "DELETE" },
),
);
expect((await response!.json()).status).toBe("cancelled");
expect(aborted).toBe(true);
});