feat(agent): 统一专业拆镜入口与真实镜头生成
This commit is contained in:
35
web/src/services/storyboard-submission.ts
Normal file
35
web/src/services/storyboard-submission.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { nanoid } from "nanoid";
|
||||
import { creationRuns, type CreationSubmission } from "./api/creation-runs";
|
||||
import type { CreateTaskInput } from "./api/task-center";
|
||||
|
||||
// Both the node composer and Agent submit the same quoted professional task.
|
||||
export async function submitStoryboardTask(request: CreateTaskInput, options: {
|
||||
signal: AbortSignal;
|
||||
assertCurrent: () => void;
|
||||
confirm: (submission: CreationSubmission) => Promise<boolean>;
|
||||
}, api = creationRuns) {
|
||||
const { signal, assertCurrent } = options;
|
||||
const detail = await api.create({ clientKey: `storyboard:${nanoid()}`, canvasId: request.projectId, state: { kind: "storyboard" } }, signal);
|
||||
const run = await api.claim(detail.run.id, { expectedEpoch: detail.run.executionEpoch, owner: `storyboard:${nanoid()}` }, signal);
|
||||
const guard = { executionEpoch: run.executionEpoch, owner: run.executionOwner };
|
||||
let connectionError: unknown;
|
||||
const heartbeat = setInterval(() => {
|
||||
void api.heartbeat(run.id, guard, signal).catch((error) => { connectionError = error; });
|
||||
}, 15_000);
|
||||
try {
|
||||
const submission = await api.prepare(run.id, { ...guard, itemKey: "storyboard", request }, signal);
|
||||
if (!await options.confirm(submission)) return undefined;
|
||||
signal.throwIfAborted();
|
||||
if (connectionError) throw connectionError;
|
||||
assertCurrent();
|
||||
if (Date.parse(submission.quote.expiresAt) <= Date.now()) throw new Error("分镜报价已过期,请重新发起拆镜并确认最新费用");
|
||||
const approved = await api.approve(run.id, { ...guard, submissionIds: [submission.id] }, signal);
|
||||
if (!approved.submissions.some((item) => item.id === submission.id && item.approvedAt)) throw new Error("费用确认回执不完整,尚未提交拆镜任务");
|
||||
signal.throwIfAborted();
|
||||
assertCurrent();
|
||||
return await api.execute(run.id, { ...guard, submissionId: submission.id }, signal);
|
||||
} finally {
|
||||
clearInterval(heartbeat);
|
||||
void api.release(run.id, guard).catch(() => { /* Offline leases expire on the server. */ });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user