吸收数字员工步骤自动调度
This commit is contained in:
@@ -26,6 +26,7 @@ import type {
|
||||
IngressRouteResponse,
|
||||
GovernanceCommandRequest,
|
||||
GovernanceCommandResponse,
|
||||
SchedulerCheckResponse,
|
||||
DigitalEmployeeManagedService,
|
||||
DigitalEmployeeWorkdayProjection,
|
||||
DigitalEmployeeWorkdayActionRequest,
|
||||
@@ -709,8 +710,8 @@ export function taskAction(taskId: string, action: string): Promise<any> {
|
||||
* Current React pages must trigger scheduler checks through runSchedulerNow()
|
||||
* so backend governance rejection and command errors are surfaced correctly.
|
||||
*/
|
||||
export function triggerCronCheck(): Promise<{ ok?: boolean; activated: number }> {
|
||||
return apiFetch<{ ok?: boolean; activated: number }>('/api/cron/check', { method: 'POST' });
|
||||
export function triggerCronCheck(): Promise<SchedulerCheckResponse> {
|
||||
return apiFetch<SchedulerCheckResponse>('/api/cron/check', { method: 'POST' });
|
||||
}
|
||||
|
||||
export function getAuditTrace(kind: string, id: string): Promise<any> {
|
||||
|
||||
@@ -3241,6 +3241,7 @@ function buildNotifications(snapshot: QimingclawSnapshot | null, state: AdapterS
|
||||
...approvalActionNotifications(snapshot),
|
||||
...syncFailureNotifications(snapshot),
|
||||
...managedServiceNotifications(snapshot),
|
||||
...planStepDispatchNotifications(snapshot),
|
||||
...taskNotifications(snapshot),
|
||||
]);
|
||||
const overlays = state.notificationStateById ?? {};
|
||||
@@ -3353,6 +3354,28 @@ function taskNotifications(snapshot: QimingclawSnapshot | null): UserNotificatio
|
||||
});
|
||||
}
|
||||
|
||||
function planStepDispatchNotifications(snapshot: QimingclawSnapshot | null): UserNotification[] {
|
||||
return runtimeEvents(snapshot)
|
||||
.filter((event) => event.kind === 'plan_step_dispatch_failed')
|
||||
.map((event) => {
|
||||
const payload = asRecord(event.payload) ?? {};
|
||||
const stepId = stringValue(payload.step_id) || event.id;
|
||||
const reason = stringValue(payload.reason);
|
||||
return {
|
||||
notification_id: `plan-step-dispatch:${stepId}:${slugifyIdPart(event.occurredAt)}`,
|
||||
plan_id: event.planId ?? stringValue(payload.plan_id),
|
||||
task_id: event.taskId ?? stringValue(payload.task_id),
|
||||
kind: 'task_failed',
|
||||
title: 'Ready 步骤派发失败',
|
||||
body: reason ? `${stepId}:${reason}` : (event.message || stepId),
|
||||
level: 'error',
|
||||
status: 'unread',
|
||||
correlation_id: stepId,
|
||||
created_at: event.occurredAt,
|
||||
} satisfies UserNotification;
|
||||
});
|
||||
}
|
||||
|
||||
function applyNotificationOverlay(notification: UserNotification, overlay?: NotificationState): UserNotification {
|
||||
if (!overlay) return notification;
|
||||
return {
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
postDigitalEmployeeWorkdayAction,
|
||||
recordApprovalAction,
|
||||
restartManagedService,
|
||||
triggerCronCheck,
|
||||
} from '@/lib/api';
|
||||
import { isTauri } from '@/lib/tauri';
|
||||
import type {
|
||||
@@ -1600,8 +1601,15 @@ export default function CommandDeck({ onNavigate }: { onNavigate: (target: Digit
|
||||
throw new Error(response.error || '执行接口未接受请求');
|
||||
}
|
||||
const dispatchedCount = response.dispatched_tasks?.length ?? 0;
|
||||
const schedulerResult = await triggerCronCheck();
|
||||
const readyDispatched = schedulerResult.readyStepDispatch?.dispatched ?? 0;
|
||||
const readyFailed = schedulerResult.readyStepDispatch?.failed ?? 0;
|
||||
setExecutePlanItem(null);
|
||||
setActionNotice(`已触发执行:${planItem.title},已派发 ${dispatchedCount} 个步骤。`);
|
||||
setActionNotice(
|
||||
readyDispatched > 0 || readyFailed > 0
|
||||
? `已触发执行:${planItem.title},新建 ${dispatchedCount} 个步骤,Ready 步骤自动派发 ${readyDispatched} 个${readyFailed > 0 ? `,失败 ${readyFailed} 个` : ''}。`
|
||||
: `已触发执行:${planItem.title},已派发 ${dispatchedCount} 个步骤。`,
|
||||
);
|
||||
await fetchProjection();
|
||||
} catch (error) {
|
||||
if (mountedRef.current) {
|
||||
|
||||
@@ -382,6 +382,24 @@ export interface GovernanceCommandResponse {
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export interface ReadyStepDispatchResult {
|
||||
candidates: number;
|
||||
dispatched: number;
|
||||
skipped: number;
|
||||
failed: number;
|
||||
errors?: Array<{ stepId: string; error: string }>;
|
||||
}
|
||||
|
||||
export interface SchedulerCheckResponse {
|
||||
ok?: boolean;
|
||||
checkedAt?: string;
|
||||
due?: number;
|
||||
activated: number;
|
||||
skipped?: number;
|
||||
errors?: Array<{ scheduleId: string; error: string }>;
|
||||
readyStepDispatch?: ReadyStepDispatchResult;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
// Console types — Debug API responses, Plan/Task/Run, Swimlane
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
Reference in New Issue
Block a user