feat(workbench): refine dynamic task collaboration

This commit is contained in:
2026-09-24 16:36:12 +08:00
parent b64d2b78bb
commit 87cc7785da
25 changed files with 1216 additions and 470 deletions
@@ -0,0 +1,33 @@
import { ShieldCheck } from "lucide-react";
import type { OperationalTask, OperationalTaskDecision } from "../api/operational-task-client";
import { AccessRequestCard, HumanActionCard } from "./agent-execution-plan-panel";
type TaskConversationReviewProps = {
task: OperationalTask;
onAccessDecision: (requestId: string, version: number, decision: "approved" | "rejected", scopes: string[]) => Promise<unknown>;
onActionDecision: (actionId: string, version: number, decision: OperationalTaskDecision, comment?: string) => Promise<unknown>;
onActionExecute: (actionId: string, version: number) => Promise<unknown>;
onDraftUpdate: (actionId: string, version: number, payload: Record<string, unknown>) => Promise<unknown>;
onConfirmDispatch: (actionId: string, version: number) => Promise<unknown>;
onActionReconcile: (actionId: string, version: number) => Promise<unknown>;
onRefresh: () => void;
};
export function TaskConversationReview({ task, onAccessDecision, onActionDecision, onActionExecute,
onDraftUpdate, onConfirmDispatch, onActionReconcile, onRefresh }: TaskConversationReviewProps) {
const pendingAccess = task.access_requests.filter((request) => request.status === "pending");
const pendingActions = task.actions.filter((action) => action.approval_status === "pending"
|| action.approval_status === "approved" && ["not_submitted", "submitted", "unknown"].includes(action.execution_status));
if (pendingAccess.length === 0 && pendingActions.length === 0) return null;
return <section aria-label="当前任务审核" className="surface-reading space-y-2 rounded-xl border border-blue-200/80 p-3">
<div className="flex items-center gap-1.5 text-xs font-semibold text-slate-800"><ShieldCheck size={14} aria-hidden="true" />当前任务审核 · {task.title}</div>
{pendingAccess.map((request) => <AccessRequestCard key={request.access_request_id} request={request}
nodeTitle={task.latest_plan?.plan.nodes.find((node) => node.id === request.node_id)?.title}
canDecide={task.permissions.can_decide_access}
onDecision={(requestId, version, decision, scopes) => onAccessDecision(requestId, version, decision, scopes)}
onRefresh={onRefresh} />)}
{pendingActions.map((action) => <HumanActionCard key={action.action_id} task={task} action={action}
onDecision={onActionDecision} onExecute={onActionExecute} onDraftUpdate={onDraftUpdate}
onConfirmDispatch={onConfirmDispatch} onReconcile={onActionReconcile} onRefresh={onRefresh} />)}
</section>;
}