mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-06 15:39:41 +02:00
feat(ultracode): master-detail tab for Workflow/ultracode run visualization
Opt-in (showUltracodeAgents, default OFF) panel that visualizes ultracode / Workflow-tool runs like Claude Code's "working agents" TUI: LEFT = runs + phases (selectable tasks), RIGHT = each run's agents with model, live state, tokens burned, and tool calls. Standalone — ZERO edits to subagent-watcher.ts. A new workflow-run-watcher.ts singleton globs the run-state tree (~/.claude/projects/*/*/workflows/wf_*.json, disjoint from the transcript tree), strips the heavy script/scriptPath/result/logs fields (174KB -> ~25KB/run), and emits workflow:run_* SSE events. The LEFT list ships lightweight summaries (getLightState replay + SSE); the RIGHT pane fetches the full run (with agents[]) via GET /api/workflows/:runId on selection. Backend: workflow-run-watcher.ts, types/workflow-run.ts, config/workflow-config.ts, 3 SSE events, getLightState workflowRuns replay, GET /api/workflows[/:runId], showUltracodeAgents schema key + boot-gate (default OFF) + live toggleService. Frontend: ultracode-panel.js (debounced master-detail render, run/phase select), header launcher (btn-ultracode-agents--hidden marker -> mobile-guard-exempt), App Settings toggle (SYNCED, deliberately not in displayKeys). Agent states on disk are start|progress|done (start=queued; done has durationMs/resultPreview). Tests: workflow-run-watcher (9), workflow-routes (3). Verified: tsc/lint/prettier/frontend-syntax/public-assets/mobile-header-guard clean; full test:ci green (2986 passed); live server + Playwright e2e against 25 real runs (28-agent grid, phase filter, OFF hides launcher). Design: docs/ultracode-agent-viz-plan.md (rev. 3). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -221,6 +221,11 @@ const _SSE_HANDLER_MAP = [
|
||||
[SSE_EVENTS.SUBAGENT_TOOL_RESULT, '_onSubagentToolResult'],
|
||||
[SSE_EVENTS.SUBAGENT_COMPLETED, '_onSubagentCompleted'],
|
||||
|
||||
// Workflow runs (ultracode)
|
||||
[SSE_EVENTS.WORKFLOW_RUN_DISCOVERED, '_onWorkflowRunDiscovered'],
|
||||
[SSE_EVENTS.WORKFLOW_RUN_UPDATED, '_onWorkflowRunUpdated'],
|
||||
[SSE_EVENTS.WORKFLOW_RUN_REMOVED, '_onWorkflowRunRemoved'],
|
||||
|
||||
// Images
|
||||
[SSE_EVENTS.IMAGE_DETECTED, '_onImageDetected'],
|
||||
[SSE_EVENTS.ATTACHMENT_DETECTED, '_onAttachmentDetected'],
|
||||
@@ -339,6 +344,12 @@ class CodemanApp {
|
||||
this.subagentToolResults = new Map(); // Map<agentId, Map<toolUseId, result>> - tool results by toolUseId
|
||||
this.activeSubagentId = null; // Currently selected subagent for detail view
|
||||
this.subagentPanelVisible = false;
|
||||
|
||||
// Ultracode / Workflow run visualization (master-detail tab)
|
||||
this.workflowRuns = new Map(); // runId -> run summary (LEFT list)
|
||||
this.workflowRunDetails = new Map(); // runId -> full run with agents[] (RIGHT pane)
|
||||
this.activeWorkflowRunId = null;
|
||||
this.activeWorkflowPhaseIndex = null;
|
||||
this.subagentWindows = new Map(); // Map<agentId, { element, position }>
|
||||
this.subagentWindowZIndex = ZINDEX_SUBAGENT_BASE;
|
||||
this.minimizedSubagents = new Map(); // Map<sessionId, Set<agentId>> - minimized to tab
|
||||
@@ -2228,6 +2239,11 @@ class CodemanApp {
|
||||
// Clear subagent activity/results maps (prevents leaks if data.subagents is missing)
|
||||
this.subagentActivity.clear();
|
||||
this.subagentToolResults.clear();
|
||||
// Clear ultracode workflow run state (re-seeded from data.workflowRuns below)
|
||||
if (this.workflowRuns) this.workflowRuns.clear();
|
||||
if (this.workflowRunDetails) this.workflowRunDetails.clear();
|
||||
this.activeWorkflowRunId = null;
|
||||
this.activeWorkflowPhaseIndex = null;
|
||||
// Clean up mobile/keyboard handlers and re-init (prevents listener accumulation on reconnect)
|
||||
MobileDetection.cleanup();
|
||||
KeyboardHandler.cleanup();
|
||||
@@ -2402,6 +2418,11 @@ class CodemanApp {
|
||||
});
|
||||
}
|
||||
|
||||
// Seed ultracode workflow runs (LEFT-pane summaries) from the snapshot
|
||||
if (data.workflowRuns) {
|
||||
this.seedWorkflowRuns(data.workflowRuns);
|
||||
}
|
||||
|
||||
// Restore previously active session (survives page reload + SSE reconnect)
|
||||
// Must always re-select because handleInit clears terminal state above.
|
||||
// Reset activeSessionId so selectSession doesn't early-return.
|
||||
|
||||
Reference in New Issue
Block a user