吸收数字员工审批时间线

This commit is contained in:
baiyanyun
2026-06-09 17:33:00 +08:00
parent 5160a73254
commit dc8cd09535
8 changed files with 333 additions and 147 deletions

View File

@@ -342,6 +342,39 @@ describe("digital employee state service", () => {
entity_id: "approval-1",
status: "pending",
});
const decisionEvents = Array.from(mockState.db?.events.values() ?? []).filter((event) => event.kind === "approval_decision");
expect(decisionEvents).toHaveLength(1);
expect(decisionEvents[0]).toMatchObject({
id: "approval-1:decision:approved:2026-06-07T08-00-00-000Z",
plan_id: "plan-1",
task_id: "task-1",
run_id: "run-1",
message: "审批处理:确认发送日报给管理端 -> approved",
sync_status: "pending",
occurred_at: "2026-06-07T08:00:00.000Z",
});
expect(JSON.parse(decisionEvents[0]?.payload ?? "{}")).toMatchObject({
source: "qimingclaw-approval-decision",
approvalId: "approval-1",
decision: "approved",
previousStatus: "pending",
nextStatus: "approved",
title: "确认发送日报给管理端",
planId: "plan-1",
taskId: "task-1",
runId: "run-1",
decidedAt: "2026-06-07T08:00:00.000Z",
acpPermission: {
permission_id: "permission-1",
session_id: "session-1",
},
});
expect(mockState.db?.outbox.get("event:insert:approval-1:decision:approved:2026-06-07T08-00-00-000Z")).toMatchObject({
entity_type: "event",
entity_id: "approval-1:decision:approved:2026-06-07T08-00-00-000Z",
operation: "insert",
status: "pending",
});
expect(mockState.ensureSchemaCalls).toBeGreaterThan(0);
});

View File

@@ -662,6 +662,11 @@ function recordUiApprovalDecision(update: DigitalEmployeeUiStateUpdate): void {
const now = new Date().toISOString();
const previousStatus = stringField(existing, "status") || "pending";
const nextStatus = approvalDecisionStatus(decision);
const planId = stringField(existing, "plan_id");
const taskId = stringField(existing, "task_id");
const runId = stringField(existing, "run_id");
const title = stringField(existing, "title") || "待确认事项";
const storedPayload = parseStoredPayload(existing["payload"]);
const storedPayloadRecord = objectRecord(storedPayload);
const acpPermission = objectRecord(metadata?.acp_permission);
@@ -682,14 +687,39 @@ function recordUiApprovalDecision(update: DigitalEmployeeUiStateUpdate): void {
};
upsertApproval({
id: decisionId,
planId: stringField(existing, "plan_id"),
taskId: stringField(existing, "task_id"),
runId: stringField(existing, "run_id"),
title: stringField(existing, "title") || "待确认事项",
status: approvalDecisionStatus(decision),
planId,
taskId,
runId,
title,
status: nextStatus,
payload,
now,
});
const eventPayload = {
source: "qimingclaw-approval-decision",
approvalId: decisionId,
decision,
previousStatus,
nextStatus,
title,
planId,
taskId,
runId,
decidedAt: now,
...(acpPermission ? { acpPermission } : {}),
};
insertEvent(
{
event_id: `${decisionId}:decision:${safeId(decision)}:${safeId(now)}`,
kind: "approval_decision",
occurred_at: now,
message: `审批处理:${title} -> ${decision}`,
plan_id: planId,
task_id: taskId,
},
runId || null,
eventPayload,
);
}
function approvalDecisionStatus(decision: string): string {