feat(client): persist digital governance events
This commit is contained in:
@@ -34,6 +34,7 @@ declare global {
|
||||
saveUiState?: (update: { state: AdapterState; action?: string; date?: string; metadata?: Record<string, unknown> }) => Promise<AdapterState>;
|
||||
getSyncStatus?: () => Promise<QimingclawSyncStatus>;
|
||||
flushSync?: () => Promise<QimingclawSyncStatus>;
|
||||
recordGovernanceCommand?: (command: QimingclawGovernanceCommandRecord) => Promise<unknown>;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -124,6 +125,19 @@ interface QimingclawSnapshot {
|
||||
uiState?: AdapterState | null;
|
||||
}
|
||||
|
||||
interface QimingclawGovernanceCommandRecord {
|
||||
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;
|
||||
}
|
||||
|
||||
interface QimingclawRuntimeRecords {
|
||||
generatedAt: string;
|
||||
plans: QimingclawPlanRecord[];
|
||||
@@ -519,6 +533,34 @@ async function saveState(
|
||||
}
|
||||
}
|
||||
|
||||
async function recordGovernanceCommand(
|
||||
body: GovernanceCommandRequest,
|
||||
response: GovernanceCommandResponse,
|
||||
): Promise<void> {
|
||||
try {
|
||||
await window.QimingClawBridge?.digital?.recordGovernanceCommand?.({
|
||||
commandKind: body.command_kind,
|
||||
commandId: response.command_id,
|
||||
correlationId: response.correlation_id,
|
||||
planId: stringFromUnknown(response.result?.plan_id)
|
||||
|| stringFromUnknown(body.context_refs?.plan_id)
|
||||
|| stringFromUnknown(body.payload?.plan_id)
|
||||
|| null,
|
||||
scheduleId: stringFromUnknown(response.result?.schedule_id)
|
||||
|| stringFromUnknown(body.context_refs?.schedule_id)
|
||||
|| stringFromUnknown(body.payload?.schedule_id)
|
||||
|| null,
|
||||
accepted: response.accepted,
|
||||
message: response.message,
|
||||
error: response.error ?? null,
|
||||
payload: body.payload ?? null,
|
||||
result: response.result ?? null,
|
||||
});
|
||||
} catch {
|
||||
// Bridge persistence is best-effort; the adapter response should not block UI flow.
|
||||
}
|
||||
}
|
||||
|
||||
function parseJsonBody<T>(body: BodyInit | null | undefined): T {
|
||||
if (typeof body !== 'string' || !body.trim()) return {} as T;
|
||||
return JSON.parse(body) as T;
|
||||
@@ -1689,37 +1731,43 @@ async function handleGovernanceCommand(
|
||||
|
||||
if (body.command_kind === 'create_plan') {
|
||||
const createdPlanId = `qimingclaw-local-${slugifyIdPart(stringFromUnknown(body.payload?.title) || planId || 'plan')}-${Date.now()}`;
|
||||
return governanceAccepted(commandId, correlationId, '已在 qimingclaw 兼容层创建本地计划草稿。', {
|
||||
const response = governanceAccepted(commandId, correlationId, '已在 qimingclaw 兼容层创建本地计划草稿。', {
|
||||
plan_id: createdPlanId,
|
||||
status: 'draft',
|
||||
source: 'qimingclaw-adapter',
|
||||
requested_action: body.payload?.requested_action,
|
||||
original_plan_id: body.payload?.original_plan_id ?? planId,
|
||||
});
|
||||
await recordGovernanceCommand(body, response);
|
||||
return response;
|
||||
}
|
||||
|
||||
if (body.command_kind === 'activate_plan' || body.command_kind === 'run_schedule_now') {
|
||||
const targetPlanId = planId || runtimeDebugPlans(snapshot)[0]?.plan_id || PLANS[0]?.plan_id || 'qimingclaw-client-readiness';
|
||||
const dispatch = await dispatchPlan(targetPlanId, snapshot);
|
||||
return governanceAccepted(commandId, correlationId, '已映射为 qimingclaw 本地任务激活。', {
|
||||
const response = governanceAccepted(commandId, correlationId, '已映射为 qimingclaw 本地任务激活。', {
|
||||
plan_id: targetPlanId,
|
||||
status: 'active',
|
||||
dispatched_tasks: dispatch.dispatched_tasks,
|
||||
source: 'qimingclaw-adapter',
|
||||
});
|
||||
await recordGovernanceCommand(body, response);
|
||||
return response;
|
||||
}
|
||||
|
||||
if (body.command_kind === 'create_schedule') {
|
||||
return governanceAccepted(commandId, correlationId, '已记录 qimingclaw 兼容定时任务请求。', {
|
||||
const response = governanceAccepted(commandId, correlationId, '已记录 qimingclaw 兼容定时任务请求。', {
|
||||
schedule_id: scheduleId || `qimingclaw-schedule-${Date.now()}`,
|
||||
plan_id: planId,
|
||||
status: 'enabled',
|
||||
source: 'qimingclaw-adapter',
|
||||
});
|
||||
await recordGovernanceCommand(body, response);
|
||||
return response;
|
||||
}
|
||||
|
||||
if (['submit_plan', 'approve_plan', 'amend_plan', 'resume_plan', 'pause_plan', 'cancel_plan'].includes(body.command_kind)) {
|
||||
return governanceAccepted(commandId, correlationId, `已接受 ${body.command_kind},当前由 qimingclaw 本地 adapter 记录兼容状态。`, {
|
||||
const response = governanceAccepted(commandId, correlationId, `已接受 ${body.command_kind},当前由 qimingclaw 本地 adapter 记录兼容状态。`, {
|
||||
plan_id: planId,
|
||||
status: body.command_kind === 'approve_plan'
|
||||
? 'approved'
|
||||
@@ -1728,15 +1776,19 @@ async function handleGovernanceCommand(
|
||||
: 'accepted',
|
||||
source: 'qimingclaw-adapter',
|
||||
});
|
||||
await recordGovernanceCommand(body, response);
|
||||
return response;
|
||||
}
|
||||
|
||||
return {
|
||||
const response = {
|
||||
command_id: commandId,
|
||||
accepted: false,
|
||||
correlation_id: correlationId,
|
||||
error: 'missing_capability',
|
||||
message: `qimingclaw 数字员工兼容层尚未支持 ${body.command_kind}。`,
|
||||
};
|
||||
await recordGovernanceCommand(body, response);
|
||||
return response;
|
||||
}
|
||||
|
||||
function governanceAccepted(
|
||||
|
||||
Reference in New Issue
Block a user