吸收数字员工产物交付状态

This commit is contained in:
baiyanyun
2026-06-09 16:47:14 +08:00
parent 4d8b8e4ad5
commit 5160a73254
7 changed files with 365 additions and 42 deletions

View File

@@ -83,6 +83,110 @@ describe("digital employee state service", () => {
expect(mockState.ensureSchemaCalls).toBeGreaterThan(0);
});
it("normalizes file server workspace events into delivery artifact payload", async () => {
const { recordDigitalEmployeeRuntimeEvent } = await import("./stateService");
recordDigitalEmployeeRuntimeEvent({
kind: "file_server.workspace.created",
request_id: "file-workspace-1",
message: "create-workspace 完成",
status: "completed",
payload: {
source: "qiming-file-server",
toolName: "create_workspace",
workspaceId: "workspace-123",
projectId: "project-file",
path: "/tmp/qiming/workspace-123",
status: "completed",
},
});
const artifacts = Array.from(mockState.db?.artifacts.values() ?? []);
expect(artifacts).toHaveLength(1);
expect(artifacts[0]).toMatchObject({
kind: "workspace",
name: "workspace-123",
uri: "/tmp/qiming/workspace-123",
});
expect(JSON.parse(artifacts[0]?.payload ?? "{}")).toMatchObject({
delivery: {
stage: "workspace",
status: "completed",
workspace_id: "workspace-123",
project_id: "project-file",
uri: "/tmp/qiming/workspace-123",
source_tool: "create_workspace",
source_event_kind: "file_server.workspace.created",
},
});
expect(mockState.db?.outbox.get(`artifact:upsert:${artifacts[0]?.id}`)).toMatchObject({
entity_type: "artifact",
status: "pending",
});
});
it("upserts file server file delivery status without duplicating artifacts", async () => {
const { recordDigitalEmployeeRuntimeEvent } = await import("./stateService");
const basePayload = {
source: "qiming-file-server",
workspaceId: "workspace-123",
projectId: "project-file",
fileId: "file-1",
filename: "report.pdf",
version: "v2",
size: 2048,
path: "/tmp/qiming/workspace-123/report.pdf",
};
recordDigitalEmployeeRuntimeEvent({
kind: "file_server.upload.completed",
request_id: "file-delivery-1",
message: "upload-file 完成",
status: "completed",
payload: {
...basePayload,
toolName: "upload_file",
status: "uploaded",
},
});
recordDigitalEmployeeRuntimeEvent({
kind: "file_server.download.completed",
request_id: "file-delivery-1",
message: "download-all-files 完成",
status: "completed",
payload: {
...basePayload,
toolName: "download_all_files",
status: "downloaded",
downloadUrl: "file:///tmp/qiming/workspace-123/report.pdf",
},
});
const artifacts = Array.from(mockState.db?.artifacts.values() ?? []);
expect(artifacts).toHaveLength(1);
expect(artifacts[0]).toMatchObject({
kind: "download",
name: "report.pdf",
uri: "file:///tmp/qiming/workspace-123/report.pdf",
});
expect(JSON.parse(artifacts[0]?.payload ?? "{}")).toMatchObject({
delivery: {
stage: "download",
status: "downloaded",
workspace_id: "workspace-123",
project_id: "project-file",
file_id: "file-1",
version: "v2",
filename: "report.pdf",
size: 2048,
uri: "file:///tmp/qiming/workspace-123/report.pdf",
source_tool: "download_all_files",
source_event_kind: "file_server.download.completed",
},
});
expect(Array.from(mockState.db?.outbox.values() ?? []).filter((row) => row.entity_type === "artifact")).toHaveLength(1);
});
it("records and lists route decisions as syncable events", async () => {
const {
listDigitalEmployeeRouteDecisions,