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
+20 -46
View File
@@ -40,10 +40,8 @@ import type { PeripheralWorkOrder } from "./peripheral-sample/client";
import { MapDevPanel } from "./components/map-dev-panel";
import { MobileWorkbenchSheet } from "./components/mobile-workbench-sheet";
import { FeaturePopover } from "./components/feature-popover";
import {
ScheduledConditionFeed,
type ScheduleCreateRequest
} from "./components/scheduled-condition-feed";
import { ScheduledConditionFeed } from "./components/scheduled-condition-feed";
import { TaskConversationReview } from "./components/task-conversation-review";
import { WorkbenchAgentPanels } from "./components/workbench-agent-panels";
import { OperationalTimeline } from "./operational-timeline/operational-timeline";
import {
@@ -105,7 +103,6 @@ import type {
DetailFeature,
ScheduledConditionItem,
ScheduledConditionRecord,
ScheduledConditionTaskId,
WorkbenchAlert,
WorkbenchUser
} from "./types";
@@ -115,17 +112,6 @@ import { createAlertQueueConversationPrompt } from "./utils/scheduled-condition-
const WORKBENCH_LAYOUT_CSS_VARIABLES = getWorkbenchLayoutCssVariables();
const SCHEDULED_CONDITION_TASK_IDS = new Set<ScheduledConditionTaskId>([
"scada-diagnosis",
"smart-dispatch",
"pump-energy",
"network-simulation"
]);
function isScheduledConditionTaskId(value: string): value is ScheduledConditionTaskId {
return SCHEDULED_CONDITION_TASK_IDS.has(value as ScheduledConditionTaskId);
}
export function MapWorkbenchPage({
user = WORKBENCH_USER,
onLogout,
@@ -164,9 +150,6 @@ export function MapWorkbenchPage({
const [layerVisibility, setLayerVisibility] =
useState<Record<string, boolean>>(INITIAL_LAYER_VISIBILITY);
const [agentUiResults, setAgentUiResults] = useState<AgentUiResult[]>([]);
const [createdMockScheduledTasks, setCreatedMockScheduledTasks] = useState<
ScheduledConditionRecord[]
>([]);
const workbenchSync = useWorkbenchSync(getAccessToken);
const workbenchSyncReconnecting =
workbenchSync.status === "reconnecting" && workbenchSync.snapshot !== null;
@@ -228,7 +211,6 @@ export function MapWorkbenchPage({
getAccessToken
});
const scheduledConditions = useMemo(() => [
...createdMockScheduledTasks,
...runtimeScheduledConditions,
...(operationalTasks.available
? operationalTasks.conditions.filter((condition) =>
@@ -236,30 +218,7 @@ export function MapWorkbenchPage({
|| condition.operationalTask?.task_type === "external_work_order"
)
: [])
], [createdMockScheduledTasks, operationalTasks.available, operationalTasks.conditions, runtimeScheduledConditions]);
const handleCreateMockScheduledTask = useCallback(async (input: ScheduleCreateRequest) => {
const taskId = isScheduledConditionTaskId(input.scheduleKey)
? input.scheduleKey
: "scada-diagnosis";
const condition: ScheduledConditionRecord = {
id: `local-scheduled-task-${crypto.randomUUID()}`,
kind: "condition",
taskId,
dataSource: "mock",
sessionId: `scheduled-condition-${taskId}-${Date.now()}`,
title: input.title,
summary: input.summary,
status: "pending",
riskLevel: "normal",
scheduledAt: input.nextRunAt,
updatedAt: Date.now(),
detail: `按 ${input.intervalSeconds / 60} 分钟周期执行,仅用于当前前端演示。`,
recommendation: "等待模拟执行窗口。",
modelName: "SupplyFlow 前端演示模拟器"
};
setCreatedMockScheduledTasks((current) => [condition, ...current]);
return condition;
}, []);
], [operationalTasks.available, operationalTasks.conditions, runtimeScheduledConditions]);
const workbenchAlerts = useMemo<WorkbenchAlert[]>(() => {
const taskNotifications = operationalTasks.notifications.flatMap((notification) => {
const route = getOperationalNotificationRoute(notification.kind);
@@ -1097,6 +1056,9 @@ export function MapWorkbenchPage({
}
return items;
}, [artifactWorkspace.activeArtifact, selectedOperationalEvent?.lane, workspaceContext]);
const collaborationReviewTask = agent.sessionPurpose !== "ordinary_chat" && agent.sessionTaskId
? operationalTasks.tasks.find((item) => item.task_id === agent.sessionTaskId)
: undefined;
const agentPanelProps: Omit<
ComponentProps<typeof AgentCommandPanel>,
"collapsing" | "onCollapse"
@@ -1116,6 +1078,14 @@ export function MapWorkbenchPage({
selectedModel: agent.selectedModel,
approvalMode: agent.approvalMode,
uiResults: activeAgentUiResults,
reviewPanel: collaborationReviewTask ? <TaskConversationReview task={collaborationReviewTask}
onAccessDecision={(requestId, version, decision, scopes) => operationalTasks.decideAccess(collaborationReviewTask.task_id, requestId, version, decision, scopes)}
onActionDecision={(actionId, version, decision, comment) => operationalTasks.decideAction(collaborationReviewTask.task_id, actionId, version, decision, comment)}
onActionExecute={(actionId, version) => operationalTasks.executeAction(collaborationReviewTask.task_id, actionId, version)}
onDraftUpdate={(actionId, version, payload) => operationalTasks.updateWorkOrderDraft(collaborationReviewTask.task_id, actionId, version, payload)}
onConfirmDispatch={(actionId, version) => operationalTasks.confirmWorkOrderDispatch(collaborationReviewTask.task_id, actionId, version)}
onActionReconcile={(actionId, version) => operationalTasks.reconcileAction(collaborationReviewTask.task_id, actionId, version)}
onRefresh={operationalTasks.refresh} /> : undefined,
workspaceContext: agentWorkspaceContext,
prompt: agent.promptDraft,
onRefreshHistory: agent.refreshSessionHistory,
@@ -1348,11 +1318,13 @@ export function MapWorkbenchPage({
onOpenTaskCollaboration={handleOpenTaskCollaboration}
onTaskDecision={operationalTasks.decideAction}
onTaskExecute={operationalTasks.executeAction}
onTaskDraftUpdate={operationalTasks.updateWorkOrderDraft}
onTaskConfirmDispatch={operationalTasks.confirmWorkOrderDispatch}
onTaskAccessDecision={operationalTasks.decideAccess}
onTaskReconcile={operationalTasks.reconcileAction}
onLoadTaskEvidenceSnapshot={operationalTasks.loadEvidenceSnapshot}
onTaskRefresh={operationalTasks.refresh}
onRefresh={workbenchSync.refresh}
onCreateSchedule={handleCreateMockScheduledTask}
/>
</div>
) : null}
@@ -1496,11 +1468,13 @@ export function MapWorkbenchPage({
onOpenTaskCollaboration={handleOpenTaskCollaboration}
onTaskDecision={operationalTasks.decideAction}
onTaskExecute={operationalTasks.executeAction}
onTaskDraftUpdate={operationalTasks.updateWorkOrderDraft}
onTaskConfirmDispatch={operationalTasks.confirmWorkOrderDispatch}
onTaskAccessDecision={operationalTasks.decideAccess}
onTaskReconcile={operationalTasks.reconcileAction}
onLoadTaskEvidenceSnapshot={operationalTasks.loadEvidenceSnapshot}
onTaskRefresh={operationalTasks.refresh}
onRefresh={workbenchSync.refresh}
onCreateSchedule={handleCreateMockScheduledTask}
/>
)}
</MobileWorkbenchSheet>