feat(client): reply digital approvals to acp
This commit is contained in:
@@ -36,6 +36,7 @@ declare global {
|
||||
getSyncStatus?: () => Promise<QimingclawSyncStatus>;
|
||||
flushSync?: () => Promise<QimingclawSyncStatus>;
|
||||
recordGovernanceCommand?: (command: QimingclawGovernanceCommandRecord) => Promise<unknown>;
|
||||
respondPermission?: (sessionId: string, permissionId: string, response: 'once' | 'always' | 'reject') => Promise<{ success?: boolean; error?: string }>;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1769,17 +1770,86 @@ async function handleWorkdayAction(body: DigitalEmployeeWorkdayActionRequest, sn
|
||||
};
|
||||
}
|
||||
|
||||
const acpPermissionResult = body.action === 'decide_approval'
|
||||
? await respondAcpPermissionForDecision(body, snapshot)
|
||||
: null;
|
||||
|
||||
const savedState = await saveState(
|
||||
state,
|
||||
body.action,
|
||||
date,
|
||||
body.action === 'decide_approval'
|
||||
? { decision_id: body.decision_id, decision: body.decision }
|
||||
? {
|
||||
decision_id: body.decision_id,
|
||||
decision: body.decision,
|
||||
acp_permission: acpPermissionResult,
|
||||
}
|
||||
: undefined,
|
||||
);
|
||||
return buildWorkday(date, { ...(snapshot ?? { generatedAt: new Date().toISOString(), services: {}, sessions: { total: 0, active: 0, items: [] } }), uiState: savedState });
|
||||
}
|
||||
|
||||
async function respondAcpPermissionForDecision(
|
||||
body: DigitalEmployeeWorkdayActionRequest,
|
||||
snapshot: QimingclawSnapshot | null,
|
||||
): Promise<Record<string, unknown> | null> {
|
||||
if (!body.decision_id || !body.decision) return null;
|
||||
const approval = findApprovalForDecision(body.decision_id, snapshot);
|
||||
if (!approval) return null;
|
||||
const refs = acpPermissionRefs(approval);
|
||||
if (!refs) return null;
|
||||
const response = acpResponseForDecision(body.decision);
|
||||
const respondPermission = window.QimingClawBridge?.digital?.respondPermission;
|
||||
if (!respondPermission) return null;
|
||||
try {
|
||||
const result = await respondPermission(refs.sessionId, refs.permissionId, response);
|
||||
return {
|
||||
permission_id: refs.permissionId,
|
||||
session_id: refs.sessionId,
|
||||
response,
|
||||
success: result?.success !== false,
|
||||
error: result?.error,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
permission_id: refs.permissionId,
|
||||
session_id: refs.sessionId,
|
||||
response,
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function findApprovalForDecision(decisionId: string, snapshot: QimingclawSnapshot | null): ApprovalEntry | null {
|
||||
return buildApprovals(snapshot).find((approval) => stringValue(approval.approval_id) === decisionId) ?? null;
|
||||
}
|
||||
|
||||
function acpPermissionRefs(approval: ApprovalEntry): { permissionId: string; sessionId: string } | null {
|
||||
const payload = asRecord(approval.payload);
|
||||
const nestedPayload = asRecord(payload?.payload);
|
||||
const permissionId = stringValue(payload?.permissionId)
|
||||
|| stringValue(payload?.permission_id)
|
||||
|| stringValue(payload?.id)
|
||||
|| stringValue(nestedPayload?.permissionId)
|
||||
|| stringValue(nestedPayload?.permission_id)
|
||||
|| stringValue(nestedPayload?.id);
|
||||
const sessionId = stringValue(payload?.sessionId)
|
||||
|| stringValue(payload?.session_id)
|
||||
|| stringValue(nestedPayload?.sessionId)
|
||||
|| stringValue(nestedPayload?.session_id);
|
||||
const source = stringValue(payload?.source);
|
||||
if (!permissionId || !sessionId || (source && source !== 'acp-permission')) return null;
|
||||
return { permissionId, sessionId };
|
||||
}
|
||||
|
||||
function acpResponseForDecision(decision: string): 'once' | 'always' | 'reject' {
|
||||
const normalized = decision.toLowerCase();
|
||||
if (normalized.includes('always')) return 'always';
|
||||
if (normalized.includes('reject') || normalized.includes('deny')) return 'reject';
|
||||
return 'once';
|
||||
}
|
||||
|
||||
async function handleGovernanceCommand(
|
||||
body: GovernanceCommandRequest,
|
||||
snapshot: QimingclawSnapshot | null,
|
||||
|
||||
Reference in New Issue
Block a user