fix(agent): 创作执行 - 修复会话恢复并校验画风与真实分镜行

This commit is contained in:
王志伟
2026-09-08 22:24:17 +08:00
parent 2856bc7f58
commit 45de256deb
13 changed files with 179 additions and 27 deletions

View File

@@ -30,6 +30,56 @@ const proposal = { id: "p", version: 1, title: "方案", summary: "摘要", mark
const submission = (id: string, itemKey: string, taskId?: string): CreationSubmission => ({ id, runId: "run", itemKey, requestHash: "hash", taskId, quote: { model: "model", billingMode: "fixed_request", quantity: 1, amountMicrocredits: 1, estimated: false, expiresAt: "2099-01-01", quoteHash: "quote" } });
describe("创作控制器恢复", () => {
for (const terminal of [true, false]) test(terminal ? "任务已失败时标记生成失败,不能引导反复读取" : "仅查询断线时保留结果恢复语义,不当作需要重做", async () => {
const h = harness({ ...initialCreativeState(), proposal, canvasApplied: true, media: [{ ref: "a", nodeId: "a", attempt: 1, submissionId: "a", taskId: "a", status: "queued" }] }, "waiting_task", [submission("a", "a", "a")], async (_id, options) => {
if (terminal) options?.onTaskUpdate?.({ id: "a", status: "failed" } as GenerationTask);
throw new Error("网络异常。");
});
try { await h.controller.load("run"); await expect(h.controller.resume()).rejects.toThrow(); expect(h.view().state.media[0].failureKind).toBe(terminal ? "generation" : "observation"); expect(h.counters().executions).toBe(0); }
finally { h.controller.dispose(); }
});
test("刷新页面可接续仍有效的旧连接,不等待旧页面租约过期", async () => {
const h = harness(initialCreativeState());
const get = h.api.get, claim = h.api.claim;
let foreign = true, claims = 0;
h.api.get = async (...args) => { const detail = await get(...args); return foreign ? { ...detail, run: { ...detail.run, executionOwner: "previous-page", leaseExpiresAt: "2099-01-01" } } : detail; };
h.api.claim = async (...args) => { claims++; foreign = false; return claim(...args); };
try { await h.controller.load("run"); expect(h.view().hasControl).toBe(true); expect(claims).toBe(1); expect(h.counters().executions).toBe(0); }
finally { h.controller.dispose(); }
});
test("普通恢复不争抢其他连接,用户重试连接可以显式接续", async () => {
const h = harness(initialCreativeState());
const get = h.api.get, claim = h.api.claim;
let foreign = false, claims = 0;
h.api.get = async (...args) => { const detail = await get(...args); return foreign ? { ...detail, run: { ...detail.run, executionOwner: "other-page", leaseExpiresAt: "2099-01-01" } } : detail; };
h.api.claim = async (...args) => { claims++; foreign = false; return claim(...args); };
try {
await h.controller.load("run"); foreign = true;
await expect(h.controller.refresh()).rejects.toThrow("重试连接"); expect(claims).toBe(1);
await h.controller.takeControl(); expect(claims).toBe(2); expect(h.view().hasControl).toBe(true); expect(h.view().error).toBeUndefined();
} finally { h.controller.dispose(); }
});
test("已提交任务即使保留待处理批次也不能再次展示费用确认", async () => {
const h = harness({ ...initialCreativeState(), proposal, canvasApplied: true, pendingPayment: ["a"], media: [{ ref: "a", nodeId: "a", attempt: 1, submissionId: "a", taskId: "task-a", status: "queued" }] }, "waiting_task", [{ ...submission("a", "a", "task-a"), approvedAt: "2026-01-01" }]);
try { await h.controller.load("run"); expect(h.view().quote).toBeUndefined(); }
finally { h.controller.dispose(); }
});
test("部分提交后费用卡只保留未提交项", async () => {
const h = harness({ ...initialCreativeState(), pendingPayment: ["a", "b"] }, "paused", [submission("a", "a", "task-a"), submission("b", "b")]);
try { await h.controller.load("run"); expect(h.view().quote?.items.map((item) => item.id)).toEqual(["b"]); }
finally { h.controller.dispose(); }
});
test("迟到的确认点击复用已提交任务,不重新批准或刷新过期费用", async () => {
const old = { ...submission("a", "a", "task-a"), approvedAt: "2000-01-01" };
old.quote.expiresAt = "2000-01-01";
const completed = { id: "task-a", status: "succeeded", resultJson: JSON.stringify({ images: [{ storageKey: "resource:output" }] }) } as GenerationTask;
const h = harness({ ...initialCreativeState(), proposal, canvasApplied: true, pendingPayment: ["a"], media: [{ ref: "a", nodeId: "a", attempt: 1, submissionId: "a", taskId: "task-a", status: "queued" }] }, "waiting_task", [old], async () => completed);
h.api.approve = async () => { throw new Error("不应重新批准已提交任务"); };
h.api.refreshQuote = async () => { throw new Error("不应刷新已提交任务报价"); };
h.api.execute = async (_id, input) => { expect(input.submissionId).toBe("a"); return completed; };
try { await h.controller.load("run"); await h.controller.approvePayment(); expect(h.view().state.media[0].status).toBe("ready"); expect(h.view().quote).toBeUndefined(); expect(h.counters().prepares).toBe(0); }
finally { h.controller.dispose(); }
});
test("更新过期报价替换分析关联并等待新批准,不执行模型", async () => {
const old = submission("old", "planning:key");
const fresh = submission("fresh", "requote:old");