feat(client): materialize restarted plans

This commit is contained in:
baiyanyun
2026-06-08 18:58:39 +08:00
parent 913c6da8f3
commit 451cda7aa6
6 changed files with 233 additions and 45 deletions

View File

@@ -168,6 +168,20 @@ describe("digital employee state service", () => {
payload: {
title: "生成今日客户跟进计划",
objective: "把今日客户跟进事项整理成可执行计划",
steps: [
{
step_id: "collect-crm",
title: "整理客户列表",
skills: ["qimingclaw-mcp-tool-crm-crm-search"],
tasks: [
{
task_id: "task-collect-crm",
title: "拉取 CRM 客户记录",
description: "读取今日需要跟进的客户",
},
],
},
],
},
result: {
plan_id: "plan-customer-followup",
@@ -191,6 +205,12 @@ describe("digital employee state service", () => {
title: "创建数字员工计划",
assigned_skill_id: "qimingclaw-governance-command",
});
expect(mockState.db?.tasks.get("task-collect-crm")).toMatchObject({
plan_id: "plan-customer-followup",
title: "拉取 CRM 客户记录",
status: "pending",
assigned_skill_id: "qimingclaw-mcp-tool-crm-crm-search",
});
expect(mockState.db?.runs.get("governance-run-command-1")).toMatchObject({
plan_id: "plan-customer-followup",
task_id: "governance-task-command-1",
@@ -208,6 +228,33 @@ describe("digital employee state service", () => {
});
expect(mockState.ensureSchemaCalls).toBeGreaterThan(0);
});
it("preserves created plan title across follow-up governance commands", async () => {
const { recordDigitalEmployeeGovernanceCommand } = await import("./stateService");
recordDigitalEmployeeGovernanceCommand({
commandKind: "create_plan",
commandId: "command-create",
accepted: true,
message: "已创建计划草稿",
payload: { title: "客户回访重新执行", objective: "重新执行客户回访流程" },
result: { plan_id: "plan-restart", status: "draft" },
});
recordDigitalEmployeeGovernanceCommand({
commandKind: "approve_plan",
commandId: "command-approve",
accepted: true,
message: "已批准计划",
result: { plan_id: "plan-restart", status: "approved" },
});
expect(mockState.db?.plans.get("plan-restart")).toMatchObject({
title: "客户回访重新执行",
objective: "重新执行客户回访流程",
status: "approved",
});
});
});
interface TestPlanRow {
@@ -325,6 +372,9 @@ class TestDb {
}
private get(sql: string, args: unknown[]): unknown {
if (sql.startsWith("SELECT title, objective FROM digital_plans")) {
return this.plans.get(args[0] as string);
}
if (sql.startsWith("SELECT id, plan_id, task_id, run_id, title, status, payload, created_at FROM digital_approvals")) {
return this.approvals.get(args[0] as string);
}