feat(client): persist digital governance events
This commit is contained in:
@@ -203,6 +203,19 @@ export interface DigitalEmployeeRuntimeEventRecord {
|
||||
payload?: unknown;
|
||||
}
|
||||
|
||||
export interface DigitalEmployeeGovernanceCommandRecord {
|
||||
commandKind: string;
|
||||
commandId: string;
|
||||
correlationId?: string;
|
||||
planId?: string | null;
|
||||
scheduleId?: string | null;
|
||||
accepted?: boolean;
|
||||
message?: string;
|
||||
error?: string | null;
|
||||
payload?: Record<string, unknown> | null;
|
||||
result?: Record<string, unknown> | null;
|
||||
}
|
||||
|
||||
function defaultState(): DigitalEmployeeState {
|
||||
return {
|
||||
version: 1,
|
||||
@@ -681,6 +694,140 @@ export function recordDigitalEmployeeRuntimeEvent(
|
||||
tx();
|
||||
}
|
||||
|
||||
export function recordDigitalEmployeeGovernanceCommand(
|
||||
command: DigitalEmployeeGovernanceCommandRecord,
|
||||
): { planId: string; taskId: string; runId: string } {
|
||||
const now = new Date().toISOString();
|
||||
const commandId = command.commandId || `governance-${Date.now()}`;
|
||||
const result = objectRecord(command.result) ?? {};
|
||||
const payload = objectRecord(command.payload) ?? {};
|
||||
const planId = stringValue(command.planId)
|
||||
|| stringValue(result.plan_id)
|
||||
|| stringValue(payload.plan_id)
|
||||
|| `governance-plan-${safeId(commandId)}`;
|
||||
const ids = {
|
||||
planId,
|
||||
taskId: `governance-task-${safeId(commandId)}`,
|
||||
runId: `governance-run-${safeId(commandId)}`,
|
||||
};
|
||||
const title = stringValue(payload.title ?? result.title)
|
||||
|| governanceCommandTitle(command.commandKind);
|
||||
const status = governanceCommandStatus(command);
|
||||
const payloadEnvelope = {
|
||||
source: "qimingclaw-governance-command",
|
||||
commandKind: command.commandKind,
|
||||
commandId,
|
||||
correlationId: command.correlationId,
|
||||
planId,
|
||||
scheduleId: command.scheduleId || stringValue(result.schedule_id) || null,
|
||||
accepted: command.accepted !== false,
|
||||
message: command.message,
|
||||
error: command.error,
|
||||
payload,
|
||||
result,
|
||||
};
|
||||
|
||||
const db = getDigitalEmployeeDb();
|
||||
if (!db) return ids;
|
||||
|
||||
const tx = db.transaction(() => {
|
||||
upsertPlan({
|
||||
id: ids.planId,
|
||||
title,
|
||||
objective: stringValue(payload.objective ?? payload.description ?? payload.requested_action)
|
||||
|| command.message
|
||||
|| title,
|
||||
status,
|
||||
payload: payloadEnvelope,
|
||||
now,
|
||||
});
|
||||
upsertTask({
|
||||
id: ids.taskId,
|
||||
planId: ids.planId,
|
||||
title: governanceCommandTitle(command.commandKind),
|
||||
status,
|
||||
assignedSkillId: "qimingclaw-governance-command",
|
||||
payload: payloadEnvelope,
|
||||
now,
|
||||
});
|
||||
upsertRun({
|
||||
id: ids.runId,
|
||||
planId: ids.planId,
|
||||
taskId: ids.taskId,
|
||||
status,
|
||||
payload: payloadEnvelope,
|
||||
now,
|
||||
});
|
||||
if (status !== "running" && status !== "pending") {
|
||||
finishRun(ids.runId, status, now);
|
||||
}
|
||||
persistPayloadArtifactsAndApprovals(ids, payloadEnvelope, now);
|
||||
insertEvent(
|
||||
{
|
||||
event_id: `${ids.runId}:${command.commandKind}:${safeId(commandId)}`,
|
||||
kind: `governance_${command.commandKind}`,
|
||||
occurred_at: now,
|
||||
message: command.message || `${governanceCommandTitle(command.commandKind)} 已记录`,
|
||||
plan_id: ids.planId,
|
||||
task_id: ids.taskId,
|
||||
},
|
||||
ids.runId,
|
||||
payloadEnvelope,
|
||||
);
|
||||
});
|
||||
tx();
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
function governanceCommandTitle(commandKind: string): string {
|
||||
switch (commandKind) {
|
||||
case "create_plan":
|
||||
return "创建数字员工计划";
|
||||
case "submit_plan":
|
||||
return "提交数字员工计划";
|
||||
case "approve_plan":
|
||||
return "批准数字员工计划";
|
||||
case "activate_plan":
|
||||
return "激活数字员工计划";
|
||||
case "create_schedule":
|
||||
return "创建数字员工定时任务";
|
||||
case "run_schedule_now":
|
||||
return "立即运行数字员工计划";
|
||||
case "pause_plan":
|
||||
return "暂停数字员工计划";
|
||||
case "cancel_plan":
|
||||
return "取消数字员工计划";
|
||||
default:
|
||||
return `数字员工治理命令:${commandKind || "unknown"}`;
|
||||
}
|
||||
}
|
||||
|
||||
function governanceCommandStatus(
|
||||
command: DigitalEmployeeGovernanceCommandRecord,
|
||||
): string {
|
||||
if (command.accepted === false || command.error) return "failed";
|
||||
const resultStatus = stringValue(command.result?.status);
|
||||
if (resultStatus) return resultStatus;
|
||||
switch (command.commandKind) {
|
||||
case "activate_plan":
|
||||
case "run_schedule_now":
|
||||
return "running";
|
||||
case "create_plan":
|
||||
return "draft";
|
||||
case "submit_plan":
|
||||
return "reviewing";
|
||||
case "approve_plan":
|
||||
return "approved";
|
||||
case "pause_plan":
|
||||
return "paused";
|
||||
case "cancel_plan":
|
||||
return "cancelled";
|
||||
default:
|
||||
return "completed";
|
||||
}
|
||||
}
|
||||
|
||||
function persistSnapshotTables(
|
||||
snapshot: DigitalEmployeeSnapshot,
|
||||
event: DigitalEmployeeStateEvent | null,
|
||||
|
||||
Reference in New Issue
Block a user