feat(orchestrator): redesign orchestrator page as template editor with terminal execution

Phase 1: Orchestrator Simplification
- Remove ExecutionMonitor from OrchestratorPage
- Replace "Run Workflow" button with "Send to Terminal" button
- Update i18n texts for template editor context

Phase 2: Session Lock Mechanism
- Add 'locked' status to TerminalStatus type
- Extend TerminalMeta with isLocked, lockReason, lockedByExecutionId, lockedAt
- Implement lockSession/unlockSession in sessionManagerStore
- Create SessionLockConfirmDialog component for input interception

Phase 3: Execution Monitor Panel
- Create executionMonitorStore for execution state management
- Create ExecutionMonitorPanel component with step progress display
- Add execution panel to DashboardToolbar and TerminalDashboardPage
- Support WebSocket message handling for execution updates

Phase 4: Execution Bridge
- Add POST /api/orchestrator/flows/:id/execute-in-session endpoint
- Create useExecuteFlowInSession hook for frontend API calls
- Broadcast EXECUTION_STARTED and CLI_SESSION_LOCKED WebSocket messages
- Lock session when execution starts, unlock on completion
This commit is contained in:
catlog22
2026-02-20 21:49:05 +08:00
parent b38750f0cf
commit f8ff9eaa7f
13 changed files with 1156 additions and 234 deletions

View File

@@ -34,6 +34,7 @@ import { useTerminalGridStore, selectTerminalGridFocusedPaneId } from '@/stores/
import { useWorkflowStore, selectProjectPath } from '@/stores/workflowStore';
import { toast } from '@/stores/notificationStore';
import { useExecutionMonitorStore, selectActiveExecutionCount } from '@/stores/executionMonitorStore';
import { useSessionManagerStore } from '@/stores/sessionManagerStore';
import { CliConfigModal, type CliSessionConfig } from './CliConfigModal';
// ========== Types ==========
@@ -106,6 +107,7 @@ export function DashboardToolbar({ activePanel, onTogglePanel, isFileSidebarOpen
const projectPath = useWorkflowStore(selectProjectPath);
const focusedPaneId = useTerminalGridStore(selectTerminalGridFocusedPaneId);
const createSessionAndAssign = useTerminalGridStore((s) => s.createSessionAndAssign);
const updateTerminalMeta = useSessionManagerStore((s) => s.updateTerminalMeta);
const [isCreating, setIsCreating] = useState(false);
const [isConfigOpen, setIsConfigOpen] = useState(false);
@@ -131,7 +133,7 @@ export function DashboardToolbar({ activePanel, onTogglePanel, isFileSidebarOpen
const targetPaneId = getOrCreateFocusedPane();
if (!targetPaneId) throw new Error('Failed to create pane');
await createSessionAndAssign(
const result = await createSessionAndAssign(
targetPaneId,
{
workingDir: config.workingDir || projectPath,
@@ -142,6 +144,14 @@ export function DashboardToolbar({ activePanel, onTogglePanel, isFileSidebarOpen
},
projectPath
);
// Store tag in terminalMetas for grouping
if (result?.session?.sessionKey) {
updateTerminalMeta(result.session.sessionKey, {
tag: config.tag,
title: config.tag,
});
}
} catch (error: unknown) {
const message = error instanceof Error
? error.message
@@ -153,7 +163,7 @@ export function DashboardToolbar({ activePanel, onTogglePanel, isFileSidebarOpen
} finally {
setIsCreating(false);
}
}, [projectPath, createSessionAndAssign, getOrCreateFocusedPane]);
}, [projectPath, createSessionAndAssign, getOrCreateFocusedPane, updateTerminalMeta]);
return (
<>