吸收数字员工PlanStep阻塞处理入口

This commit is contained in:
baiyanyun
2026-06-10 20:37:11 +08:00
parent d679639175
commit a6e0246418
11 changed files with 543 additions and 197 deletions

View File

@@ -2593,11 +2593,13 @@ function planStepRows(snapshot: QimingclawSnapshot | null): BusinessViewRow[] {
dependency_status: stringValue(dependencyGraph.status) || stepDependencyStatus(step, blockedDependencies, waitingDependencies),
blocked_dependencies: blockedDependencies,
blocked_dependency_count: blockedDependencies.length,
blocked_dependency_details: planStepDependencyDetails(blockedDependencies, snapshot),
waiting_dependencies: waitingDependencies,
waiting_dependency_count: waitingDependencies.length,
satisfied_dependencies: satisfiedDependencies,
preferred_skill_ids: step.preferredSkillIds,
task_id: readiness.taskId,
latest_run_id: readiness.latestRunId,
dispatchable: readiness.dispatchable,
skip_reason: readiness.skipReason,
last_dispatch_status: stringValue(lastDispatch.status) || null,
@@ -2626,8 +2628,11 @@ function planStepGraphRows(snapshot: QimingclawSnapshot | null): BusinessViewRow
depends_on: arrayValue(row.depends_on),
dependency_status: stringValue(row.dependency_status) || null,
blocked_dependencies: arrayValue(row.blocked_dependencies),
blocked_dependency_details: arrayValue(row.blocked_dependency_details),
waiting_dependencies: arrayValue(row.waiting_dependencies),
satisfied_dependencies: arrayValue(row.satisfied_dependencies),
task_id: stringValue(row.task_id) || null,
latest_run_id: stringValue(row.latest_run_id) || null,
dispatchable: row.dispatchable === true,
skip_reason: stringValue(row.skip_reason) || null,
sync_status: stringValue(row.sync_status) || null,
@@ -2661,12 +2666,13 @@ function planStepDispatchReadiness(
step: QimingclawPlanStepRecord,
snapshot: QimingclawSnapshot | null,
payload: Record<string, unknown>,
): { taskId: string | null; dispatchable: boolean; skipReason: string | null } {
): { taskId: string | null; latestRunId: string | null; dispatchable: boolean; skipReason: string | null } {
const tasks = runtimePlanTasks(snapshot, step.planId);
const task = tasks.find((candidate) => taskStepId(candidate) === step.id)
?? tasks.find((candidate) => !isTerminalRuntimeTaskStatus(candidate.status))
?? null;
const taskId = task?.id ?? null;
const latestRunId = task ? latestRunForTask(runtimeRuns(snapshot), task.id)?.id ?? null : null;
let skipReason: string | null = null;
if (step.status.toLowerCase() !== 'ready') skipReason = 'not_ready';
else if (!task) skipReason = 'missing_task';
@@ -2674,7 +2680,39 @@ function planStepDispatchReadiness(
else if (runtimeRuns(snapshot).some((run) => run.taskId === task.id && isActiveRuntimeRunStatus(run.status))) skipReason = 'task_already_running';
else if (runtimeApprovals(snapshot).some((approval) => isOpenRuntimeApprovalStatus(approval.status) && (approval.planId === step.planId || approval.taskId === task.id || stringValue(asRecord(approval.payload)?.stepId ?? asRecord(approval.payload)?.step_id) === step.id))) skipReason = 'approval_pending';
else if (payload.auto_dispatch === false || payload.autoDispatch === false) skipReason = 'auto_dispatch_disabled';
return { taskId, dispatchable: !skipReason, skipReason };
return { taskId, latestRunId, dispatchable: !skipReason, skipReason };
}
function planStepDependencyDetails(dependencyIds: string[], snapshot: QimingclawSnapshot | null): BusinessViewRow[] {
const stepsById = new Map(runtimePlanSteps(snapshot).map((step) => [step.id, step]));
return dependencyIds.map((dependencyId) => {
const dependency = stepsById.get(dependencyId);
if (!dependency) {
return {
step_id: dependencyId,
task_id: null,
latest_run_id: null,
title: dependencyId,
status: 'missing',
dependency_status: 'missing',
dispatchable: false,
skip_reason: 'missing_step',
};
}
const payload = asRecord(dependency.payload) ?? {};
const graph = asRecord(payload.dependencyGraph ?? payload.dependency_graph) ?? {};
const readiness = planStepDispatchReadiness(dependency, snapshot, payload);
return {
step_id: dependency.id,
task_id: readiness.taskId,
latest_run_id: readiness.latestRunId,
title: dependency.title,
status: dependency.status,
dependency_status: stringValue(graph.status) || dependency.status,
dispatchable: readiness.dispatchable,
skip_reason: readiness.skipReason,
};
});
}
function isTerminalRuntimeTaskStatus(status: string): boolean {