feat(runtime): 即梦本机运行时 - 接入安全生成闭环与桌面本机渠道
Refs #225 Co-authored-by: zkhyww <127009345+zkhyww@users.noreply.github.com>
This commit is contained in:
110
web/test/generation-task-durability.node.test.ts
Normal file
110
web/test/generation-task-durability.node.test.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { test } from "node:test";
|
||||
|
||||
import type { GenerationTask } from "../src/services/api/task-center";
|
||||
import { applyGenerationConsumerEffect } from "../src/services/generation-consumer-dedupe";
|
||||
import { createGenerationTaskMaterializer, type GenerationTaskEffectResult, type GenerationTaskEffectStore } from "../src/services/generation-task-materializer";
|
||||
|
||||
test("node message and agent consumers receive stable effect keys across three replays", async () => {
|
||||
const completed = new Map<string, GenerationTaskEffectResult>();
|
||||
const claimed = new Set<string>();
|
||||
const effects: GenerationTaskEffectStore = {
|
||||
async claim(effectKey) {
|
||||
const result = completed.get(effectKey);
|
||||
if (result) return { status: "completed", result };
|
||||
if (claimed.has(effectKey)) return { status: "busy" };
|
||||
claimed.add(effectKey);
|
||||
return { status: "claimed", fence: 1 };
|
||||
},
|
||||
async renew() {
|
||||
return { fence: 1 };
|
||||
},
|
||||
async complete(effectKey, _taskId, result) {
|
||||
claimed.delete(effectKey);
|
||||
completed.set(effectKey, result);
|
||||
},
|
||||
async release(effectKey) {
|
||||
claimed.delete(effectKey);
|
||||
},
|
||||
};
|
||||
const materializer = createGenerationTaskMaterializer({
|
||||
effects,
|
||||
async materializeOutput() {
|
||||
throw new Error("already materialized");
|
||||
},
|
||||
});
|
||||
const task: GenerationTask = {
|
||||
id: "task-consumer-effect-keys",
|
||||
type: "image",
|
||||
status: "succeeded",
|
||||
prompt: "redacted",
|
||||
attempts: 1,
|
||||
resultState: "READY",
|
||||
outputs: [{ outputIndex: 0, mediaType: "image", materializedAssetId: "asset-stable-id" }],
|
||||
createdAt: "2026-08-13T00:00:00.000Z",
|
||||
updatedAt: "2026-08-13T00:00:00.000Z",
|
||||
};
|
||||
const seen: string[] = [];
|
||||
|
||||
for (let replay = 0; replay < 3; replay += 1) {
|
||||
await materializer.attachNode(task, "node-safe-id", 0, async ({ effectKey }) => {
|
||||
seen.push(effectKey);
|
||||
});
|
||||
await materializer.attachMessage(task, "message-safe-id", 0, async ({ effectKey }) => {
|
||||
seen.push(effectKey);
|
||||
});
|
||||
await materializer.resumeAgent(task, "continuation-safe-id", async ({ effectKey }) => {
|
||||
seen.push(effectKey);
|
||||
});
|
||||
}
|
||||
|
||||
assert.deepEqual(seen, ["attach-node:task-consumer-effect-keys:node-safe-id:0", "attach-message:task-consumer-effect-keys:message-safe-id:0", "agent-resume:task-consumer-effect-keys:continuation-safe-id"]);
|
||||
});
|
||||
|
||||
test("production-shaped node message and agent records replay three times with one side effect", () => {
|
||||
const effectKeys = {
|
||||
node: "attach-node:task-consumer:node-safe-id:0",
|
||||
message: "attach-message:task-consumer:message-safe-id:0",
|
||||
agent: "agent-resume:task-consumer:continuation-safe-id",
|
||||
};
|
||||
const calls = { node: 0, message: 0, agent: 0 };
|
||||
let node = { generationEffectKeys: [] as string[], content: "" };
|
||||
let message = { generationEffectKeys: [] as string[], resultUrls: [] as string[] };
|
||||
let agent = { generationEffectKeys: [] as string[], resumed: false };
|
||||
|
||||
for (let replay = 0; replay < 3; replay += 1) {
|
||||
node = applyGenerationConsumerEffect(node, effectKeys.node, (current) => {
|
||||
calls.node += 1;
|
||||
return { ...current, content: "opaque://asset" };
|
||||
}).value;
|
||||
message = applyGenerationConsumerEffect(message, effectKeys.message, (current) => {
|
||||
calls.message += 1;
|
||||
return { ...current, resultUrls: ["opaque://asset"] };
|
||||
}).value;
|
||||
agent = applyGenerationConsumerEffect(agent, effectKeys.agent, (current) => {
|
||||
calls.agent += 1;
|
||||
return { ...current, resumed: true };
|
||||
}).value;
|
||||
}
|
||||
|
||||
node = structuredClone(node);
|
||||
message = structuredClone(message);
|
||||
agent = structuredClone(agent);
|
||||
node = applyGenerationConsumerEffect(node, effectKeys.node, () => {
|
||||
calls.node += 1;
|
||||
return node;
|
||||
}).value;
|
||||
message = applyGenerationConsumerEffect(message, effectKeys.message, () => {
|
||||
calls.message += 1;
|
||||
return message;
|
||||
}).value;
|
||||
agent = applyGenerationConsumerEffect(agent, effectKeys.agent, () => {
|
||||
calls.agent += 1;
|
||||
return agent;
|
||||
}).value;
|
||||
|
||||
assert.deepEqual(calls, { node: 1, message: 1, agent: 1 });
|
||||
assert.equal(node.generationEffectKeys.length, 1);
|
||||
assert.equal(message.generationEffectKeys.length, 1);
|
||||
assert.equal(agent.generationEffectKeys.length, 1);
|
||||
});
|
||||
Reference in New Issue
Block a user