吸收数字员工通知回复任务输入
This commit is contained in:
@@ -3819,11 +3819,14 @@ async function handleNotificationAction(
|
||||
action: 'read' | 'dismiss' | 'reply',
|
||||
body: Record<string, unknown>,
|
||||
snapshot: QimingclawSnapshot | null,
|
||||
): Promise<{ ok: boolean; task_id?: string; status?: string }> {
|
||||
): Promise<{ ok: boolean; task_id?: string; status?: string; task_input_recorded?: boolean; governance_command_id?: string; governance_event_id?: string }> {
|
||||
const state = snapshot?.uiState ?? await readBridgeUiState() ?? readState();
|
||||
const current = buildNotifications(snapshot, state).find((notification) => notification.notification_id === notificationId);
|
||||
const now = new Date().toISOString();
|
||||
const overlay: NotificationState = { ...(state.notificationStateById?.[notificationId] ?? {}) };
|
||||
const previousOverlay = state.notificationStateById?.[notificationId];
|
||||
const alreadyReplied = Boolean(previousOverlay?.replied_at);
|
||||
const overlay: NotificationState = { ...(previousOverlay ?? {}) };
|
||||
let replyContent = '';
|
||||
if (action === 'read') {
|
||||
overlay.status = current?.status === 'resolved' ? 'resolved' : 'read';
|
||||
overlay.read_at = overlay.read_at ?? now;
|
||||
@@ -3833,7 +3836,8 @@ async function handleNotificationAction(
|
||||
} else {
|
||||
overlay.status = current?.status === 'resolved' ? 'resolved' : 'read';
|
||||
overlay.read_at = overlay.read_at ?? now;
|
||||
overlay.reply = stringValue(body.content ?? body.reply ?? body.message);
|
||||
replyContent = stringValue(body.content ?? body.reply ?? body.message);
|
||||
overlay.reply = replyContent;
|
||||
overlay.replied_at = now;
|
||||
}
|
||||
const nextState: AdapterState = {
|
||||
@@ -3844,7 +3848,51 @@ async function handleNotificationAction(
|
||||
},
|
||||
};
|
||||
await saveState(nextState, `notification_${action}`, undefined, { notification_id: notificationId, action });
|
||||
return { ok: true, task_id: current?.task_id, status: overlay.status };
|
||||
const taskInput = action === 'reply' && current?.kind === 'need_input' && current.task_id && replyContent && !alreadyReplied
|
||||
? await recordNotificationTaskInput(current, replyContent, snapshot)
|
||||
: null;
|
||||
return {
|
||||
ok: true,
|
||||
task_id: current?.task_id,
|
||||
status: overlay.status,
|
||||
task_input_recorded: Boolean(taskInput?.accepted),
|
||||
governance_command_id: taskInput?.command_id,
|
||||
governance_event_id: governanceEventIdFromCommand(taskInput),
|
||||
};
|
||||
}
|
||||
|
||||
async function recordNotificationTaskInput(
|
||||
notification: UserNotification,
|
||||
replyContent: string,
|
||||
snapshot: QimingclawSnapshot | null,
|
||||
): Promise<GovernanceCommandResponse> {
|
||||
const stamp = Date.now();
|
||||
return handleGovernanceCommand({
|
||||
command_kind: 'provide_task_input',
|
||||
context_refs: {
|
||||
plan_id: notification.plan_id || undefined,
|
||||
task_id: notification.task_id,
|
||||
},
|
||||
payload: {
|
||||
input: replyContent,
|
||||
source: 'notification_reply',
|
||||
notification_id: notification.notification_id,
|
||||
plan_id: notification.plan_id || undefined,
|
||||
task_id: notification.task_id,
|
||||
},
|
||||
correlation_id: `qimingclaw-notification-reply-${slugifyIdPart(notification.notification_id)}-${stamp}`,
|
||||
idempotency_key: `qimingclaw-notification-reply-${notification.notification_id}`,
|
||||
}, snapshot);
|
||||
}
|
||||
|
||||
function governanceEventIdFromCommand(response: GovernanceCommandResponse | null): string | undefined {
|
||||
const runId = stringFromUnknown(response?.result?.run_id);
|
||||
if (!response?.accepted || !runId || !response.command_id) return undefined;
|
||||
return `${runId}:provide_task_input:${safeEventIdPart(response.command_id)}`;
|
||||
}
|
||||
|
||||
function safeEventIdPart(value: string): string {
|
||||
return value.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, '') || 'unknown';
|
||||
}
|
||||
|
||||
function buildWorkdayDecisions(
|
||||
|
||||
Reference in New Issue
Block a user