feat: publish Agent Studio integrations and setup guide
This commit is contained in:
@@ -29,6 +29,62 @@ async function fixture() {
|
||||
}
|
||||
|
||||
describe("durable image video tasks", () => {
|
||||
it("continues an orphaned uploaded task locally without losing receipts or automatically submitting", async () => {
|
||||
const f = await fixture(); const task = await f.service.create("ses_owner", f.draft);
|
||||
await f.service.upload("ses_owner", task.id); await f.service.refresh(task.id);
|
||||
const path = join(f.options.root, task.id, "record.json");
|
||||
const before = JSON.parse(await readFile(path, "utf8")) as ImageVideoRecord;
|
||||
f.calls.length = 0;
|
||||
const restored = new harness.ImageVideoService(f.options);
|
||||
const result = await restored.continueTask("ses_new", task.id, before.revision, () => false, () => {});
|
||||
expect(result).toMatchObject({ id: task.id, state: "awaiting_submission", revision: before.revision + 1 });
|
||||
expect(f.calls).toEqual([]);
|
||||
const after = JSON.parse(await readFile(path, "utf8")) as ImageVideoRecord;
|
||||
expect(after).toMatchObject({ ownerSessionId: "ses_new", draft: before.draft, referenceHash: before.referenceHash, requestHash: before.requestHash, upload: before.upload, assetId: "asset_1" });
|
||||
expect(after.continuations).toHaveLength(1);
|
||||
expect(after.continuations?.[0]).toMatchObject({ fromSessionId: "ses_owner", toSessionId: "ses_new", revision: before.revision });
|
||||
expect(Number.isFinite(Date.parse(after.continuations?.[0]?.at ?? ""))).toBe(true);
|
||||
await expect(restored.owned("ses_owner", task.id)).rejects.toMatchObject({ code: "I2V_TASK_NOT_FOUND" });
|
||||
expect((await restored.owned("ses_new", task.id)).id).toBe(task.id);
|
||||
await restored.submit("ses_new", task.id);
|
||||
expect(f.calls).toEqual(["identity", "submit"]);
|
||||
expect(JSON.stringify(result)).not.toMatch(/ownerSessionId|continuations|uploadUrl/);
|
||||
});
|
||||
it("rejects active-owner takeover, stale confirmation, uncertain state and concurrent continuation", async () => {
|
||||
const f = await fixture(); const task = await f.service.create("ses_owner", f.draft);
|
||||
await expect(f.service.continueTask("ses_new", task.id, 0, () => true, () => {})).rejects.toMatchObject({ code: "I2V_OWNER_ACTIVE" });
|
||||
await expect(f.service.continueTask("ses_new", task.id, 99, () => false, () => {})).rejects.toMatchObject({ code: "I2V_STALE_REVISION" });
|
||||
const attempts = await Promise.allSettled([f.service.continueTask("ses_new", task.id, 0, () => false, () => {}), f.service.continueTask("ses_other", task.id, 0, () => false, () => {})]);
|
||||
expect(attempts.map(a => a.status)).toEqual(["fulfilled", "rejected"]);
|
||||
const path = join(f.options.root, task.id, "record.json");
|
||||
const record = JSON.parse(await readFile(path, "utf8")) as ImageVideoRecord;
|
||||
for (const state of ["unknown_upload", "unknown_submission", "failed", "queued"] as const) {
|
||||
await writeFile(path, JSON.stringify({ ...record, state }));
|
||||
await expect(f.service.continueTask("ses_new", task.id, record.revision, () => false, () => {})).rejects.toMatchObject({ code: "I2V_CONTINUE_BLOCKED" });
|
||||
expect((JSON.parse(await readFile(path, "utf8")) as ImageVideoRecord).state).toBe(state);
|
||||
}
|
||||
expect(f.calls).toEqual([]);
|
||||
});
|
||||
it("reuses a verified existing image without PUT, finalize or automatic generation and persists it across restart", async () => {
|
||||
const f = await fixture(); const task = await f.service.create("ses_owner", f.draft);
|
||||
f.remote.initialize = () => { f.calls.push("initialize"); return Promise.resolve({ reused: true as const, assetId: "existing_asset" }); };
|
||||
expect((await f.service.upload("ses_owner", task.id)).state).toBe("awaiting_submission");
|
||||
expect(f.calls).toEqual(["identity", "initialize"]);
|
||||
const restored = new harness.ImageVideoService(f.options);
|
||||
expect((await restored.view(task.id)).state).toBe("awaiting_submission");
|
||||
expect((await restored.submit("ses_owner", task.id)).jobId).toBe("remote_job_1");
|
||||
expect(f.calls).not.toContain("put"); expect(f.calls).not.toContain("finalize");
|
||||
});
|
||||
it("persists a sanitized failure stage while keeping rejected uploads quarantined", async () => {
|
||||
const f = await fixture(); const task = await f.service.create("ses_owner", f.draft);
|
||||
f.remote.initialize = () => Promise.reject(new harness.HarnessError("I2V_REMOTE_REJECTED", "secret signed URL"));
|
||||
const result = await f.service.upload("ses_owner", task.id);
|
||||
expect(result).toMatchObject({ state: "unknown_upload" });
|
||||
expect(result.error).toContain("initializing_upload/I2V_REMOTE_REJECTED");
|
||||
expect(result.error).not.toContain("secret");
|
||||
expect((await new harness.ImageVideoService(f.options).view(task.id)).error).toBe(result.error);
|
||||
expect(f.calls).not.toContain("put");
|
||||
});
|
||||
it("copies a local reference without transmitting it and hides private bindings", async () => {
|
||||
const f = await fixture(); const task = await f.service.create("ses_owner", f.draft);
|
||||
expect(f.calls).toEqual([]); expect(task.state).toBe("draft");
|
||||
@@ -65,6 +121,16 @@ describe("durable image video tasks", () => {
|
||||
record.state = "submitting"; await writeFile(file, JSON.stringify(record));
|
||||
expect((await new harness.ImageVideoService(f.options).view(task.id)).state).toBe("unknown_submission");
|
||||
});
|
||||
it("records a typed submission rejection without exposing provider details or retrying", async () => {
|
||||
const f = await fixture(); const task = await f.service.create("ses_owner", f.draft);
|
||||
await f.service.upload("ses_owner", task.id); await f.service.refresh(task.id);
|
||||
f.remote.submit = () => Promise.reject(new harness.HarnessError("I2V_REMOTE_REJECTED", "secret upstream detail"));
|
||||
const result = await f.service.submit("ses_owner", task.id);
|
||||
expect(result.error).toContain("submitting/I2V_REMOTE_REJECTED");
|
||||
expect(result.error).not.toContain("secret");
|
||||
expect(result.state).toBe("unknown_submission");
|
||||
await expect(f.service.submit("ses_owner", task.id)).rejects.toMatchObject({ code: "I2V_UNKNOWN_SUBMISSION" });
|
||||
});
|
||||
it("never reinitializes uncertain uploads and blocks stale persisted revisions", async () => {
|
||||
const f = await fixture(); const task = await f.service.create("ses_owner", f.draft);
|
||||
f.remote.initialize = () => { f.calls.push("initialize"); return Promise.reject(new Error("timeout")); };
|
||||
|
||||
Reference in New Issue
Block a user