@agimon-ai/doompi-workflow 0.0.1-alpha.76 → 0.0.1-alpha.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/api-contracts.cjs +7 -0
- package/dist/api-contracts.d.cts +2 -0
- package/dist/api-contracts.d.mts +2 -0
- package/dist/api-contracts.mjs +2 -0
- package/dist/extensions/pi.cjs +63 -0
- package/dist/extensions/pi.cjs.map +1 -0
- package/dist/extensions/pi.d.cts +6 -0
- package/dist/extensions/pi.d.cts.map +1 -0
- package/dist/extensions/pi.d.mts +6 -0
- package/dist/extensions/pi.d.mts.map +1 -0
- package/dist/extensions/pi.mjs +58 -0
- package/dist/extensions/pi.mjs.map +1 -0
- package/dist/extensions/server.cjs +96 -0
- package/dist/extensions/server.cjs.map +1 -0
- package/dist/extensions/server.d.cts +5 -0
- package/dist/extensions/server.d.cts.map +1 -0
- package/dist/extensions/server.d.mts +5 -0
- package/dist/extensions/server.d.mts.map +1 -0
- package/dist/extensions/server.mjs +91 -0
- package/dist/extensions/server.mjs.map +1 -0
- package/dist/extensions/web.mjs +3219 -0
- package/dist/extensions/web.mjs.map +1 -0
- package/dist/index.cjs +4 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +2 -0
- package/dist/src/constants/workflow.cjs +32 -0
- package/dist/src/constants/workflow.cjs.map +1 -0
- package/dist/src/constants/workflow.mjs +21 -0
- package/dist/src/constants/workflow.mjs.map +1 -0
- package/dist/src/extensions/(backend)/_lib/index.server.cjs +12 -0
- package/dist/src/extensions/(backend)/_lib/index.server.cjs.map +1 -0
- package/dist/src/extensions/(backend)/_lib/index.server.mjs +12 -0
- package/dist/src/extensions/(backend)/_lib/index.server.mjs.map +1 -0
- package/dist/src/extensions/(backend)/api/workflow/route.server.cjs +7 -0
- package/dist/src/extensions/(backend)/api/workflow/route.server.cjs.map +1 -0
- package/dist/src/extensions/(backend)/api/workflow/route.server.mjs +8 -0
- package/dist/src/extensions/(backend)/api/workflow/route.server.mjs.map +1 -0
- package/dist/src/extensions/(backend)/channel/workflow-catalog.server.cjs +7 -0
- package/dist/src/extensions/(backend)/channel/workflow-catalog.server.cjs.map +1 -0
- package/dist/src/extensions/(backend)/channel/workflow-catalog.server.mjs +8 -0
- package/dist/src/extensions/(backend)/channel/workflow-catalog.server.mjs.map +1 -0
- package/dist/src/extensions/(backend)/channel/workflows.server.cjs +7 -0
- package/dist/src/extensions/(backend)/channel/workflows.server.cjs.map +1 -0
- package/dist/src/extensions/(backend)/channel/workflows.server.mjs +8 -0
- package/dist/src/extensions/(backend)/channel/workflows.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.cjs +100 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.mjs +100 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.cjs +11 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.mjs +11 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.cjs +12 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.mjs +12 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs +15 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs +16 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs +17 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs +18 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.cjs +50 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.mjs +47 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.cjs +36 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.mjs +35 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.mjs.map +1 -0
- package/dist/src/schemas/apiContracts.cjs +330 -0
- package/dist/src/schemas/apiContracts.cjs.map +1 -0
- package/dist/src/schemas/apiContracts.d.cts +53 -0
- package/dist/src/schemas/apiContracts.d.cts.map +1 -0
- package/dist/src/schemas/apiContracts.d.mts +53 -0
- package/dist/src/schemas/apiContracts.d.mts.map +1 -0
- package/dist/src/schemas/apiContracts.mjs +327 -0
- package/dist/src/schemas/apiContracts.mjs.map +1 -0
- package/dist/src/schemas/workflowPi.cjs +77 -0
- package/dist/src/schemas/workflowPi.cjs.map +1 -0
- package/dist/src/schemas/workflowPi.d.cts +1 -0
- package/dist/src/schemas/workflowPi.d.mts +1 -0
- package/dist/src/schemas/workflowPi.mjs +74 -0
- package/dist/src/schemas/workflowPi.mjs.map +1 -0
- package/dist/src/services/backgroundWork/index.cjs +61 -0
- package/dist/src/services/backgroundWork/index.cjs.map +1 -0
- package/dist/src/services/backgroundWork/index.mjs +61 -0
- package/dist/src/services/backgroundWork/index.mjs.map +1 -0
- package/dist/src/services/piToolBridge/index.cjs +205 -0
- package/dist/src/services/piToolBridge/index.cjs.map +1 -0
- package/dist/src/services/piToolBridge/index.mjs +195 -0
- package/dist/src/services/piToolBridge/index.mjs.map +1 -0
- package/dist/src/services/serverRuntime/index.cjs +387 -0
- package/dist/src/services/serverRuntime/index.cjs.map +1 -0
- package/dist/src/services/serverRuntime/index.mjs +387 -0
- package/dist/src/services/serverRuntime/index.mjs.map +1 -0
- package/dist/src/services/webWorkflowCatalog/index.cjs +53 -0
- package/dist/src/services/webWorkflowCatalog/index.cjs.map +1 -0
- package/dist/src/services/webWorkflowCatalog/index.mjs +52 -0
- package/dist/src/services/webWorkflowCatalog/index.mjs.map +1 -0
- package/dist/src/services/workflowCatalogChannel/index.cjs +74 -0
- package/dist/src/services/workflowCatalogChannel/index.cjs.map +1 -0
- package/dist/src/services/workflowCatalogChannel/index.mjs +74 -0
- package/dist/src/services/workflowCatalogChannel/index.mjs.map +1 -0
- package/dist/src/services/workflowCatalogDeps/index.cjs +25 -0
- package/dist/src/services/workflowCatalogDeps/index.cjs.map +1 -0
- package/dist/src/services/workflowCatalogDeps/index.mjs +25 -0
- package/dist/src/services/workflowCatalogDeps/index.mjs.map +1 -0
- package/dist/src/services/workflowExecution/index.cjs +205 -0
- package/dist/src/services/workflowExecution/index.cjs.map +1 -0
- package/dist/src/services/workflowExecution/index.d.cts +6 -0
- package/dist/src/services/workflowExecution/index.d.mts +6 -0
- package/dist/src/services/workflowExecution/index.mjs +200 -0
- package/dist/src/services/workflowExecution/index.mjs.map +1 -0
- package/dist/src/services/workflowFence/index.cjs +170 -0
- package/dist/src/services/workflowFence/index.cjs.map +1 -0
- package/dist/src/services/workflowFence/index.mjs +166 -0
- package/dist/src/services/workflowFence/index.mjs.map +1 -0
- package/dist/src/services/workflowHubApi/index.cjs +415 -0
- package/dist/src/services/workflowHubApi/index.cjs.map +1 -0
- package/dist/src/services/workflowHubApi/index.mjs +411 -0
- package/dist/src/services/workflowHubApi/index.mjs.map +1 -0
- package/dist/src/services/workflowLaunchCommand/index.cjs +121 -0
- package/dist/src/services/workflowLaunchCommand/index.cjs.map +1 -0
- package/dist/src/services/workflowLaunchCommand/index.d.cts +52 -0
- package/dist/src/services/workflowLaunchCommand/index.d.cts.map +1 -0
- package/dist/src/services/workflowLaunchCommand/index.d.mts +52 -0
- package/dist/src/services/workflowLaunchCommand/index.d.mts.map +1 -0
- package/dist/src/services/workflowLaunchCommand/index.mjs +118 -0
- package/dist/src/services/workflowLaunchCommand/index.mjs.map +1 -0
- package/dist/src/services/workflowLauncher/index.cjs +181 -0
- package/dist/src/services/workflowLauncher/index.cjs.map +1 -0
- package/dist/src/services/workflowLauncher/index.mjs +177 -0
- package/dist/src/services/workflowLauncher/index.mjs.map +1 -0
- package/dist/src/services/workflowNarration/index.cjs +19 -0
- package/dist/src/services/workflowNarration/index.cjs.map +1 -0
- package/dist/src/services/workflowNarration/index.mjs +19 -0
- package/dist/src/services/workflowNarration/index.mjs.map +1 -0
- package/dist/src/services/workflowResource/index.cjs +27 -0
- package/dist/src/services/workflowResource/index.cjs.map +1 -0
- package/dist/src/services/workflowResource/index.mjs +24 -0
- package/dist/src/services/workflowResource/index.mjs.map +1 -0
- package/dist/src/services/workflowRuns/index.cjs +333 -0
- package/dist/src/services/workflowRuns/index.cjs.map +1 -0
- package/dist/src/services/workflowRuns/index.mjs +319 -0
- package/dist/src/services/workflowRuns/index.mjs.map +1 -0
- package/dist/src/services/workflowTerminal/index.cjs +69 -0
- package/dist/src/services/workflowTerminal/index.cjs.map +1 -0
- package/dist/src/services/workflowTerminal/index.mjs +69 -0
- package/dist/src/services/workflowTerminal/index.mjs.map +1 -0
- package/dist/src/services/workflowTools/index.cjs +221 -0
- package/dist/src/services/workflowTools/index.cjs.map +1 -0
- package/dist/src/services/workflowTools/index.mjs +221 -0
- package/dist/src/services/workflowTools/index.mjs.map +1 -0
- package/dist/src/services/workflowWatcher/index.cjs +78 -0
- package/dist/src/services/workflowWatcher/index.cjs.map +1 -0
- package/dist/src/services/workflowWatcher/index.mjs +74 -0
- package/dist/src/services/workflowWatcher/index.mjs.map +1 -0
- package/dist/src/services/workflowsHubChannel/index.cjs +58 -0
- package/dist/src/services/workflowsHubChannel/index.cjs.map +1 -0
- package/dist/src/services/workflowsHubChannel/index.mjs +58 -0
- package/dist/src/services/workflowsHubChannel/index.mjs.map +1 -0
- package/dist/src/tui/leader.cjs +84 -0
- package/dist/src/tui/leader.cjs.map +1 -0
- package/dist/src/tui/leader.mjs +83 -0
- package/dist/src/tui/leader.mjs.map +1 -0
- package/dist/src/tui/workflow/doomOverlay.cjs +159 -0
- package/dist/src/tui/workflow/doomOverlay.cjs.map +1 -0
- package/dist/src/tui/workflow/doomOverlay.mjs +157 -0
- package/dist/src/tui/workflow/doomOverlay.mjs.map +1 -0
- package/dist/src/tui/workflow/overlayText.cjs +83 -0
- package/dist/src/tui/workflow/overlayText.cjs.map +1 -0
- package/dist/src/tui/workflow/overlayText.mjs +78 -0
- package/dist/src/tui/workflow/overlayText.mjs.map +1 -0
- package/dist/src/tui/workflow/rendering.cjs +22 -0
- package/dist/src/tui/workflow/rendering.cjs.map +1 -0
- package/dist/src/tui/workflow/rendering.mjs +20 -0
- package/dist/src/tui/workflow/rendering.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowCatalog.cjs +336 -0
- package/dist/src/tui/workflow/workflowCatalog.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowCatalog.mjs +333 -0
- package/dist/src/tui/workflow/workflowCatalog.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowFinishedMessage.cjs +50 -0
- package/dist/src/tui/workflow/workflowFinishedMessage.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowFinishedMessage.mjs +47 -0
- package/dist/src/tui/workflow/workflowFinishedMessage.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowInspector.cjs +276 -0
- package/dist/src/tui/workflow/workflowInspector.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowInspector.mjs +276 -0
- package/dist/src/tui/workflow/workflowInspector.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowOverlay.cjs +126 -0
- package/dist/src/tui/workflow/workflowOverlay.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowOverlay.mjs +125 -0
- package/dist/src/tui/workflow/workflowOverlay.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowPicker.cjs +138 -0
- package/dist/src/tui/workflow/workflowPicker.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowPicker.mjs +136 -0
- package/dist/src/tui/workflow/workflowPicker.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowProgressOverlay.cjs +197 -0
- package/dist/src/tui/workflow/workflowProgressOverlay.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowProgressOverlay.mjs +192 -0
- package/dist/src/tui/workflow/workflowProgressOverlay.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowPrompt.cjs +142 -0
- package/dist/src/tui/workflow/workflowPrompt.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowPrompt.mjs +139 -0
- package/dist/src/tui/workflow/workflowPrompt.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowRunPanel.cjs +95 -0
- package/dist/src/tui/workflow/workflowRunPanel.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowRunPanel.mjs +94 -0
- package/dist/src/tui/workflow/workflowRunPanel.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowStatusRow.cjs +20 -0
- package/dist/src/tui/workflow/workflowStatusRow.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowStatusRow.mjs +20 -0
- package/dist/src/tui/workflow/workflowStatusRow.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowStepMessage.cjs +32 -0
- package/dist/src/tui/workflow/workflowStepMessage.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowStepMessage.mjs +31 -0
- package/dist/src/tui/workflow/workflowStepMessage.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowToolRender.cjs +491 -0
- package/dist/src/tui/workflow/workflowToolRender.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowToolRender.mjs +490 -0
- package/dist/src/tui/workflow/workflowToolRender.mjs.map +1 -0
- package/dist/src/tui/workflowRuntime.cjs +1934 -0
- package/dist/src/tui/workflowRuntime.cjs.map +1 -0
- package/dist/src/tui/workflowRuntime.d.cts +33 -0
- package/dist/src/tui/workflowRuntime.d.cts.map +1 -0
- package/dist/src/tui/workflowRuntime.d.mts +33 -0
- package/dist/src/tui/workflowRuntime.d.mts.map +1 -0
- package/dist/src/tui/workflowRuntime.mjs +1930 -0
- package/dist/src/tui/workflowRuntime.mjs.map +1 -0
- package/dist/src/types/apiRoutes.cjs +82 -0
- package/dist/src/types/apiRoutes.cjs.map +1 -0
- package/dist/src/types/apiRoutes.mjs +80 -0
- package/dist/src/types/apiRoutes.mjs.map +1 -0
- package/dist/src/types/webWorkflowTerminal.cjs +23 -0
- package/dist/src/types/webWorkflowTerminal.cjs.map +1 -0
- package/dist/src/types/webWorkflowTerminal.mjs +22 -0
- package/dist/src/types/webWorkflowTerminal.mjs.map +1 -0
- package/dist/src/types/webWorkflows.cjs +8 -0
- package/dist/src/types/webWorkflows.cjs.map +1 -0
- package/dist/src/types/webWorkflows.mjs +7 -0
- package/dist/src/types/webWorkflows.mjs.map +1 -0
- package/package.json +8 -8
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
let _earendil_works_pi_tui = require("@earendil-works/pi-tui");
|
|
2
|
+
//#region src/tui/workflow/workflowProgressOverlay.ts
|
|
3
|
+
const WORKFLOW_PROGRESS_WIDGET_KEY = "workflow-mcp-progress";
|
|
4
|
+
const OVERLAY_HEADING = "Workflows";
|
|
5
|
+
const PROGRESS_TICK_MS = 200;
|
|
6
|
+
const RUNNING_SPINNER_FRAMES = [
|
|
7
|
+
"⠋",
|
|
8
|
+
"⠙",
|
|
9
|
+
"⠹",
|
|
10
|
+
"⠸",
|
|
11
|
+
"⠼",
|
|
12
|
+
"⠴",
|
|
13
|
+
"⠦",
|
|
14
|
+
"⠧",
|
|
15
|
+
"⠇",
|
|
16
|
+
"⠏"
|
|
17
|
+
];
|
|
18
|
+
const STATIC_PROGRESS_MARKER = "*";
|
|
19
|
+
const MILLISECONDS_PER_SECOND = 1e3;
|
|
20
|
+
const SECONDS_PER_MINUTE = 60;
|
|
21
|
+
const MINUTES_PER_HOUR = 60;
|
|
22
|
+
const STARTING_JOB_STEP = "Starting job";
|
|
23
|
+
const STARTING_WORKFLOW_STEP = "Starting workflow";
|
|
24
|
+
const PREPARING_WORKFLOW_STEP = "Preparing workflow";
|
|
25
|
+
const FINALIZING_WORKFLOW_STEP = "Finalizing workflow";
|
|
26
|
+
/** One explicit palette makes every workflow state visually stable across the list. */
|
|
27
|
+
const WORKFLOW_PROGRESS_COLORS = {
|
|
28
|
+
starting: "dim",
|
|
29
|
+
running: "accent",
|
|
30
|
+
completed: "success",
|
|
31
|
+
paused: "warning",
|
|
32
|
+
failed: "error",
|
|
33
|
+
skipped: "muted"
|
|
34
|
+
};
|
|
35
|
+
function latestStep(events) {
|
|
36
|
+
return events.findLast((event) => event.type === "step" && !!event.step);
|
|
37
|
+
}
|
|
38
|
+
function latestEvent(events) {
|
|
39
|
+
return events.at(-1);
|
|
40
|
+
}
|
|
41
|
+
function progressState(record, event) {
|
|
42
|
+
if (record.stage === "error") return "failed";
|
|
43
|
+
if (record.stage === "completed") return "completed";
|
|
44
|
+
if (record.executionState === "paused" || record.executionState === "pause_requested") return "paused";
|
|
45
|
+
switch (event?.status) {
|
|
46
|
+
case "failed": return "failed";
|
|
47
|
+
case "paused":
|
|
48
|
+
case "pause_requested": return "paused";
|
|
49
|
+
case "completed": return "completed";
|
|
50
|
+
case "skipped": return "skipped";
|
|
51
|
+
case "resumed":
|
|
52
|
+
case "running": return "running";
|
|
53
|
+
default: return record.executionCursor?.stepName ? "running" : "starting";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function fallbackStep(record) {
|
|
57
|
+
switch (record.executionCursor?.phase) {
|
|
58
|
+
case "pre": return PREPARING_WORKFLOW_STEP;
|
|
59
|
+
case "post": return FINALIZING_WORKFLOW_STEP;
|
|
60
|
+
case "job":
|
|
61
|
+
case "step": return STARTING_JOB_STEP;
|
|
62
|
+
default: return STARTING_WORKFLOW_STEP;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** Derive the single current line for one run from its record and pushed progress events. */
|
|
66
|
+
function workflowProgressRow(record, events) {
|
|
67
|
+
const stepEvent = latestStep(events);
|
|
68
|
+
const event = latestEvent(events);
|
|
69
|
+
const cursor = record.executionCursor;
|
|
70
|
+
const job = cursor?.job ?? stepEvent?.job ?? event?.job ?? record.job ?? cursor?.phase ?? "workflow";
|
|
71
|
+
const step = cursor?.stepName ?? (stepEvent?.job === job ? stepEvent.step : void 0) ?? fallbackStep(record);
|
|
72
|
+
return {
|
|
73
|
+
job,
|
|
74
|
+
key: record.runId ?? `${record.workspace}/${record.runKey}`,
|
|
75
|
+
name: record.displayName,
|
|
76
|
+
startedAt: record.startedAt,
|
|
77
|
+
state: progressState(record, event),
|
|
78
|
+
step
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/** Task-style elapsed time: whole seconds stay stable and compact between animation ticks. */
|
|
82
|
+
function formatWorkflowDuration(durationMs) {
|
|
83
|
+
if (!Number.isFinite(durationMs) || durationMs < 0) return "?";
|
|
84
|
+
const totalSeconds = Math.floor(durationMs / MILLISECONDS_PER_SECOND);
|
|
85
|
+
const seconds = totalSeconds % SECONDS_PER_MINUTE;
|
|
86
|
+
const totalMinutes = Math.floor(totalSeconds / SECONDS_PER_MINUTE);
|
|
87
|
+
if (totalMinutes < MINUTES_PER_HOUR) return totalMinutes === 0 ? `${seconds}s` : `${totalMinutes}m${String(seconds).padStart(2, "0")}s`;
|
|
88
|
+
const minutes = totalMinutes % MINUTES_PER_HOUR;
|
|
89
|
+
return `${Math.floor(totalMinutes / MINUTES_PER_HOUR)}h${String(minutes).padStart(2, "0")}m${String(seconds).padStart(2, "0")}s`;
|
|
90
|
+
}
|
|
91
|
+
function progressMarker(state, nowMs) {
|
|
92
|
+
if (state !== "running" && state !== "starting") return STATIC_PROGRESS_MARKER;
|
|
93
|
+
const tick = Number.isFinite(nowMs) ? Math.floor(Math.max(0, nowMs) / PROGRESS_TICK_MS) : 0;
|
|
94
|
+
return RUNNING_SPINNER_FRAMES[tick % RUNNING_SPINNER_FRAMES.length] ?? RUNNING_SPINNER_FRAMES[0];
|
|
95
|
+
}
|
|
96
|
+
/** Render exactly: `<workflow name>[<duration>][<job>] <activity> <step>`. */
|
|
97
|
+
function formatWorkflowProgressRow(row, theme, nowMs = Date.now()) {
|
|
98
|
+
const startedAt = Date.parse(row.startedAt);
|
|
99
|
+
const duration = formatWorkflowDuration(Number.isFinite(startedAt) ? nowMs - startedAt : NaN);
|
|
100
|
+
const color = WORKFLOW_PROGRESS_COLORS[row.state];
|
|
101
|
+
return [
|
|
102
|
+
theme.fg(color, row.name),
|
|
103
|
+
theme.fg("muted", `[${duration}][${row.job}]`),
|
|
104
|
+
theme.fg(color, ` ${progressMarker(row.state, nowMs)} `),
|
|
105
|
+
theme.fg("text", row.step)
|
|
106
|
+
].join("");
|
|
107
|
+
}
|
|
108
|
+
/** Persistent workflow widget with the same heading/tree shape as Doom's task list. */
|
|
109
|
+
var WorkflowProgressOverlay = class {
|
|
110
|
+
rows = [];
|
|
111
|
+
uiCtx;
|
|
112
|
+
widgetRegistered = false;
|
|
113
|
+
tui;
|
|
114
|
+
progressTimer;
|
|
115
|
+
/** Identity-compare so repeated session starts do not register duplicate widgets. */
|
|
116
|
+
setUICtx(ctx) {
|
|
117
|
+
if (ctx === this.uiCtx) return;
|
|
118
|
+
if (this.uiCtx && this.widgetRegistered) this.uiCtx.setWidget(WORKFLOW_PROGRESS_WIDGET_KEY, void 0);
|
|
119
|
+
this.stopProgressTimer();
|
|
120
|
+
this.uiCtx = ctx;
|
|
121
|
+
this.widgetRegistered = false;
|
|
122
|
+
this.tui = void 0;
|
|
123
|
+
}
|
|
124
|
+
update(rows) {
|
|
125
|
+
this.rows = rows;
|
|
126
|
+
if (!this.uiCtx) {
|
|
127
|
+
this.stopProgressTimer();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (rows.length === 0) {
|
|
131
|
+
if (this.widgetRegistered) {
|
|
132
|
+
this.uiCtx.setWidget(WORKFLOW_PROGRESS_WIDGET_KEY, void 0);
|
|
133
|
+
this.widgetRegistered = false;
|
|
134
|
+
this.tui = void 0;
|
|
135
|
+
}
|
|
136
|
+
this.stopProgressTimer();
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (this.widgetRegistered) {
|
|
140
|
+
this.syncProgressTimer();
|
|
141
|
+
this.tui?.requestRender();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
this.uiCtx.setWidget(WORKFLOW_PROGRESS_WIDGET_KEY, (tui, factoryTheme) => {
|
|
145
|
+
this.tui = tui;
|
|
146
|
+
return {
|
|
147
|
+
render: (width) => this.renderWidget(this.uiCtx?.theme ?? factoryTheme, width),
|
|
148
|
+
invalidate: () => {}
|
|
149
|
+
};
|
|
150
|
+
}, { placement: "aboveEditor" });
|
|
151
|
+
this.widgetRegistered = true;
|
|
152
|
+
this.syncProgressTimer();
|
|
153
|
+
}
|
|
154
|
+
syncProgressTimer() {
|
|
155
|
+
if (!this.widgetRegistered || this.rows.length === 0) {
|
|
156
|
+
this.stopProgressTimer();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (this.progressTimer) return;
|
|
160
|
+
this.progressTimer = setInterval(() => this.tui?.requestRender(), PROGRESS_TICK_MS);
|
|
161
|
+
this.progressTimer.unref?.();
|
|
162
|
+
}
|
|
163
|
+
stopProgressTimer() {
|
|
164
|
+
if (this.progressTimer) clearInterval(this.progressTimer);
|
|
165
|
+
this.progressTimer = void 0;
|
|
166
|
+
}
|
|
167
|
+
renderWidget(theme, width) {
|
|
168
|
+
if (this.rows.length === 0) return [];
|
|
169
|
+
const truncate = (line) => (0, _earendil_works_pi_tui.truncateToWidth)(line, width, "…");
|
|
170
|
+
const heading = truncate(`${theme.fg("accent", "●")} ${theme.fg("accent", `${OVERLAY_HEADING} (${this.rows.length})`)}`);
|
|
171
|
+
const nowMs = Date.now();
|
|
172
|
+
const lines = [heading];
|
|
173
|
+
for (const [index, row] of this.rows.entries()) {
|
|
174
|
+
const branch = index === this.rows.length - 1 ? "└─" : "├─";
|
|
175
|
+
lines.push(truncate(`${theme.fg("dim", branch)} ${formatWorkflowProgressRow(row, theme, nowMs)}`));
|
|
176
|
+
}
|
|
177
|
+
lines.push("");
|
|
178
|
+
return lines;
|
|
179
|
+
}
|
|
180
|
+
dispose() {
|
|
181
|
+
this.stopProgressTimer();
|
|
182
|
+
if (this.uiCtx) this.uiCtx.setWidget(WORKFLOW_PROGRESS_WIDGET_KEY, void 0);
|
|
183
|
+
this.rows = [];
|
|
184
|
+
this.widgetRegistered = false;
|
|
185
|
+
this.tui = void 0;
|
|
186
|
+
this.uiCtx = void 0;
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
//#endregion
|
|
190
|
+
exports.WORKFLOW_PROGRESS_COLORS = WORKFLOW_PROGRESS_COLORS;
|
|
191
|
+
exports.WORKFLOW_PROGRESS_WIDGET_KEY = WORKFLOW_PROGRESS_WIDGET_KEY;
|
|
192
|
+
exports.WorkflowProgressOverlay = WorkflowProgressOverlay;
|
|
193
|
+
exports.formatWorkflowDuration = formatWorkflowDuration;
|
|
194
|
+
exports.formatWorkflowProgressRow = formatWorkflowProgressRow;
|
|
195
|
+
exports.workflowProgressRow = workflowProgressRow;
|
|
196
|
+
|
|
197
|
+
//# sourceMappingURL=workflowProgressOverlay.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflowProgressOverlay.cjs","names":["truncateToWidth"],"sources":["../../../../src/tui/workflow/workflowProgressOverlay.ts"],"sourcesContent":["/**\n * Task-like live workflow list shown above Pi's editor.\n *\n * DESIGN PATTERNS:\n * - The extension owns run/event state; this component only projects and renders it.\n * - Register the widget once, then request redraws as progress, elapsed time, or the spinner changes.\n * - Terminal runs are absent from `rows`, so the widget disappears when the last run ends.\n *\n * CODING STANDARDS:\n * - Every rendered line is ANSI-aware and truncated to the available terminal width.\n * - Theme colors come from Pi's live UI context so theme changes repaint correctly.\n * - Named exports only and explicit return types on exported members.\n *\n * AVOID:\n * - Persisting progress in the chat transcript.\n * - Starting timers while no workflow is visible.\n */\n\nimport type { WorkflowProgressEvent, WorkflowRunRecord } from '@agimon-ai/workflow-mcp';\nimport type { ExtensionUIContext, Theme } from '@earendil-works/pi-coding-agent';\nimport { type TUI, truncateToWidth } from '@earendil-works/pi-tui';\n\nexport const WORKFLOW_PROGRESS_WIDGET_KEY = 'workflow-mcp-progress';\n\nconst OVERLAY_HEADING = 'Workflows';\nconst PROGRESS_TICK_MS = 200;\nconst RUNNING_SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'] as const;\nconst STATIC_PROGRESS_MARKER = '*';\nconst MILLISECONDS_PER_SECOND = 1000;\nconst SECONDS_PER_MINUTE = 60;\nconst MINUTES_PER_HOUR = 60;\nconst STARTING_JOB_STEP = 'Starting job';\nconst STARTING_WORKFLOW_STEP = 'Starting workflow';\nconst PREPARING_WORKFLOW_STEP = 'Preparing workflow';\nconst FINALIZING_WORKFLOW_STEP = 'Finalizing workflow';\n\ntype WorkflowProgressColor = Parameters<Theme['fg']>[0];\n\nexport type WorkflowProgressState = 'completed' | 'failed' | 'paused' | 'running' | 'skipped' | 'starting';\n\n/** One explicit palette makes every workflow state visually stable across the list. */\nexport const WORKFLOW_PROGRESS_COLORS: Readonly<Record<WorkflowProgressState, WorkflowProgressColor>> = {\n starting: 'dim',\n running: 'accent',\n completed: 'success',\n paused: 'warning',\n failed: 'error',\n skipped: 'muted',\n};\n\nexport interface WorkflowProgressRow {\n job: string;\n key: string;\n name: string;\n startedAt: string;\n state: WorkflowProgressState;\n step: string;\n}\n\nfunction latestStep(events: readonly WorkflowProgressEvent[]): WorkflowProgressEvent | undefined {\n return events.findLast((event) => event.type === 'step' && !!event.step);\n}\n\nfunction latestEvent(events: readonly WorkflowProgressEvent[]): WorkflowProgressEvent | undefined {\n return events.at(-1);\n}\n\nfunction progressState(record: WorkflowRunRecord, event: WorkflowProgressEvent | undefined): WorkflowProgressState {\n if (record.stage === 'error') return 'failed';\n if (record.stage === 'completed') return 'completed';\n if (record.executionState === 'paused' || record.executionState === 'pause_requested') return 'paused';\n\n switch (event?.status) {\n case 'failed':\n return 'failed';\n case 'paused':\n case 'pause_requested':\n return 'paused';\n case 'completed':\n return 'completed';\n case 'skipped':\n return 'skipped';\n case 'resumed':\n case 'running':\n return 'running';\n default:\n return record.executionCursor?.stepName ? 'running' : 'starting';\n }\n}\n\nfunction fallbackStep(record: WorkflowRunRecord): string {\n switch (record.executionCursor?.phase) {\n case 'pre':\n return PREPARING_WORKFLOW_STEP;\n case 'post':\n return FINALIZING_WORKFLOW_STEP;\n case 'job':\n case 'step':\n return STARTING_JOB_STEP;\n default:\n return STARTING_WORKFLOW_STEP;\n }\n}\n\n/** Derive the single current line for one run from its record and pushed progress events. */\nexport function workflowProgressRow(\n record: WorkflowRunRecord,\n events: readonly WorkflowProgressEvent[],\n): WorkflowProgressRow {\n const stepEvent = latestStep(events);\n const event = latestEvent(events);\n const cursor = record.executionCursor;\n const job = cursor?.job ?? stepEvent?.job ?? event?.job ?? record.job ?? cursor?.phase ?? 'workflow';\n const step = cursor?.stepName ?? (stepEvent?.job === job ? stepEvent.step : undefined) ?? fallbackStep(record);\n\n return {\n job,\n key: record.runId ?? `${record.workspace}/${record.runKey}`,\n name: record.displayName,\n startedAt: record.startedAt,\n state: progressState(record, event),\n step,\n };\n}\n\n/** Task-style elapsed time: whole seconds stay stable and compact between animation ticks. */\nexport function formatWorkflowDuration(durationMs: number): string {\n if (!Number.isFinite(durationMs) || durationMs < 0) return '?';\n const totalSeconds = Math.floor(durationMs / MILLISECONDS_PER_SECOND);\n const seconds = totalSeconds % SECONDS_PER_MINUTE;\n const totalMinutes = Math.floor(totalSeconds / SECONDS_PER_MINUTE);\n if (totalMinutes < MINUTES_PER_HOUR) {\n return totalMinutes === 0 ? `${seconds}s` : `${totalMinutes}m${String(seconds).padStart(2, '0')}s`;\n }\n const minutes = totalMinutes % MINUTES_PER_HOUR;\n const hours = Math.floor(totalMinutes / MINUTES_PER_HOUR);\n return `${hours}h${String(minutes).padStart(2, '0')}m${String(seconds).padStart(2, '0')}s`;\n}\n\nfunction progressMarker(state: WorkflowProgressState, nowMs: number): string {\n if (state !== 'running' && state !== 'starting') return STATIC_PROGRESS_MARKER;\n const tick = Number.isFinite(nowMs) ? Math.floor(Math.max(0, nowMs) / PROGRESS_TICK_MS) : 0;\n return RUNNING_SPINNER_FRAMES[tick % RUNNING_SPINNER_FRAMES.length] ?? RUNNING_SPINNER_FRAMES[0];\n}\n\n/** Render exactly: `<workflow name>[<duration>][<job>] <activity> <step>`. */\nexport function formatWorkflowProgressRow(row: WorkflowProgressRow, theme: Theme, nowMs = Date.now()): string {\n const startedAt = Date.parse(row.startedAt);\n const duration = formatWorkflowDuration(Number.isFinite(startedAt) ? nowMs - startedAt : Number.NaN);\n const color = WORKFLOW_PROGRESS_COLORS[row.state];\n return [\n theme.fg(color, row.name),\n theme.fg('muted', `[${duration}][${row.job}]`),\n theme.fg(color, ` ${progressMarker(row.state, nowMs)} `),\n theme.fg('text', row.step),\n ].join('');\n}\n\n/** Persistent workflow widget with the same heading/tree shape as Doom's task list. */\nexport class WorkflowProgressOverlay {\n private rows: readonly WorkflowProgressRow[] = [];\n private uiCtx: ExtensionUIContext | undefined;\n private widgetRegistered = false;\n private tui: TUI | undefined;\n private progressTimer: NodeJS.Timeout | undefined;\n\n /** Identity-compare so repeated session starts do not register duplicate widgets. */\n setUICtx(ctx: ExtensionUIContext): void {\n if (ctx === this.uiCtx) return;\n if (this.uiCtx && this.widgetRegistered) this.uiCtx.setWidget(WORKFLOW_PROGRESS_WIDGET_KEY, undefined);\n this.stopProgressTimer();\n this.uiCtx = ctx;\n this.widgetRegistered = false;\n this.tui = undefined;\n }\n\n update(rows: readonly WorkflowProgressRow[]): void {\n this.rows = rows;\n if (!this.uiCtx) {\n this.stopProgressTimer();\n return;\n }\n\n if (rows.length === 0) {\n if (this.widgetRegistered) {\n this.uiCtx.setWidget(WORKFLOW_PROGRESS_WIDGET_KEY, undefined);\n this.widgetRegistered = false;\n this.tui = undefined;\n }\n this.stopProgressTimer();\n return;\n }\n\n if (this.widgetRegistered) {\n this.syncProgressTimer();\n this.tui?.requestRender();\n return;\n }\n\n this.uiCtx.setWidget(\n WORKFLOW_PROGRESS_WIDGET_KEY,\n (tui, factoryTheme) => {\n this.tui = tui;\n return {\n render: (width: number) => this.renderWidget(this.uiCtx?.theme ?? factoryTheme, width),\n invalidate: () => {\n // Nothing cached: the next render reads the current rows, clock, and theme.\n },\n };\n },\n { placement: 'aboveEditor' },\n );\n this.widgetRegistered = true;\n this.syncProgressTimer();\n }\n\n private syncProgressTimer(): void {\n if (!this.widgetRegistered || this.rows.length === 0) {\n this.stopProgressTimer();\n return;\n }\n if (this.progressTimer) return;\n this.progressTimer = setInterval(() => this.tui?.requestRender(), PROGRESS_TICK_MS);\n this.progressTimer.unref?.();\n }\n\n private stopProgressTimer(): void {\n if (this.progressTimer) clearInterval(this.progressTimer);\n this.progressTimer = undefined;\n }\n\n private renderWidget(theme: Theme, width: number): string[] {\n if (this.rows.length === 0) return [];\n const truncate = (line: string): string => truncateToWidth(line, width, '…');\n const heading = truncate(\n `${theme.fg('accent', '●')} ${theme.fg('accent', `${OVERLAY_HEADING} (${this.rows.length})`)}`,\n );\n const nowMs = Date.now();\n const lines = [heading];\n\n for (const [index, row] of this.rows.entries()) {\n const branch = index === this.rows.length - 1 ? '└─' : '├─';\n lines.push(truncate(`${theme.fg('dim', branch)} ${formatWorkflowProgressRow(row, theme, nowMs)}`));\n }\n\n // Pi adds space above widgets but not below; keep the list off the editor border.\n lines.push('');\n return lines;\n }\n\n dispose(): void {\n this.stopProgressTimer();\n if (this.uiCtx) this.uiCtx.setWidget(WORKFLOW_PROGRESS_WIDGET_KEY, undefined);\n this.rows = [];\n this.widgetRegistered = false;\n this.tui = undefined;\n this.uiCtx = undefined;\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { truncateToWidth } from "@earendil-works/pi-tui";
|
|
2
|
+
//#region src/tui/workflow/workflowProgressOverlay.ts
|
|
3
|
+
const WORKFLOW_PROGRESS_WIDGET_KEY = "workflow-mcp-progress";
|
|
4
|
+
const OVERLAY_HEADING = "Workflows";
|
|
5
|
+
const PROGRESS_TICK_MS = 200;
|
|
6
|
+
const RUNNING_SPINNER_FRAMES = [
|
|
7
|
+
"⠋",
|
|
8
|
+
"⠙",
|
|
9
|
+
"⠹",
|
|
10
|
+
"⠸",
|
|
11
|
+
"⠼",
|
|
12
|
+
"⠴",
|
|
13
|
+
"⠦",
|
|
14
|
+
"⠧",
|
|
15
|
+
"⠇",
|
|
16
|
+
"⠏"
|
|
17
|
+
];
|
|
18
|
+
const STATIC_PROGRESS_MARKER = "*";
|
|
19
|
+
const MILLISECONDS_PER_SECOND = 1e3;
|
|
20
|
+
const SECONDS_PER_MINUTE = 60;
|
|
21
|
+
const MINUTES_PER_HOUR = 60;
|
|
22
|
+
const STARTING_JOB_STEP = "Starting job";
|
|
23
|
+
const STARTING_WORKFLOW_STEP = "Starting workflow";
|
|
24
|
+
const PREPARING_WORKFLOW_STEP = "Preparing workflow";
|
|
25
|
+
const FINALIZING_WORKFLOW_STEP = "Finalizing workflow";
|
|
26
|
+
/** One explicit palette makes every workflow state visually stable across the list. */
|
|
27
|
+
const WORKFLOW_PROGRESS_COLORS = {
|
|
28
|
+
starting: "dim",
|
|
29
|
+
running: "accent",
|
|
30
|
+
completed: "success",
|
|
31
|
+
paused: "warning",
|
|
32
|
+
failed: "error",
|
|
33
|
+
skipped: "muted"
|
|
34
|
+
};
|
|
35
|
+
function latestStep(events) {
|
|
36
|
+
return events.findLast((event) => event.type === "step" && !!event.step);
|
|
37
|
+
}
|
|
38
|
+
function latestEvent(events) {
|
|
39
|
+
return events.at(-1);
|
|
40
|
+
}
|
|
41
|
+
function progressState(record, event) {
|
|
42
|
+
if (record.stage === "error") return "failed";
|
|
43
|
+
if (record.stage === "completed") return "completed";
|
|
44
|
+
if (record.executionState === "paused" || record.executionState === "pause_requested") return "paused";
|
|
45
|
+
switch (event?.status) {
|
|
46
|
+
case "failed": return "failed";
|
|
47
|
+
case "paused":
|
|
48
|
+
case "pause_requested": return "paused";
|
|
49
|
+
case "completed": return "completed";
|
|
50
|
+
case "skipped": return "skipped";
|
|
51
|
+
case "resumed":
|
|
52
|
+
case "running": return "running";
|
|
53
|
+
default: return record.executionCursor?.stepName ? "running" : "starting";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function fallbackStep(record) {
|
|
57
|
+
switch (record.executionCursor?.phase) {
|
|
58
|
+
case "pre": return PREPARING_WORKFLOW_STEP;
|
|
59
|
+
case "post": return FINALIZING_WORKFLOW_STEP;
|
|
60
|
+
case "job":
|
|
61
|
+
case "step": return STARTING_JOB_STEP;
|
|
62
|
+
default: return STARTING_WORKFLOW_STEP;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** Derive the single current line for one run from its record and pushed progress events. */
|
|
66
|
+
function workflowProgressRow(record, events) {
|
|
67
|
+
const stepEvent = latestStep(events);
|
|
68
|
+
const event = latestEvent(events);
|
|
69
|
+
const cursor = record.executionCursor;
|
|
70
|
+
const job = cursor?.job ?? stepEvent?.job ?? event?.job ?? record.job ?? cursor?.phase ?? "workflow";
|
|
71
|
+
const step = cursor?.stepName ?? (stepEvent?.job === job ? stepEvent.step : void 0) ?? fallbackStep(record);
|
|
72
|
+
return {
|
|
73
|
+
job,
|
|
74
|
+
key: record.runId ?? `${record.workspace}/${record.runKey}`,
|
|
75
|
+
name: record.displayName,
|
|
76
|
+
startedAt: record.startedAt,
|
|
77
|
+
state: progressState(record, event),
|
|
78
|
+
step
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/** Task-style elapsed time: whole seconds stay stable and compact between animation ticks. */
|
|
82
|
+
function formatWorkflowDuration(durationMs) {
|
|
83
|
+
if (!Number.isFinite(durationMs) || durationMs < 0) return "?";
|
|
84
|
+
const totalSeconds = Math.floor(durationMs / MILLISECONDS_PER_SECOND);
|
|
85
|
+
const seconds = totalSeconds % SECONDS_PER_MINUTE;
|
|
86
|
+
const totalMinutes = Math.floor(totalSeconds / SECONDS_PER_MINUTE);
|
|
87
|
+
if (totalMinutes < MINUTES_PER_HOUR) return totalMinutes === 0 ? `${seconds}s` : `${totalMinutes}m${String(seconds).padStart(2, "0")}s`;
|
|
88
|
+
const minutes = totalMinutes % MINUTES_PER_HOUR;
|
|
89
|
+
return `${Math.floor(totalMinutes / MINUTES_PER_HOUR)}h${String(minutes).padStart(2, "0")}m${String(seconds).padStart(2, "0")}s`;
|
|
90
|
+
}
|
|
91
|
+
function progressMarker(state, nowMs) {
|
|
92
|
+
if (state !== "running" && state !== "starting") return STATIC_PROGRESS_MARKER;
|
|
93
|
+
const tick = Number.isFinite(nowMs) ? Math.floor(Math.max(0, nowMs) / PROGRESS_TICK_MS) : 0;
|
|
94
|
+
return RUNNING_SPINNER_FRAMES[tick % RUNNING_SPINNER_FRAMES.length] ?? RUNNING_SPINNER_FRAMES[0];
|
|
95
|
+
}
|
|
96
|
+
/** Render exactly: `<workflow name>[<duration>][<job>] <activity> <step>`. */
|
|
97
|
+
function formatWorkflowProgressRow(row, theme, nowMs = Date.now()) {
|
|
98
|
+
const startedAt = Date.parse(row.startedAt);
|
|
99
|
+
const duration = formatWorkflowDuration(Number.isFinite(startedAt) ? nowMs - startedAt : NaN);
|
|
100
|
+
const color = WORKFLOW_PROGRESS_COLORS[row.state];
|
|
101
|
+
return [
|
|
102
|
+
theme.fg(color, row.name),
|
|
103
|
+
theme.fg("muted", `[${duration}][${row.job}]`),
|
|
104
|
+
theme.fg(color, ` ${progressMarker(row.state, nowMs)} `),
|
|
105
|
+
theme.fg("text", row.step)
|
|
106
|
+
].join("");
|
|
107
|
+
}
|
|
108
|
+
/** Persistent workflow widget with the same heading/tree shape as Doom's task list. */
|
|
109
|
+
var WorkflowProgressOverlay = class {
|
|
110
|
+
rows = [];
|
|
111
|
+
uiCtx;
|
|
112
|
+
widgetRegistered = false;
|
|
113
|
+
tui;
|
|
114
|
+
progressTimer;
|
|
115
|
+
/** Identity-compare so repeated session starts do not register duplicate widgets. */
|
|
116
|
+
setUICtx(ctx) {
|
|
117
|
+
if (ctx === this.uiCtx) return;
|
|
118
|
+
if (this.uiCtx && this.widgetRegistered) this.uiCtx.setWidget(WORKFLOW_PROGRESS_WIDGET_KEY, void 0);
|
|
119
|
+
this.stopProgressTimer();
|
|
120
|
+
this.uiCtx = ctx;
|
|
121
|
+
this.widgetRegistered = false;
|
|
122
|
+
this.tui = void 0;
|
|
123
|
+
}
|
|
124
|
+
update(rows) {
|
|
125
|
+
this.rows = rows;
|
|
126
|
+
if (!this.uiCtx) {
|
|
127
|
+
this.stopProgressTimer();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (rows.length === 0) {
|
|
131
|
+
if (this.widgetRegistered) {
|
|
132
|
+
this.uiCtx.setWidget(WORKFLOW_PROGRESS_WIDGET_KEY, void 0);
|
|
133
|
+
this.widgetRegistered = false;
|
|
134
|
+
this.tui = void 0;
|
|
135
|
+
}
|
|
136
|
+
this.stopProgressTimer();
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (this.widgetRegistered) {
|
|
140
|
+
this.syncProgressTimer();
|
|
141
|
+
this.tui?.requestRender();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
this.uiCtx.setWidget(WORKFLOW_PROGRESS_WIDGET_KEY, (tui, factoryTheme) => {
|
|
145
|
+
this.tui = tui;
|
|
146
|
+
return {
|
|
147
|
+
render: (width) => this.renderWidget(this.uiCtx?.theme ?? factoryTheme, width),
|
|
148
|
+
invalidate: () => {}
|
|
149
|
+
};
|
|
150
|
+
}, { placement: "aboveEditor" });
|
|
151
|
+
this.widgetRegistered = true;
|
|
152
|
+
this.syncProgressTimer();
|
|
153
|
+
}
|
|
154
|
+
syncProgressTimer() {
|
|
155
|
+
if (!this.widgetRegistered || this.rows.length === 0) {
|
|
156
|
+
this.stopProgressTimer();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (this.progressTimer) return;
|
|
160
|
+
this.progressTimer = setInterval(() => this.tui?.requestRender(), PROGRESS_TICK_MS);
|
|
161
|
+
this.progressTimer.unref?.();
|
|
162
|
+
}
|
|
163
|
+
stopProgressTimer() {
|
|
164
|
+
if (this.progressTimer) clearInterval(this.progressTimer);
|
|
165
|
+
this.progressTimer = void 0;
|
|
166
|
+
}
|
|
167
|
+
renderWidget(theme, width) {
|
|
168
|
+
if (this.rows.length === 0) return [];
|
|
169
|
+
const truncate = (line) => truncateToWidth(line, width, "…");
|
|
170
|
+
const heading = truncate(`${theme.fg("accent", "●")} ${theme.fg("accent", `${OVERLAY_HEADING} (${this.rows.length})`)}`);
|
|
171
|
+
const nowMs = Date.now();
|
|
172
|
+
const lines = [heading];
|
|
173
|
+
for (const [index, row] of this.rows.entries()) {
|
|
174
|
+
const branch = index === this.rows.length - 1 ? "└─" : "├─";
|
|
175
|
+
lines.push(truncate(`${theme.fg("dim", branch)} ${formatWorkflowProgressRow(row, theme, nowMs)}`));
|
|
176
|
+
}
|
|
177
|
+
lines.push("");
|
|
178
|
+
return lines;
|
|
179
|
+
}
|
|
180
|
+
dispose() {
|
|
181
|
+
this.stopProgressTimer();
|
|
182
|
+
if (this.uiCtx) this.uiCtx.setWidget(WORKFLOW_PROGRESS_WIDGET_KEY, void 0);
|
|
183
|
+
this.rows = [];
|
|
184
|
+
this.widgetRegistered = false;
|
|
185
|
+
this.tui = void 0;
|
|
186
|
+
this.uiCtx = void 0;
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
//#endregion
|
|
190
|
+
export { WORKFLOW_PROGRESS_COLORS, WORKFLOW_PROGRESS_WIDGET_KEY, WorkflowProgressOverlay, formatWorkflowDuration, formatWorkflowProgressRow, workflowProgressRow };
|
|
191
|
+
|
|
192
|
+
//# sourceMappingURL=workflowProgressOverlay.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflowProgressOverlay.mjs","names":[],"sources":["../../../../src/tui/workflow/workflowProgressOverlay.ts"],"sourcesContent":["/**\n * Task-like live workflow list shown above Pi's editor.\n *\n * DESIGN PATTERNS:\n * - The extension owns run/event state; this component only projects and renders it.\n * - Register the widget once, then request redraws as progress, elapsed time, or the spinner changes.\n * - Terminal runs are absent from `rows`, so the widget disappears when the last run ends.\n *\n * CODING STANDARDS:\n * - Every rendered line is ANSI-aware and truncated to the available terminal width.\n * - Theme colors come from Pi's live UI context so theme changes repaint correctly.\n * - Named exports only and explicit return types on exported members.\n *\n * AVOID:\n * - Persisting progress in the chat transcript.\n * - Starting timers while no workflow is visible.\n */\n\nimport type { WorkflowProgressEvent, WorkflowRunRecord } from '@agimon-ai/workflow-mcp';\nimport type { ExtensionUIContext, Theme } from '@earendil-works/pi-coding-agent';\nimport { type TUI, truncateToWidth } from '@earendil-works/pi-tui';\n\nexport const WORKFLOW_PROGRESS_WIDGET_KEY = 'workflow-mcp-progress';\n\nconst OVERLAY_HEADING = 'Workflows';\nconst PROGRESS_TICK_MS = 200;\nconst RUNNING_SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'] as const;\nconst STATIC_PROGRESS_MARKER = '*';\nconst MILLISECONDS_PER_SECOND = 1000;\nconst SECONDS_PER_MINUTE = 60;\nconst MINUTES_PER_HOUR = 60;\nconst STARTING_JOB_STEP = 'Starting job';\nconst STARTING_WORKFLOW_STEP = 'Starting workflow';\nconst PREPARING_WORKFLOW_STEP = 'Preparing workflow';\nconst FINALIZING_WORKFLOW_STEP = 'Finalizing workflow';\n\ntype WorkflowProgressColor = Parameters<Theme['fg']>[0];\n\nexport type WorkflowProgressState = 'completed' | 'failed' | 'paused' | 'running' | 'skipped' | 'starting';\n\n/** One explicit palette makes every workflow state visually stable across the list. */\nexport const WORKFLOW_PROGRESS_COLORS: Readonly<Record<WorkflowProgressState, WorkflowProgressColor>> = {\n starting: 'dim',\n running: 'accent',\n completed: 'success',\n paused: 'warning',\n failed: 'error',\n skipped: 'muted',\n};\n\nexport interface WorkflowProgressRow {\n job: string;\n key: string;\n name: string;\n startedAt: string;\n state: WorkflowProgressState;\n step: string;\n}\n\nfunction latestStep(events: readonly WorkflowProgressEvent[]): WorkflowProgressEvent | undefined {\n return events.findLast((event) => event.type === 'step' && !!event.step);\n}\n\nfunction latestEvent(events: readonly WorkflowProgressEvent[]): WorkflowProgressEvent | undefined {\n return events.at(-1);\n}\n\nfunction progressState(record: WorkflowRunRecord, event: WorkflowProgressEvent | undefined): WorkflowProgressState {\n if (record.stage === 'error') return 'failed';\n if (record.stage === 'completed') return 'completed';\n if (record.executionState === 'paused' || record.executionState === 'pause_requested') return 'paused';\n\n switch (event?.status) {\n case 'failed':\n return 'failed';\n case 'paused':\n case 'pause_requested':\n return 'paused';\n case 'completed':\n return 'completed';\n case 'skipped':\n return 'skipped';\n case 'resumed':\n case 'running':\n return 'running';\n default:\n return record.executionCursor?.stepName ? 'running' : 'starting';\n }\n}\n\nfunction fallbackStep(record: WorkflowRunRecord): string {\n switch (record.executionCursor?.phase) {\n case 'pre':\n return PREPARING_WORKFLOW_STEP;\n case 'post':\n return FINALIZING_WORKFLOW_STEP;\n case 'job':\n case 'step':\n return STARTING_JOB_STEP;\n default:\n return STARTING_WORKFLOW_STEP;\n }\n}\n\n/** Derive the single current line for one run from its record and pushed progress events. */\nexport function workflowProgressRow(\n record: WorkflowRunRecord,\n events: readonly WorkflowProgressEvent[],\n): WorkflowProgressRow {\n const stepEvent = latestStep(events);\n const event = latestEvent(events);\n const cursor = record.executionCursor;\n const job = cursor?.job ?? stepEvent?.job ?? event?.job ?? record.job ?? cursor?.phase ?? 'workflow';\n const step = cursor?.stepName ?? (stepEvent?.job === job ? stepEvent.step : undefined) ?? fallbackStep(record);\n\n return {\n job,\n key: record.runId ?? `${record.workspace}/${record.runKey}`,\n name: record.displayName,\n startedAt: record.startedAt,\n state: progressState(record, event),\n step,\n };\n}\n\n/** Task-style elapsed time: whole seconds stay stable and compact between animation ticks. */\nexport function formatWorkflowDuration(durationMs: number): string {\n if (!Number.isFinite(durationMs) || durationMs < 0) return '?';\n const totalSeconds = Math.floor(durationMs / MILLISECONDS_PER_SECOND);\n const seconds = totalSeconds % SECONDS_PER_MINUTE;\n const totalMinutes = Math.floor(totalSeconds / SECONDS_PER_MINUTE);\n if (totalMinutes < MINUTES_PER_HOUR) {\n return totalMinutes === 0 ? `${seconds}s` : `${totalMinutes}m${String(seconds).padStart(2, '0')}s`;\n }\n const minutes = totalMinutes % MINUTES_PER_HOUR;\n const hours = Math.floor(totalMinutes / MINUTES_PER_HOUR);\n return `${hours}h${String(minutes).padStart(2, '0')}m${String(seconds).padStart(2, '0')}s`;\n}\n\nfunction progressMarker(state: WorkflowProgressState, nowMs: number): string {\n if (state !== 'running' && state !== 'starting') return STATIC_PROGRESS_MARKER;\n const tick = Number.isFinite(nowMs) ? Math.floor(Math.max(0, nowMs) / PROGRESS_TICK_MS) : 0;\n return RUNNING_SPINNER_FRAMES[tick % RUNNING_SPINNER_FRAMES.length] ?? RUNNING_SPINNER_FRAMES[0];\n}\n\n/** Render exactly: `<workflow name>[<duration>][<job>] <activity> <step>`. */\nexport function formatWorkflowProgressRow(row: WorkflowProgressRow, theme: Theme, nowMs = Date.now()): string {\n const startedAt = Date.parse(row.startedAt);\n const duration = formatWorkflowDuration(Number.isFinite(startedAt) ? nowMs - startedAt : Number.NaN);\n const color = WORKFLOW_PROGRESS_COLORS[row.state];\n return [\n theme.fg(color, row.name),\n theme.fg('muted', `[${duration}][${row.job}]`),\n theme.fg(color, ` ${progressMarker(row.state, nowMs)} `),\n theme.fg('text', row.step),\n ].join('');\n}\n\n/** Persistent workflow widget with the same heading/tree shape as Doom's task list. */\nexport class WorkflowProgressOverlay {\n private rows: readonly WorkflowProgressRow[] = [];\n private uiCtx: ExtensionUIContext | undefined;\n private widgetRegistered = false;\n private tui: TUI | undefined;\n private progressTimer: NodeJS.Timeout | undefined;\n\n /** Identity-compare so repeated session starts do not register duplicate widgets. */\n setUICtx(ctx: ExtensionUIContext): void {\n if (ctx === this.uiCtx) return;\n if (this.uiCtx && this.widgetRegistered) this.uiCtx.setWidget(WORKFLOW_PROGRESS_WIDGET_KEY, undefined);\n this.stopProgressTimer();\n this.uiCtx = ctx;\n this.widgetRegistered = false;\n this.tui = undefined;\n }\n\n update(rows: readonly WorkflowProgressRow[]): void {\n this.rows = rows;\n if (!this.uiCtx) {\n this.stopProgressTimer();\n return;\n }\n\n if (rows.length === 0) {\n if (this.widgetRegistered) {\n this.uiCtx.setWidget(WORKFLOW_PROGRESS_WIDGET_KEY, undefined);\n this.widgetRegistered = false;\n this.tui = undefined;\n }\n this.stopProgressTimer();\n return;\n }\n\n if (this.widgetRegistered) {\n this.syncProgressTimer();\n this.tui?.requestRender();\n return;\n }\n\n this.uiCtx.setWidget(\n WORKFLOW_PROGRESS_WIDGET_KEY,\n (tui, factoryTheme) => {\n this.tui = tui;\n return {\n render: (width: number) => this.renderWidget(this.uiCtx?.theme ?? factoryTheme, width),\n invalidate: () => {\n // Nothing cached: the next render reads the current rows, clock, and theme.\n },\n };\n },\n { placement: 'aboveEditor' },\n );\n this.widgetRegistered = true;\n this.syncProgressTimer();\n }\n\n private syncProgressTimer(): void {\n if (!this.widgetRegistered || this.rows.length === 0) {\n this.stopProgressTimer();\n return;\n }\n if (this.progressTimer) return;\n this.progressTimer = setInterval(() => this.tui?.requestRender(), PROGRESS_TICK_MS);\n this.progressTimer.unref?.();\n }\n\n private stopProgressTimer(): void {\n if (this.progressTimer) clearInterval(this.progressTimer);\n this.progressTimer = undefined;\n }\n\n private renderWidget(theme: Theme, width: number): string[] {\n if (this.rows.length === 0) return [];\n const truncate = (line: string): string => truncateToWidth(line, width, '…');\n const heading = truncate(\n `${theme.fg('accent', '●')} ${theme.fg('accent', `${OVERLAY_HEADING} (${this.rows.length})`)}`,\n );\n const nowMs = Date.now();\n const lines = [heading];\n\n for (const [index, row] of this.rows.entries()) {\n const branch = index === this.rows.length - 1 ? '└─' : '├─';\n lines.push(truncate(`${theme.fg('dim', branch)} ${formatWorkflowProgressRow(row, theme, nowMs)}`));\n }\n\n // Pi adds space above widgets but not below; keep the list off the editor border.\n lines.push('');\n return lines;\n }\n\n dispose(): void {\n this.stopProgressTimer();\n if (this.uiCtx) this.uiCtx.setWidget(WORKFLOW_PROGRESS_WIDGET_KEY, undefined);\n this.rows = [];\n this.widgetRegistered = false;\n this.tui = undefined;\n this.uiCtx = undefined;\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
const require_doomOverlay = require("./doomOverlay.cjs");
|
|
2
|
+
const require_overlayText = require("./overlayText.cjs");
|
|
3
|
+
let _earendil_works_pi_tui = require("@earendil-works/pi-tui");
|
|
4
|
+
require_doomOverlay.DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions;
|
|
5
|
+
const CHOICE_TITLE = "WORKFLOW PROMPT";
|
|
6
|
+
const CHOOSE_LABEL = "CHOOSE";
|
|
7
|
+
const VALUE_LABEL = "VALUE";
|
|
8
|
+
const DEFAULT_MARKER = "default";
|
|
9
|
+
const EMPTY_CHOICES = "No options are available.";
|
|
10
|
+
const CHOICE_HINTS = [
|
|
11
|
+
["↑↓", "select"],
|
|
12
|
+
["enter", "confirm"],
|
|
13
|
+
["esc", "cancel"]
|
|
14
|
+
];
|
|
15
|
+
const INPUT_HINTS = [
|
|
16
|
+
["type", "edit"],
|
|
17
|
+
["enter", "confirm"],
|
|
18
|
+
["ctrl+u", "clear"],
|
|
19
|
+
["esc", "cancel"]
|
|
20
|
+
];
|
|
21
|
+
const KEY_CLEAR = "";
|
|
22
|
+
/** Rows the heading and its spacer take before the first option. */
|
|
23
|
+
const HEADING_ROWS = 2;
|
|
24
|
+
const DIM = "dim";
|
|
25
|
+
const ACCENT = "accent";
|
|
26
|
+
const SELECTED_BG = "selectedBg";
|
|
27
|
+
const ROW_BG = "userMessageBg";
|
|
28
|
+
var WorkflowChoiceComponent = class extends require_doomOverlay.DoomOverlay {
|
|
29
|
+
options;
|
|
30
|
+
done;
|
|
31
|
+
selected;
|
|
32
|
+
constructor(tui, theme, options, done) {
|
|
33
|
+
super(tui, theme);
|
|
34
|
+
this.options = options;
|
|
35
|
+
this.done = done;
|
|
36
|
+
this.selected = Math.max(0, options.preselect ? options.choices.indexOf(options.preselect) : 0);
|
|
37
|
+
}
|
|
38
|
+
handleInput(data) {
|
|
39
|
+
if ((0, _earendil_works_pi_tui.matchesKey)(data, "escape") || (0, _earendil_works_pi_tui.matchesKey)(data, "ctrl+c")) {
|
|
40
|
+
this.done(void 0);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if ((0, _earendil_works_pi_tui.matchesKey)(data, "enter")) {
|
|
44
|
+
const choice = this.options.choices[this.selected];
|
|
45
|
+
if (choice !== void 0) this.done(choice);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const count = this.options.choices.length;
|
|
49
|
+
if (count === 0) return;
|
|
50
|
+
if ((0, _earendil_works_pi_tui.matchesKey)(data, "up") || (0, _earendil_works_pi_tui.matchesKey)(data, "ctrl+p")) this.selected = Math.max(0, this.selected - 1);
|
|
51
|
+
else if ((0, _earendil_works_pi_tui.matchesKey)(data, "down") || (0, _earendil_works_pi_tui.matchesKey)(data, "ctrl+n")) this.selected = Math.min(count - 1, this.selected + 1);
|
|
52
|
+
else return;
|
|
53
|
+
this.tui.requestRender();
|
|
54
|
+
}
|
|
55
|
+
getChrome() {
|
|
56
|
+
return {
|
|
57
|
+
title: CHOICE_TITLE,
|
|
58
|
+
accent: require_doomOverlay.DOOM_OVERLAY_ACCENT,
|
|
59
|
+
breadcrumb: this.options.breadcrumb,
|
|
60
|
+
headerRight: `${this.options.choices.length} options`,
|
|
61
|
+
footer: "↑↓ select · enter confirm · esc cancel",
|
|
62
|
+
footerHints: CHOICE_HINTS,
|
|
63
|
+
footerRight: this.options.choices.length > 0 ? `${this.selected + 1}/${this.options.choices.length}` : "no options"
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
renderBody(width, height) {
|
|
67
|
+
const lines = [this.theme.bold(require_overlayText.fit(this.options.title, width)), ""];
|
|
68
|
+
if (this.options.choices.length === 0) {
|
|
69
|
+
lines.push(this.theme.fg(DIM, EMPTY_CHOICES));
|
|
70
|
+
return lines.slice(0, height);
|
|
71
|
+
}
|
|
72
|
+
lines.push(this.theme.fg(DIM, CHOOSE_LABEL));
|
|
73
|
+
const capacity = Math.max(1, height - HEADING_ROWS - 1);
|
|
74
|
+
const start = Math.max(0, Math.min(this.selected - capacity + 1, Math.max(0, this.options.choices.length - capacity)));
|
|
75
|
+
for (const [offset, choice] of this.options.choices.slice(start, start + capacity).entries()) {
|
|
76
|
+
const current = start + offset === this.selected;
|
|
77
|
+
const marker = current ? this.theme.fg(ACCENT, "›") : " ";
|
|
78
|
+
const label = current ? this.theme.bold(choice) : choice;
|
|
79
|
+
const note = choice === this.options.preselect ? this.theme.fg(DIM, DEFAULT_MARKER) : "";
|
|
80
|
+
const background = current ? SELECTED_BG : ROW_BG;
|
|
81
|
+
lines.push(this.theme.bg(background, require_overlayText.rightAligned(`${marker} ${label}`, note, width)));
|
|
82
|
+
}
|
|
83
|
+
return lines.slice(0, height);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
var WorkflowInputComponent = class extends require_doomOverlay.DoomOverlay {
|
|
87
|
+
options;
|
|
88
|
+
done;
|
|
89
|
+
draft = "";
|
|
90
|
+
constructor(tui, theme, options, done) {
|
|
91
|
+
super(tui, theme);
|
|
92
|
+
this.options = options;
|
|
93
|
+
this.done = done;
|
|
94
|
+
}
|
|
95
|
+
handleInput(data) {
|
|
96
|
+
if ((0, _earendil_works_pi_tui.matchesKey)(data, "escape") || (0, _earendil_works_pi_tui.matchesKey)(data, "ctrl+c")) {
|
|
97
|
+
this.done(void 0);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if ((0, _earendil_works_pi_tui.matchesKey)(data, "enter")) {
|
|
101
|
+
this.done(this.draft.trim() || this.options.fallback || "");
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if ((0, _earendil_works_pi_tui.matchesKey)(data, "backspace")) this.draft = this.draft.slice(0, -1);
|
|
105
|
+
else if (data === KEY_CLEAR) this.draft = "";
|
|
106
|
+
else if (!require_overlayText.isControlInput(data)) this.draft += data;
|
|
107
|
+
else return;
|
|
108
|
+
this.tui.requestRender();
|
|
109
|
+
}
|
|
110
|
+
getChrome() {
|
|
111
|
+
return {
|
|
112
|
+
title: CHOICE_TITLE,
|
|
113
|
+
accent: require_doomOverlay.DOOM_OVERLAY_ACCENT,
|
|
114
|
+
breadcrumb: this.options.breadcrumb,
|
|
115
|
+
headerRight: this.options.fallback ? `default ${this.options.fallback}` : "no default",
|
|
116
|
+
footer: "type to edit · enter confirm · ctrl+u clear · esc cancel",
|
|
117
|
+
footerHints: INPUT_HINTS
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
renderBody(width, height) {
|
|
121
|
+
const label = this.options.fallback ? require_overlayText.rightAligned(this.theme.fg(DIM, VALUE_LABEL), this.theme.fg(DIM, `${DEFAULT_MARKER} ${this.options.fallback}`), width) : this.theme.fg(DIM, VALUE_LABEL);
|
|
122
|
+
return [
|
|
123
|
+
this.theme.bold(require_overlayText.fit(this.options.title, width)),
|
|
124
|
+
"",
|
|
125
|
+
label,
|
|
126
|
+
this.theme.bg(SELECTED_BG, require_overlayText.fit(` ${this.draft}█`, width))
|
|
127
|
+
].slice(0, height);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
async function openWorkflowChoice(ctx, options) {
|
|
131
|
+
return ctx.ui.custom((tui, theme, _keybindings, done) => new WorkflowChoiceComponent(tui, theme, options, done), require_doomOverlay.DOOM_FULLSCREEN_UI_OPTIONS);
|
|
132
|
+
}
|
|
133
|
+
async function openWorkflowInput(ctx, options) {
|
|
134
|
+
return ctx.ui.custom((tui, theme, _keybindings, done) => new WorkflowInputComponent(tui, theme, options, done), require_doomOverlay.DOOM_FULLSCREEN_UI_OPTIONS);
|
|
135
|
+
}
|
|
136
|
+
//#endregion
|
|
137
|
+
exports.WorkflowChoiceComponent = WorkflowChoiceComponent;
|
|
138
|
+
exports.WorkflowInputComponent = WorkflowInputComponent;
|
|
139
|
+
exports.openWorkflowChoice = openWorkflowChoice;
|
|
140
|
+
exports.openWorkflowInput = openWorkflowInput;
|
|
141
|
+
|
|
142
|
+
//# sourceMappingURL=workflowPrompt.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflowPrompt.cjs","names":["DOOM_FULLSCREEN_UI_OPTIONS","DoomOverlay","matchesKey","DOOM_OVERLAY_ACCENT","fit","rightAligned","isControlInput"],"sources":["../../../../src/tui/workflow/workflowPrompt.ts"],"sourcesContent":["/**\n * The short prompts: pick one of a few options, or type one value.\n *\n * These were `ui.select` and `ui.input`, which meant the run manager, the runner\n * picker and every `workflow_dispatch` input rendered as native Pi widgets in the\n * middle of a flow whose other steps are framed doom overlays. Same surface for\n * all of them now, so a launch reads as one sequence rather than three styles.\n *\n * Rendering is pure, so both modes can be asserted as text without a terminal.\n */\n\nimport type { ExtensionContext, Theme } from '@earendil-works/pi-coding-agent';\nimport { matchesKey } from '@earendil-works/pi-tui';\n\nimport {\n DOOM_FULLSCREEN_UI_OPTIONS,\n DOOM_OVERLAY_ACCENT,\n DoomOverlay,\n type DoomOverlayChrome,\n type DoomOverlayTui,\n} from './doomOverlay';\nimport { CURSOR_BLOCK, fit, isControlInput, rightAligned, SELECTION_MARKER } from './overlayText';\n\nexport const WORKFLOW_PROMPT_OVERLAY_OPTIONS = DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions;\n\nconst CHOICE_TITLE = 'WORKFLOW PROMPT';\nconst CHOOSE_LABEL = 'CHOOSE';\nconst VALUE_LABEL = 'VALUE';\nconst DEFAULT_MARKER = 'default';\nconst EMPTY_CHOICES = 'No options are available.';\nconst CHOICE_HINTS: readonly (readonly [string, string])[] = [\n ['↑↓', 'select'],\n ['enter', 'confirm'],\n ['esc', 'cancel'],\n];\nconst INPUT_HINTS: readonly (readonly [string, string])[] = [\n ['type', 'edit'],\n ['enter', 'confirm'],\n ['ctrl+u', 'clear'],\n ['esc', 'cancel'],\n];\nconst KEY_CLEAR = '\\x15';\n/** Rows the heading and its spacer take before the first option. */\nconst HEADING_ROWS = 2;\n\n/** Neither palette name is exported, so take both from the theme's methods. */\ntype ThemeBg = Parameters<Theme['bg']>[0];\ntype ThemeColor = Parameters<Theme['fg']>[0];\n\nconst DIM: ThemeColor = 'dim';\nconst ACCENT: ThemeColor = 'accent';\nconst SELECTED_BG: ThemeBg = 'selectedBg';\nconst ROW_BG: ThemeBg = 'userMessageBg';\n\nexport interface WorkflowChoiceOptions {\n title: string;\n breadcrumb: string;\n choices: readonly string[];\n /** Marked `default` in the list and pre-selected. */\n preselect?: string;\n}\n\nexport interface WorkflowInputOptions {\n title: string;\n breadcrumb: string;\n /** Committed when the field is left empty, and shown beside the label. */\n fallback?: string;\n}\n\nexport class WorkflowChoiceComponent extends DoomOverlay {\n private selected: number;\n\n constructor(\n tui: DoomOverlayTui,\n theme: Theme,\n private readonly options: WorkflowChoiceOptions,\n private readonly done: (choice: string | undefined) => void,\n ) {\n super(tui, theme);\n this.selected = Math.max(0, options.preselect ? options.choices.indexOf(options.preselect) : 0);\n }\n\n handleInput(data: string): void {\n if (matchesKey(data, 'escape') || matchesKey(data, 'ctrl+c')) {\n this.done(undefined);\n return;\n }\n if (matchesKey(data, 'enter')) {\n const choice = this.options.choices[this.selected];\n if (choice !== undefined) this.done(choice);\n return;\n }\n const count = this.options.choices.length;\n if (count === 0) return;\n if (matchesKey(data, 'up') || matchesKey(data, 'ctrl+p')) this.selected = Math.max(0, this.selected - 1);\n else if (matchesKey(data, 'down') || matchesKey(data, 'ctrl+n'))\n this.selected = Math.min(count - 1, this.selected + 1);\n else return;\n this.tui.requestRender();\n }\n\n protected getChrome(): DoomOverlayChrome {\n return {\n title: CHOICE_TITLE,\n accent: DOOM_OVERLAY_ACCENT,\n breadcrumb: this.options.breadcrumb,\n headerRight: `${this.options.choices.length} options`,\n footer: '↑↓ select · enter confirm · esc cancel',\n footerHints: CHOICE_HINTS,\n footerRight:\n this.options.choices.length > 0 ? `${this.selected + 1}/${this.options.choices.length}` : 'no options',\n };\n }\n\n protected renderBody(width: number, height: number): string[] {\n const lines = [this.theme.bold(fit(this.options.title, width)), ''];\n if (this.options.choices.length === 0) {\n lines.push(this.theme.fg(DIM, EMPTY_CHOICES));\n return lines.slice(0, height);\n }\n\n lines.push(this.theme.fg(DIM, CHOOSE_LABEL));\n // The window follows the cursor, so a list longer than the body still scrolls.\n const capacity = Math.max(1, height - HEADING_ROWS - 1);\n const start = Math.max(\n 0,\n Math.min(this.selected - capacity + 1, Math.max(0, this.options.choices.length - capacity)),\n );\n for (const [offset, choice] of this.options.choices.slice(start, start + capacity).entries()) {\n const current = start + offset === this.selected;\n const marker = current ? this.theme.fg(ACCENT, SELECTION_MARKER) : ' ';\n const label = current ? this.theme.bold(choice) : choice;\n const note = choice === this.options.preselect ? this.theme.fg(DIM, DEFAULT_MARKER) : '';\n const background: ThemeBg = current ? SELECTED_BG : ROW_BG;\n lines.push(this.theme.bg(background, rightAligned(`${marker} ${label}`, note, width)));\n }\n return lines.slice(0, height);\n }\n}\n\nexport class WorkflowInputComponent extends DoomOverlay {\n private draft = '';\n\n constructor(\n tui: DoomOverlayTui,\n theme: Theme,\n private readonly options: WorkflowInputOptions,\n private readonly done: (value: string | undefined) => void,\n ) {\n super(tui, theme);\n }\n\n handleInput(data: string): void {\n if (matchesKey(data, 'escape') || matchesKey(data, 'ctrl+c')) {\n this.done(undefined);\n return;\n }\n if (matchesKey(data, 'enter')) {\n // An empty field commits the fallback rather than an empty string: the\n // caller offered a default, and pressing enter is how you accept it.\n this.done(this.draft.trim() || this.options.fallback || '');\n return;\n }\n if (matchesKey(data, 'backspace')) this.draft = this.draft.slice(0, -1);\n else if (data === KEY_CLEAR) this.draft = '';\n else if (!isControlInput(data)) this.draft += data;\n else return;\n this.tui.requestRender();\n }\n\n protected getChrome(): DoomOverlayChrome {\n return {\n title: CHOICE_TITLE,\n accent: DOOM_OVERLAY_ACCENT,\n breadcrumb: this.options.breadcrumb,\n headerRight: this.options.fallback ? `default ${this.options.fallback}` : 'no default',\n footer: 'type to edit · enter confirm · ctrl+u clear · esc cancel',\n footerHints: INPUT_HINTS,\n };\n }\n\n protected renderBody(width: number, height: number): string[] {\n const label = this.options.fallback\n ? rightAligned(\n this.theme.fg(DIM, VALUE_LABEL),\n this.theme.fg(DIM, `${DEFAULT_MARKER} ${this.options.fallback}`),\n width,\n )\n : this.theme.fg(DIM, VALUE_LABEL);\n return [\n this.theme.bold(fit(this.options.title, width)),\n '',\n label,\n this.theme.bg(SELECTED_BG, fit(` ${this.draft}${CURSOR_BLOCK}`, width)),\n ].slice(0, height);\n }\n}\n\nexport async function openWorkflowChoice(\n ctx: ExtensionContext,\n options: WorkflowChoiceOptions,\n): Promise<string | undefined> {\n return ctx.ui.custom<string | undefined>(\n (tui, theme, _keybindings, done) => new WorkflowChoiceComponent(tui, theme, options, done),\n DOOM_FULLSCREEN_UI_OPTIONS,\n );\n}\n\nexport async function openWorkflowInput(\n ctx: ExtensionContext,\n options: WorkflowInputOptions,\n): Promise<string | undefined> {\n return ctx.ui.custom<string | undefined>(\n (tui, theme, _keybindings, done) => new WorkflowInputComponent(tui, theme, options, done),\n DOOM_FULLSCREEN_UI_OPTIONS,\n );\n}\n"],"mappings":"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"}
|