@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,74 @@
|
|
|
1
|
+
import { PROGRESS_FILE_NAME, RUN_RECORD_FILE_NAME, WORKFLOW_STAGES, WORKSPACES_DIR_NAME, completeWorkflowRunView, foldWorkflowProgress, parseWorkflowProgress, parseWorkflowRunRecord, resolveWorkflowHome } from "../workflowRuns/index.mjs";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
//#region src/services/workflowWatcher/index.ts
|
|
6
|
+
/**
|
|
7
|
+
* Read the durable workflow registry once.
|
|
8
|
+
*
|
|
9
|
+
* The registry is an initial snapshot only. Live delivery belongs to the
|
|
10
|
+
* session lifecycle and is routed through the host-owned direct event bus.
|
|
11
|
+
*/
|
|
12
|
+
function readWorkflowRuns(options = {}) {
|
|
13
|
+
const environment = options.environment;
|
|
14
|
+
const homeDir = options.homeDir ?? resolveWorkflowHome({
|
|
15
|
+
envValue: environment?.["WORKFLOW_MCP_HOME"],
|
|
16
|
+
homeDir: os.homedir()
|
|
17
|
+
});
|
|
18
|
+
const workspacesDir = path.join(homeDir, WORKSPACES_DIR_NAME);
|
|
19
|
+
const recordCache = /* @__PURE__ */ new Map();
|
|
20
|
+
const progressCache = /* @__PURE__ */ new Map();
|
|
21
|
+
const cachedParse = (cache, filePath, parse, empty) => {
|
|
22
|
+
let stat;
|
|
23
|
+
try {
|
|
24
|
+
stat = fs.statSync(filePath);
|
|
25
|
+
} catch {
|
|
26
|
+
cache.delete(filePath);
|
|
27
|
+
return empty;
|
|
28
|
+
}
|
|
29
|
+
const cached = cache.get(filePath);
|
|
30
|
+
if (cached && cached.size === stat.size && cached.mtimeMs === stat.mtimeMs) return cached.value;
|
|
31
|
+
let raw;
|
|
32
|
+
try {
|
|
33
|
+
raw = fs.readFileSync(filePath, "utf8");
|
|
34
|
+
} catch {
|
|
35
|
+
cache.delete(filePath);
|
|
36
|
+
return empty;
|
|
37
|
+
}
|
|
38
|
+
const value = parse(raw);
|
|
39
|
+
cache.set(filePath, {
|
|
40
|
+
size: stat.size,
|
|
41
|
+
mtimeMs: stat.mtimeMs,
|
|
42
|
+
value
|
|
43
|
+
});
|
|
44
|
+
return value;
|
|
45
|
+
};
|
|
46
|
+
const listDir = (directory) => {
|
|
47
|
+
try {
|
|
48
|
+
return fs.readdirSync(directory).sort();
|
|
49
|
+
} catch {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const runs = [];
|
|
54
|
+
for (const workspace of listDir(workspacesDir)) for (const stage of WORKFLOW_STAGES) {
|
|
55
|
+
const stageDir = path.join(workspacesDir, workspace, stage);
|
|
56
|
+
for (const runKey of listDir(stageDir)) {
|
|
57
|
+
const runDir = path.join(stageDir, runKey);
|
|
58
|
+
const recordPath = path.join(runDir, RUN_RECORD_FILE_NAME);
|
|
59
|
+
const progressPath = path.join(runDir, PROGRESS_FILE_NAME);
|
|
60
|
+
const parsed = cachedParse(recordCache, recordPath, parseWorkflowRunRecord, void 0);
|
|
61
|
+
if (parsed === void 0) continue;
|
|
62
|
+
const jobs = cachedParse(progressCache, progressPath, (raw) => foldWorkflowProgress(parseWorkflowProgress(raw)), []);
|
|
63
|
+
runs.push({
|
|
64
|
+
...parsed,
|
|
65
|
+
view: completeWorkflowRunView(parsed.view, jobs)
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return runs;
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
export { readWorkflowRuns };
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/services/workflowWatcher/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport {\n completeWorkflowRunView,\n foldWorkflowProgress,\n type ParsedWorkflowRun,\n parseWorkflowProgress,\n parseWorkflowRunRecord,\n PROGRESS_FILE_NAME,\n resolveWorkflowHome,\n RUN_RECORD_FILE_NAME,\n WORKFLOW_HOME_ENV,\n WORKFLOW_STAGES,\n WORKSPACES_DIR_NAME,\n} from '../workflowRuns';\n\nexport interface ReadWorkflowRunsOptions {\n /** Registry home override, primarily for tests. */\n homeDir?: string;\n /** Admitted session environment used to resolve the registry home. */\n environment?: Readonly<Record<string, string | undefined>>;\n}\n\n/**\n * Read the durable workflow registry once.\n *\n * The registry is an initial snapshot only. Live delivery belongs to the\n * session lifecycle and is routed through the host-owned direct event bus.\n */\nexport function readWorkflowRuns(options: ReadWorkflowRunsOptions = {}): ParsedWorkflowRun[] {\n const environment = options.environment;\n const homeDir =\n options.homeDir ??\n resolveWorkflowHome({\n envValue: environment?.[WORKFLOW_HOME_ENV],\n homeDir: os.homedir(),\n });\n const workspacesDir = path.join(homeDir, WORKSPACES_DIR_NAME);\n const recordCache = new Map<string, { size: number; mtimeMs: number; value: ParsedWorkflowRun | undefined }>();\n const progressCache = new Map<\n string,\n { size: number; mtimeMs: number; value: ReturnType<typeof foldWorkflowProgress> }\n >();\n\n const cachedParse = <T>(\n cache: Map<string, { size: number; mtimeMs: number; value: T }>,\n filePath: string,\n parse: (raw: string) => T,\n empty: T,\n ): T => {\n let stat: fs.Stats;\n try {\n stat = fs.statSync(filePath);\n } catch {\n cache.delete(filePath);\n return empty;\n }\n const cached = cache.get(filePath);\n if (cached && cached.size === stat.size && cached.mtimeMs === stat.mtimeMs) return cached.value;\n let raw: string;\n try {\n raw = fs.readFileSync(filePath, 'utf8');\n } catch {\n cache.delete(filePath);\n return empty;\n }\n const value = parse(raw);\n cache.set(filePath, { size: stat.size, mtimeMs: stat.mtimeMs, value });\n return value;\n };\n\n const listDir = (directory: string): string[] => {\n try {\n return fs.readdirSync(directory).sort();\n } catch {\n return [];\n }\n };\n\n const runs: ParsedWorkflowRun[] = [];\n for (const workspace of listDir(workspacesDir)) {\n for (const stage of WORKFLOW_STAGES) {\n const stageDir = path.join(workspacesDir, workspace, stage);\n for (const runKey of listDir(stageDir)) {\n const runDir = path.join(stageDir, runKey);\n const recordPath = path.join(runDir, RUN_RECORD_FILE_NAME);\n const progressPath = path.join(runDir, PROGRESS_FILE_NAME);\n const parsed = cachedParse(recordCache, recordPath, parseWorkflowRunRecord, undefined);\n if (parsed === undefined) continue;\n const jobs = cachedParse(\n progressCache,\n progressPath,\n (raw) => foldWorkflowProgress(parseWorkflowProgress(raw)),\n [],\n );\n runs.push({ ...parsed, view: completeWorkflowRunView(parsed.view, jobs) });\n }\n }\n }\n return runs;\n}\n"],"mappings":";;;;;;;;;;;AA+BA,SAAgB,iBAAiB,UAAmC,CAAC,GAAwB;CAC3F,MAAM,cAAc,QAAQ;CAC5B,MAAM,UACJ,QAAQ,WACR,oBAAoB;EAClB,UAAU,cAAA;EACV,SAAS,GAAG,QAAQ;CACtB,CAAC;CACH,MAAM,gBAAgB,KAAK,KAAK,SAAS,mBAAmB;CAC5D,MAAM,8BAAc,IAAI,IAAqF;CAC7G,MAAM,gCAAgB,IAAI,IAGxB;CAEF,MAAM,eACJ,OACA,UACA,OACA,UACM;EACN,IAAI;EACJ,IAAI;GACF,OAAO,GAAG,SAAS,QAAQ;EAC7B,QAAQ;GACN,MAAM,OAAO,QAAQ;GACrB,OAAO;EACT;EACA,MAAM,SAAS,MAAM,IAAI,QAAQ;EACjC,IAAI,UAAU,OAAO,SAAS,KAAK,QAAQ,OAAO,YAAY,KAAK,SAAS,OAAO,OAAO;EAC1F,IAAI;EACJ,IAAI;GACF,MAAM,GAAG,aAAa,UAAU,MAAM;EACxC,QAAQ;GACN,MAAM,OAAO,QAAQ;GACrB,OAAO;EACT;EACA,MAAM,QAAQ,MAAM,GAAG;EACvB,MAAM,IAAI,UAAU;GAAE,MAAM,KAAK;GAAM,SAAS,KAAK;GAAS;EAAM,CAAC;EACrE,OAAO;CACT;CAEA,MAAM,WAAW,cAAgC;EAC/C,IAAI;GACF,OAAO,GAAG,YAAY,SAAS,CAAC,CAAC,KAAK;EACxC,QAAQ;GACN,OAAO,CAAC;EACV;CACF;CAEA,MAAM,OAA4B,CAAC;CACnC,KAAK,MAAM,aAAa,QAAQ,aAAa,GAC3C,KAAK,MAAM,SAAS,iBAAiB;EACnC,MAAM,WAAW,KAAK,KAAK,eAAe,WAAW,KAAK;EAC1D,KAAK,MAAM,UAAU,QAAQ,QAAQ,GAAG;GACtC,MAAM,SAAS,KAAK,KAAK,UAAU,MAAM;GACzC,MAAM,aAAa,KAAK,KAAK,QAAQ,oBAAoB;GACzD,MAAM,eAAe,KAAK,KAAK,QAAQ,kBAAkB;GACzD,MAAM,SAAS,YAAY,aAAa,YAAY,wBAAwB,KAAA,CAAS;GACrF,IAAI,WAAW,KAAA,GAAW;GAC1B,MAAM,OAAO,YACX,eACA,eACC,QAAQ,qBAAqB,sBAAsB,GAAG,CAAC,GACxD,CAAC,CACH;GACA,KAAK,KAAK;IAAE,GAAG;IAAQ,MAAM,wBAAwB,OAAO,MAAM,IAAI;GAAE,CAAC;EAC3E;CACF;CAEF,OAAO;AACT"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const require_index = require("../workflowRuns/index.cjs");
|
|
2
|
+
const require_index$1 = require("../workflowWatcher/index.cjs");
|
|
3
|
+
const require_webWorkflows = require("../../types/webWorkflows.cjs");
|
|
4
|
+
//#region src/services/workflowsHubChannel/index.ts
|
|
5
|
+
function isWorkflowRunsPayload(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && Array.isArray(value.runs);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The workflow runs data channel. Durable registry state seeds each session
|
|
10
|
+
* once; subsequent updates arrive through the host-owned direct event bus.
|
|
11
|
+
*/
|
|
12
|
+
function createWorkflowsChannel(options = {}) {
|
|
13
|
+
const read = options.read ?? require_index$1.readWorkflowRuns;
|
|
14
|
+
return {
|
|
15
|
+
frameType: require_webWorkflows.WORKFLOW_RUNS_TYPE,
|
|
16
|
+
start(host) {
|
|
17
|
+
const scopes = /* @__PURE__ */ new Map();
|
|
18
|
+
const latest = /* @__PURE__ */ new Map();
|
|
19
|
+
const subscriptions = /* @__PURE__ */ new Map();
|
|
20
|
+
const runsFor = (scope, parsed) => require_index.presentWorkflowRuns(parsed.filter((run) => require_index.runBelongsToSession(run, scope.sessionId)).map((run) => run.view), Date.now());
|
|
21
|
+
const publish = (scope, payload) => {
|
|
22
|
+
latest.set(scope.sessionId, payload);
|
|
23
|
+
host.publish(scope.sessionId, payload);
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
payloadFor(scope) {
|
|
27
|
+
return scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : void 0;
|
|
28
|
+
},
|
|
29
|
+
sessionAdded(scope) {
|
|
30
|
+
scopes.set(scope.sessionId, scope);
|
|
31
|
+
subscriptions.get(scope.sessionId)?.();
|
|
32
|
+
const unsubscribe = host.directEvents.subscribe(require_webWorkflows.WORKFLOW_RUNS_TYPE, scope.sessionId, (value) => {
|
|
33
|
+
if (isWorkflowRunsPayload(value)) publish(scope, value);
|
|
34
|
+
}, { replayLatest: true });
|
|
35
|
+
subscriptions.set(scope.sessionId, unsubscribe);
|
|
36
|
+
const payload = { runs: runsFor(scope, read({ environment: scope.environment })) };
|
|
37
|
+
publish(scope, payload);
|
|
38
|
+
},
|
|
39
|
+
sessionRemoved(sessionId) {
|
|
40
|
+
subscriptions.get(sessionId)?.();
|
|
41
|
+
subscriptions.delete(sessionId);
|
|
42
|
+
scopes.delete(sessionId);
|
|
43
|
+
latest.delete(sessionId);
|
|
44
|
+
},
|
|
45
|
+
close() {
|
|
46
|
+
for (const unsubscribe of subscriptions.values()) unsubscribe();
|
|
47
|
+
subscriptions.clear();
|
|
48
|
+
scopes.clear();
|
|
49
|
+
latest.clear();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
exports.createWorkflowsChannel = createWorkflowsChannel;
|
|
57
|
+
|
|
58
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["readWorkflowRuns","WORKFLOW_RUNS_TYPE","presentWorkflowRuns","runBelongsToSession"],"sources":["../../../../src/services/workflowsHubChannel/index.ts"],"sourcesContent":["import type { DoomHubChannelSource, DoomHubSessionScope, DoomHubChannel } from '@agimon-ai/doompi-core/hub-channel';\n\nimport { presentWorkflowRuns, runBelongsToSession, type ParsedWorkflowRun } from '../../services/workflowRuns';\nimport { readWorkflowRuns, type ReadWorkflowRunsOptions } from '../../services/workflowWatcher';\nimport { WORKFLOW_RUNS_TYPE, type WorkflowRunView, type WorkflowRunsPayload } from '../../types/webWorkflows';\n\nexport interface WorkflowsChannelOptions {\n /** Injectable durable initial snapshot reader for tests. */\n read?: (options: ReadWorkflowRunsOptions) => ParsedWorkflowRun[];\n}\n\nfunction isWorkflowRunsPayload(value: unknown): value is WorkflowRunsPayload {\n return typeof value === 'object' && value !== null && Array.isArray((value as { runs?: unknown }).runs);\n}\n\n/**\n * The workflow runs data channel. Durable registry state seeds each session\n * once; subsequent updates arrive through the host-owned direct event bus.\n */\nexport function createWorkflowsChannel(options: WorkflowsChannelOptions = {}): DoomHubChannel {\n const read = options.read ?? readWorkflowRuns;\n return {\n frameType: WORKFLOW_RUNS_TYPE,\n start(host) {\n const scopes = new Map<string, DoomHubSessionScope>();\n const latest = new Map<string, WorkflowRunsPayload>();\n const subscriptions = new Map<string, () => void>();\n const runsFor = (scope: DoomHubSessionScope, parsed: readonly ParsedWorkflowRun[]): WorkflowRunView[] =>\n presentWorkflowRuns(\n parsed.filter((run) => runBelongsToSession(run, scope.sessionId)).map((run) => run.view),\n Date.now(),\n );\n const publish = (scope: DoomHubSessionScope, payload: WorkflowRunsPayload): void => {\n latest.set(scope.sessionId, payload);\n host.publish(scope.sessionId, payload);\n };\n const source: DoomHubChannelSource = {\n payloadFor(scope) {\n return scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : undefined;\n },\n sessionAdded(scope) {\n scopes.set(scope.sessionId, scope);\n subscriptions.get(scope.sessionId)?.();\n const unsubscribe = host.directEvents.subscribe(\n WORKFLOW_RUNS_TYPE,\n scope.sessionId,\n (value) => {\n if (isWorkflowRunsPayload(value)) publish(scope, value);\n },\n { replayLatest: true },\n );\n subscriptions.set(scope.sessionId, unsubscribe);\n const payload = { runs: runsFor(scope, read({ environment: scope.environment })) };\n publish(scope, payload);\n },\n sessionRemoved(sessionId) {\n subscriptions.get(sessionId)?.();\n subscriptions.delete(sessionId);\n scopes.delete(sessionId);\n latest.delete(sessionId);\n },\n close() {\n for (const unsubscribe of subscriptions.values()) unsubscribe();\n subscriptions.clear();\n scopes.clear();\n latest.clear();\n },\n };\n return source;\n },\n };\n}\n"],"mappings":";;;;AAWA,SAAS,sBAAsB,OAA8C;CAC3E,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAS,MAA6B,IAAI;AACxG;;;;;AAMA,SAAgB,uBAAuB,UAAmC,CAAC,GAAmB;CAC5F,MAAM,OAAO,QAAQ,QAAQA,gBAAAA;CAC7B,OAAO;EACL,WAAWC,qBAAAA;EACX,MAAM,MAAM;GACV,MAAM,yBAAS,IAAI,IAAiC;GACpD,MAAM,yBAAS,IAAI,IAAiC;GACpD,MAAM,gCAAgB,IAAI,IAAwB;GAClD,MAAM,WAAW,OAA4B,WAC3CC,cAAAA,oBACE,OAAO,QAAQ,QAAQC,cAAAA,oBAAoB,KAAK,MAAM,SAAS,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,GACvF,KAAK,IAAI,CACX;GACF,MAAM,WAAW,OAA4B,YAAuC;IAClF,OAAO,IAAI,MAAM,WAAW,OAAO;IACnC,KAAK,QAAQ,MAAM,WAAW,OAAO;GACvC;GAiCA,OAAO;IA/BL,WAAW,OAAO;KAChB,OAAO,OAAO,IAAI,MAAM,SAAS,IAAI,OAAO,IAAI,MAAM,SAAS,IAAI,KAAA;IACrE;IACA,aAAa,OAAO;KAClB,OAAO,IAAI,MAAM,WAAW,KAAK;KACjC,cAAc,IAAI,MAAM,SAAS,CAAC,GAAG;KACrC,MAAM,cAAc,KAAK,aAAa,UACpCF,qBAAAA,oBACA,MAAM,YACL,UAAU;MACT,IAAI,sBAAsB,KAAK,GAAG,QAAQ,OAAO,KAAK;KACxD,GACA,EAAE,cAAc,KAAK,CACvB;KACA,cAAc,IAAI,MAAM,WAAW,WAAW;KAC9C,MAAM,UAAU,EAAE,MAAM,QAAQ,OAAO,KAAK,EAAE,aAAa,MAAM,YAAY,CAAC,CAAC,EAAE;KACjF,QAAQ,OAAO,OAAO;IACxB;IACA,eAAe,WAAW;KACxB,cAAc,IAAI,SAAS,CAAC,GAAG;KAC/B,cAAc,OAAO,SAAS;KAC9B,OAAO,OAAO,SAAS;KACvB,OAAO,OAAO,SAAS;IACzB;IACA,QAAQ;KACN,KAAK,MAAM,eAAe,cAAc,OAAO,GAAG,YAAY;KAC9D,cAAc,MAAM;KACpB,OAAO,MAAM;KACb,OAAO,MAAM;IACf;GAEU;EACd;CACF;AACF"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { presentWorkflowRuns, runBelongsToSession } from "../workflowRuns/index.mjs";
|
|
2
|
+
import { readWorkflowRuns } from "../workflowWatcher/index.mjs";
|
|
3
|
+
import { WORKFLOW_RUNS_TYPE } from "../../types/webWorkflows.mjs";
|
|
4
|
+
//#region src/services/workflowsHubChannel/index.ts
|
|
5
|
+
function isWorkflowRunsPayload(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && Array.isArray(value.runs);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The workflow runs data channel. Durable registry state seeds each session
|
|
10
|
+
* once; subsequent updates arrive through the host-owned direct event bus.
|
|
11
|
+
*/
|
|
12
|
+
function createWorkflowsChannel(options = {}) {
|
|
13
|
+
const read = options.read ?? readWorkflowRuns;
|
|
14
|
+
return {
|
|
15
|
+
frameType: WORKFLOW_RUNS_TYPE,
|
|
16
|
+
start(host) {
|
|
17
|
+
const scopes = /* @__PURE__ */ new Map();
|
|
18
|
+
const latest = /* @__PURE__ */ new Map();
|
|
19
|
+
const subscriptions = /* @__PURE__ */ new Map();
|
|
20
|
+
const runsFor = (scope, parsed) => presentWorkflowRuns(parsed.filter((run) => runBelongsToSession(run, scope.sessionId)).map((run) => run.view), Date.now());
|
|
21
|
+
const publish = (scope, payload) => {
|
|
22
|
+
latest.set(scope.sessionId, payload);
|
|
23
|
+
host.publish(scope.sessionId, payload);
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
payloadFor(scope) {
|
|
27
|
+
return scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : void 0;
|
|
28
|
+
},
|
|
29
|
+
sessionAdded(scope) {
|
|
30
|
+
scopes.set(scope.sessionId, scope);
|
|
31
|
+
subscriptions.get(scope.sessionId)?.();
|
|
32
|
+
const unsubscribe = host.directEvents.subscribe(WORKFLOW_RUNS_TYPE, scope.sessionId, (value) => {
|
|
33
|
+
if (isWorkflowRunsPayload(value)) publish(scope, value);
|
|
34
|
+
}, { replayLatest: true });
|
|
35
|
+
subscriptions.set(scope.sessionId, unsubscribe);
|
|
36
|
+
const payload = { runs: runsFor(scope, read({ environment: scope.environment })) };
|
|
37
|
+
publish(scope, payload);
|
|
38
|
+
},
|
|
39
|
+
sessionRemoved(sessionId) {
|
|
40
|
+
subscriptions.get(sessionId)?.();
|
|
41
|
+
subscriptions.delete(sessionId);
|
|
42
|
+
scopes.delete(sessionId);
|
|
43
|
+
latest.delete(sessionId);
|
|
44
|
+
},
|
|
45
|
+
close() {
|
|
46
|
+
for (const unsubscribe of subscriptions.values()) unsubscribe();
|
|
47
|
+
subscriptions.clear();
|
|
48
|
+
scopes.clear();
|
|
49
|
+
latest.clear();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { createWorkflowsChannel };
|
|
57
|
+
|
|
58
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/services/workflowsHubChannel/index.ts"],"sourcesContent":["import type { DoomHubChannelSource, DoomHubSessionScope, DoomHubChannel } from '@agimon-ai/doompi-core/hub-channel';\n\nimport { presentWorkflowRuns, runBelongsToSession, type ParsedWorkflowRun } from '../../services/workflowRuns';\nimport { readWorkflowRuns, type ReadWorkflowRunsOptions } from '../../services/workflowWatcher';\nimport { WORKFLOW_RUNS_TYPE, type WorkflowRunView, type WorkflowRunsPayload } from '../../types/webWorkflows';\n\nexport interface WorkflowsChannelOptions {\n /** Injectable durable initial snapshot reader for tests. */\n read?: (options: ReadWorkflowRunsOptions) => ParsedWorkflowRun[];\n}\n\nfunction isWorkflowRunsPayload(value: unknown): value is WorkflowRunsPayload {\n return typeof value === 'object' && value !== null && Array.isArray((value as { runs?: unknown }).runs);\n}\n\n/**\n * The workflow runs data channel. Durable registry state seeds each session\n * once; subsequent updates arrive through the host-owned direct event bus.\n */\nexport function createWorkflowsChannel(options: WorkflowsChannelOptions = {}): DoomHubChannel {\n const read = options.read ?? readWorkflowRuns;\n return {\n frameType: WORKFLOW_RUNS_TYPE,\n start(host) {\n const scopes = new Map<string, DoomHubSessionScope>();\n const latest = new Map<string, WorkflowRunsPayload>();\n const subscriptions = new Map<string, () => void>();\n const runsFor = (scope: DoomHubSessionScope, parsed: readonly ParsedWorkflowRun[]): WorkflowRunView[] =>\n presentWorkflowRuns(\n parsed.filter((run) => runBelongsToSession(run, scope.sessionId)).map((run) => run.view),\n Date.now(),\n );\n const publish = (scope: DoomHubSessionScope, payload: WorkflowRunsPayload): void => {\n latest.set(scope.sessionId, payload);\n host.publish(scope.sessionId, payload);\n };\n const source: DoomHubChannelSource = {\n payloadFor(scope) {\n return scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : undefined;\n },\n sessionAdded(scope) {\n scopes.set(scope.sessionId, scope);\n subscriptions.get(scope.sessionId)?.();\n const unsubscribe = host.directEvents.subscribe(\n WORKFLOW_RUNS_TYPE,\n scope.sessionId,\n (value) => {\n if (isWorkflowRunsPayload(value)) publish(scope, value);\n },\n { replayLatest: true },\n );\n subscriptions.set(scope.sessionId, unsubscribe);\n const payload = { runs: runsFor(scope, read({ environment: scope.environment })) };\n publish(scope, payload);\n },\n sessionRemoved(sessionId) {\n subscriptions.get(sessionId)?.();\n subscriptions.delete(sessionId);\n scopes.delete(sessionId);\n latest.delete(sessionId);\n },\n close() {\n for (const unsubscribe of subscriptions.values()) unsubscribe();\n subscriptions.clear();\n scopes.clear();\n latest.clear();\n },\n };\n return source;\n },\n };\n}\n"],"mappings":";;;;AAWA,SAAS,sBAAsB,OAA8C;CAC3E,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAS,MAA6B,IAAI;AACxG;;;;;AAMA,SAAgB,uBAAuB,UAAmC,CAAC,GAAmB;CAC5F,MAAM,OAAO,QAAQ,QAAQ;CAC7B,OAAO;EACL,WAAW;EACX,MAAM,MAAM;GACV,MAAM,yBAAS,IAAI,IAAiC;GACpD,MAAM,yBAAS,IAAI,IAAiC;GACpD,MAAM,gCAAgB,IAAI,IAAwB;GAClD,MAAM,WAAW,OAA4B,WAC3C,oBACE,OAAO,QAAQ,QAAQ,oBAAoB,KAAK,MAAM,SAAS,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,GACvF,KAAK,IAAI,CACX;GACF,MAAM,WAAW,OAA4B,YAAuC;IAClF,OAAO,IAAI,MAAM,WAAW,OAAO;IACnC,KAAK,QAAQ,MAAM,WAAW,OAAO;GACvC;GAiCA,OAAO;IA/BL,WAAW,OAAO;KAChB,OAAO,OAAO,IAAI,MAAM,SAAS,IAAI,OAAO,IAAI,MAAM,SAAS,IAAI,KAAA;IACrE;IACA,aAAa,OAAO;KAClB,OAAO,IAAI,MAAM,WAAW,KAAK;KACjC,cAAc,IAAI,MAAM,SAAS,CAAC,GAAG;KACrC,MAAM,cAAc,KAAK,aAAa,UACpC,oBACA,MAAM,YACL,UAAU;MACT,IAAI,sBAAsB,KAAK,GAAG,QAAQ,OAAO,KAAK;KACxD,GACA,EAAE,cAAc,KAAK,CACvB;KACA,cAAc,IAAI,MAAM,WAAW,WAAW;KAC9C,MAAM,UAAU,EAAE,MAAM,QAAQ,OAAO,KAAK,EAAE,aAAa,MAAM,YAAY,CAAC,CAAC,EAAE;KACjF,QAAQ,OAAO,OAAO;IACxB;IACA,eAAe,WAAW;KACxB,cAAc,IAAI,SAAS,CAAC,GAAG;KAC/B,cAAc,OAAO,SAAS;KAC9B,OAAO,OAAO,SAAS;KACvB,OAAO,OAAO,SAAS;IACzB;IACA,QAAQ;KACN,KAAK,MAAM,eAAe,cAAc,OAAO,GAAG,YAAY;KAC9D,cAAc,MAAM;KACpB,OAAO,MAAM;KACb,OAAO,MAAM;IACf;GAEU;EACd;CACF;AACF"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const require_workflow = require("../constants/workflow.cjs");
|
|
2
|
+
//#region src/tui/leader.ts
|
|
3
|
+
const LEADER_BINDING_PREFIX = "doom-workflow";
|
|
4
|
+
const GROUP_SEGMENT = {
|
|
5
|
+
key: "w",
|
|
6
|
+
label: require_workflow.LEADER_LABEL,
|
|
7
|
+
detail: require_workflow.LEADER_DETAIL,
|
|
8
|
+
order: 50
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* The menu as it stands with the mode on or off.
|
|
12
|
+
*
|
|
13
|
+
* One entry on `e` rather than an enable row beside a disable row: only one of
|
|
14
|
+
* the two ever does anything, and a menu that prints both makes the reader
|
|
15
|
+
* check the mode line to find out which. The label says which way it flips.
|
|
16
|
+
*/
|
|
17
|
+
function workflowLeaderBindings(mode) {
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
id: `${LEADER_BINDING_PREFIX}.catalog`,
|
|
21
|
+
path: [GROUP_SEGMENT, {
|
|
22
|
+
key: "l",
|
|
23
|
+
label: "list",
|
|
24
|
+
detail: "browse and launch workflows"
|
|
25
|
+
}],
|
|
26
|
+
action: { name: require_workflow.LEADER_CATALOG_ACTION }
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: `${LEADER_BINDING_PREFIX}.manage`,
|
|
30
|
+
path: [GROUP_SEGMENT, {
|
|
31
|
+
key: "r",
|
|
32
|
+
label: "runs",
|
|
33
|
+
detail: "runs in this session"
|
|
34
|
+
}],
|
|
35
|
+
action: { name: require_workflow.LEADER_MANAGE_ACTION }
|
|
36
|
+
},
|
|
37
|
+
mode ? {
|
|
38
|
+
id: `${LEADER_BINDING_PREFIX}.disable`,
|
|
39
|
+
path: [GROUP_SEGMENT, {
|
|
40
|
+
key: "e",
|
|
41
|
+
label: "exit",
|
|
42
|
+
detail: "take back workflow tools",
|
|
43
|
+
tone: "exit"
|
|
44
|
+
}],
|
|
45
|
+
action: { name: require_workflow.LEADER_DISABLE_ACTION }
|
|
46
|
+
} : {
|
|
47
|
+
id: `${LEADER_BINDING_PREFIX}.enable`,
|
|
48
|
+
path: [GROUP_SEGMENT, {
|
|
49
|
+
key: "e",
|
|
50
|
+
label: "enter",
|
|
51
|
+
detail: "give the agent workflow tools"
|
|
52
|
+
}],
|
|
53
|
+
action: { name: require_workflow.LEADER_ENABLE_ACTION }
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: `${LEADER_BINDING_PREFIX}.recover`,
|
|
57
|
+
path: [GROUP_SEGMENT, {
|
|
58
|
+
key: "c",
|
|
59
|
+
label: "recover",
|
|
60
|
+
detail: "adopt a failed run"
|
|
61
|
+
}],
|
|
62
|
+
action: { name: require_workflow.LEADER_RECOVER_ACTION }
|
|
63
|
+
}
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
function registerLeaderContribution(hub, enabled = false) {
|
|
67
|
+
const contribution = hub.registerLeader({
|
|
68
|
+
source: require_workflow.PACKAGE_SOURCE,
|
|
69
|
+
bindings: workflowLeaderBindings(enabled)
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
setMode(enabled) {
|
|
73
|
+
contribution.update(workflowLeaderBindings(enabled));
|
|
74
|
+
},
|
|
75
|
+
dispose() {
|
|
76
|
+
contribution.dispose();
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
exports.registerLeaderContribution = registerLeaderContribution;
|
|
82
|
+
exports.workflowLeaderBindings = workflowLeaderBindings;
|
|
83
|
+
|
|
84
|
+
//# sourceMappingURL=leader.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leader.cjs","names":["LEADER_LABEL","LEADER_DETAIL","LEADER_CATALOG_ACTION","LEADER_MANAGE_ACTION","LEADER_DISABLE_ACTION","LEADER_ENABLE_ACTION","LEADER_RECOVER_ACTION","PACKAGE_SOURCE"],"sources":["../../../src/tui/leader.ts"],"sourcesContent":["import type { LeaderBinding } from '@agimon-ai/doompi-core/leader';\nimport type { DoomUiHubService } from '@agimon-ai/doompi-core/ui-hub';\n\nimport {\n LEADER_CATALOG_ACTION,\n LEADER_DETAIL,\n LEADER_DISABLE_ACTION,\n LEADER_ENABLE_ACTION,\n LEADER_KEY,\n LEADER_LABEL,\n LEADER_MANAGE_ACTION,\n LEADER_ORDER,\n LEADER_RECOVER_ACTION,\n PACKAGE_SOURCE,\n} from '../constants/workflow';\n\nconst LEADER_BINDING_PREFIX = 'doom-workflow';\nconst GROUP_SEGMENT = {\n key: LEADER_KEY,\n label: LEADER_LABEL,\n detail: LEADER_DETAIL,\n order: LEADER_ORDER,\n} as const;\n\nexport interface WorkflowLeaderHandle {\n /** Republish the menu for the mode's current state. */\n setMode(enabled: boolean): void;\n dispose(): void;\n}\n\n/**\n * The menu as it stands with the mode on or off.\n *\n * One entry on `e` rather than an enable row beside a disable row: only one of\n * the two ever does anything, and a menu that prints both makes the reader\n * check the mode line to find out which. The label says which way it flips.\n */\nexport function workflowLeaderBindings(mode: boolean): LeaderBinding[] {\n return [\n {\n id: `${LEADER_BINDING_PREFIX}.catalog`,\n // Launching lives on this board's own `r` key rather than a second menu\n // entry: picking which workflow to run is the same act as reading what\n // one does.\n path: [GROUP_SEGMENT, { key: 'l', label: 'list', detail: 'browse and launch workflows' }],\n action: { name: LEADER_CATALOG_ACTION },\n },\n {\n id: `${LEADER_BINDING_PREFIX}.manage`,\n path: [GROUP_SEGMENT, { key: 'r', label: 'runs', detail: 'runs in this session' }],\n action: { name: LEADER_MANAGE_ACTION },\n },\n mode\n ? {\n id: `${LEADER_BINDING_PREFIX}.disable`,\n path: [GROUP_SEGMENT, { key: 'e', label: 'exit', detail: 'take back workflow tools', tone: 'exit' }],\n action: { name: LEADER_DISABLE_ACTION },\n }\n : {\n id: `${LEADER_BINDING_PREFIX}.enable`,\n path: [GROUP_SEGMENT, { key: 'e', label: 'enter', detail: 'give the agent workflow tools' }],\n action: { name: LEADER_ENABLE_ACTION },\n },\n // `r` is runs everywhere, so recovery moves off it rather than reading as a\n // third flavour of list in the one space that has both.\n {\n id: `${LEADER_BINDING_PREFIX}.recover`,\n path: [GROUP_SEGMENT, { key: 'c', label: 'recover', detail: 'adopt a failed run' }],\n action: { name: LEADER_RECOVER_ACTION },\n },\n ];\n}\n\nexport function registerLeaderContribution(hub: DoomUiHubService, enabled = false): WorkflowLeaderHandle {\n const contribution = hub.registerLeader({\n source: PACKAGE_SOURCE,\n bindings: workflowLeaderBindings(enabled),\n });\n return {\n setMode(enabled) {\n contribution.update(workflowLeaderBindings(enabled));\n },\n dispose() {\n contribution.dispose();\n },\n };\n}\n"],"mappings":";;AAgBA,MAAM,wBAAwB;AAC9B,MAAM,gBAAgB;CACpB,KAAA;CACA,OAAOA,iBAAAA;CACP,QAAQC,iBAAAA;CACR,OAAA;AACF;;;;;;;;AAeA,SAAgB,uBAAuB,MAAgC;CACrE,OAAO;EACL;GACE,IAAI,GAAG,sBAAsB;GAI7B,MAAM,CAAC,eAAe;IAAE,KAAK;IAAK,OAAO;IAAQ,QAAQ;GAA8B,CAAC;GACxF,QAAQ,EAAE,MAAMC,iBAAAA,sBAAsB;EACxC;EACA;GACE,IAAI,GAAG,sBAAsB;GAC7B,MAAM,CAAC,eAAe;IAAE,KAAK;IAAK,OAAO;IAAQ,QAAQ;GAAuB,CAAC;GACjF,QAAQ,EAAE,MAAMC,iBAAAA,qBAAqB;EACvC;EACA,OACI;GACE,IAAI,GAAG,sBAAsB;GAC7B,MAAM,CAAC,eAAe;IAAE,KAAK;IAAK,OAAO;IAAQ,QAAQ;IAA4B,MAAM;GAAO,CAAC;GACnG,QAAQ,EAAE,MAAMC,iBAAAA,sBAAsB;EACxC,IACA;GACE,IAAI,GAAG,sBAAsB;GAC7B,MAAM,CAAC,eAAe;IAAE,KAAK;IAAK,OAAO;IAAS,QAAQ;GAAgC,CAAC;GAC3F,QAAQ,EAAE,MAAMC,iBAAAA,qBAAqB;EACvC;EAGJ;GACE,IAAI,GAAG,sBAAsB;GAC7B,MAAM,CAAC,eAAe;IAAE,KAAK;IAAK,OAAO;IAAW,QAAQ;GAAqB,CAAC;GAClF,QAAQ,EAAE,MAAMC,iBAAAA,sBAAsB;EACxC;CACF;AACF;AAEA,SAAgB,2BAA2B,KAAuB,UAAU,OAA6B;CACvG,MAAM,eAAe,IAAI,eAAe;EACtC,QAAQC,iBAAAA;EACR,UAAU,uBAAuB,OAAO;CAC1C,CAAC;CACD,OAAO;EACL,QAAQ,SAAS;GACf,aAAa,OAAO,uBAAuB,OAAO,CAAC;EACrD;EACA,UAAU;GACR,aAAa,QAAQ;EACvB;CACF;AACF"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { LEADER_CATALOG_ACTION, LEADER_DETAIL, LEADER_DISABLE_ACTION, LEADER_ENABLE_ACTION, LEADER_LABEL, LEADER_MANAGE_ACTION, LEADER_RECOVER_ACTION, PACKAGE_SOURCE } from "../constants/workflow.mjs";
|
|
2
|
+
//#region src/tui/leader.ts
|
|
3
|
+
const LEADER_BINDING_PREFIX = "doom-workflow";
|
|
4
|
+
const GROUP_SEGMENT = {
|
|
5
|
+
key: "w",
|
|
6
|
+
label: LEADER_LABEL,
|
|
7
|
+
detail: LEADER_DETAIL,
|
|
8
|
+
order: 50
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* The menu as it stands with the mode on or off.
|
|
12
|
+
*
|
|
13
|
+
* One entry on `e` rather than an enable row beside a disable row: only one of
|
|
14
|
+
* the two ever does anything, and a menu that prints both makes the reader
|
|
15
|
+
* check the mode line to find out which. The label says which way it flips.
|
|
16
|
+
*/
|
|
17
|
+
function workflowLeaderBindings(mode) {
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
id: `${LEADER_BINDING_PREFIX}.catalog`,
|
|
21
|
+
path: [GROUP_SEGMENT, {
|
|
22
|
+
key: "l",
|
|
23
|
+
label: "list",
|
|
24
|
+
detail: "browse and launch workflows"
|
|
25
|
+
}],
|
|
26
|
+
action: { name: LEADER_CATALOG_ACTION }
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: `${LEADER_BINDING_PREFIX}.manage`,
|
|
30
|
+
path: [GROUP_SEGMENT, {
|
|
31
|
+
key: "r",
|
|
32
|
+
label: "runs",
|
|
33
|
+
detail: "runs in this session"
|
|
34
|
+
}],
|
|
35
|
+
action: { name: LEADER_MANAGE_ACTION }
|
|
36
|
+
},
|
|
37
|
+
mode ? {
|
|
38
|
+
id: `${LEADER_BINDING_PREFIX}.disable`,
|
|
39
|
+
path: [GROUP_SEGMENT, {
|
|
40
|
+
key: "e",
|
|
41
|
+
label: "exit",
|
|
42
|
+
detail: "take back workflow tools",
|
|
43
|
+
tone: "exit"
|
|
44
|
+
}],
|
|
45
|
+
action: { name: LEADER_DISABLE_ACTION }
|
|
46
|
+
} : {
|
|
47
|
+
id: `${LEADER_BINDING_PREFIX}.enable`,
|
|
48
|
+
path: [GROUP_SEGMENT, {
|
|
49
|
+
key: "e",
|
|
50
|
+
label: "enter",
|
|
51
|
+
detail: "give the agent workflow tools"
|
|
52
|
+
}],
|
|
53
|
+
action: { name: LEADER_ENABLE_ACTION }
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: `${LEADER_BINDING_PREFIX}.recover`,
|
|
57
|
+
path: [GROUP_SEGMENT, {
|
|
58
|
+
key: "c",
|
|
59
|
+
label: "recover",
|
|
60
|
+
detail: "adopt a failed run"
|
|
61
|
+
}],
|
|
62
|
+
action: { name: LEADER_RECOVER_ACTION }
|
|
63
|
+
}
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
function registerLeaderContribution(hub, enabled = false) {
|
|
67
|
+
const contribution = hub.registerLeader({
|
|
68
|
+
source: PACKAGE_SOURCE,
|
|
69
|
+
bindings: workflowLeaderBindings(enabled)
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
setMode(enabled) {
|
|
73
|
+
contribution.update(workflowLeaderBindings(enabled));
|
|
74
|
+
},
|
|
75
|
+
dispose() {
|
|
76
|
+
contribution.dispose();
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { registerLeaderContribution, workflowLeaderBindings };
|
|
82
|
+
|
|
83
|
+
//# sourceMappingURL=leader.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leader.mjs","names":[],"sources":["../../../src/tui/leader.ts"],"sourcesContent":["import type { LeaderBinding } from '@agimon-ai/doompi-core/leader';\nimport type { DoomUiHubService } from '@agimon-ai/doompi-core/ui-hub';\n\nimport {\n LEADER_CATALOG_ACTION,\n LEADER_DETAIL,\n LEADER_DISABLE_ACTION,\n LEADER_ENABLE_ACTION,\n LEADER_KEY,\n LEADER_LABEL,\n LEADER_MANAGE_ACTION,\n LEADER_ORDER,\n LEADER_RECOVER_ACTION,\n PACKAGE_SOURCE,\n} from '../constants/workflow';\n\nconst LEADER_BINDING_PREFIX = 'doom-workflow';\nconst GROUP_SEGMENT = {\n key: LEADER_KEY,\n label: LEADER_LABEL,\n detail: LEADER_DETAIL,\n order: LEADER_ORDER,\n} as const;\n\nexport interface WorkflowLeaderHandle {\n /** Republish the menu for the mode's current state. */\n setMode(enabled: boolean): void;\n dispose(): void;\n}\n\n/**\n * The menu as it stands with the mode on or off.\n *\n * One entry on `e` rather than an enable row beside a disable row: only one of\n * the two ever does anything, and a menu that prints both makes the reader\n * check the mode line to find out which. The label says which way it flips.\n */\nexport function workflowLeaderBindings(mode: boolean): LeaderBinding[] {\n return [\n {\n id: `${LEADER_BINDING_PREFIX}.catalog`,\n // Launching lives on this board's own `r` key rather than a second menu\n // entry: picking which workflow to run is the same act as reading what\n // one does.\n path: [GROUP_SEGMENT, { key: 'l', label: 'list', detail: 'browse and launch workflows' }],\n action: { name: LEADER_CATALOG_ACTION },\n },\n {\n id: `${LEADER_BINDING_PREFIX}.manage`,\n path: [GROUP_SEGMENT, { key: 'r', label: 'runs', detail: 'runs in this session' }],\n action: { name: LEADER_MANAGE_ACTION },\n },\n mode\n ? {\n id: `${LEADER_BINDING_PREFIX}.disable`,\n path: [GROUP_SEGMENT, { key: 'e', label: 'exit', detail: 'take back workflow tools', tone: 'exit' }],\n action: { name: LEADER_DISABLE_ACTION },\n }\n : {\n id: `${LEADER_BINDING_PREFIX}.enable`,\n path: [GROUP_SEGMENT, { key: 'e', label: 'enter', detail: 'give the agent workflow tools' }],\n action: { name: LEADER_ENABLE_ACTION },\n },\n // `r` is runs everywhere, so recovery moves off it rather than reading as a\n // third flavour of list in the one space that has both.\n {\n id: `${LEADER_BINDING_PREFIX}.recover`,\n path: [GROUP_SEGMENT, { key: 'c', label: 'recover', detail: 'adopt a failed run' }],\n action: { name: LEADER_RECOVER_ACTION },\n },\n ];\n}\n\nexport function registerLeaderContribution(hub: DoomUiHubService, enabled = false): WorkflowLeaderHandle {\n const contribution = hub.registerLeader({\n source: PACKAGE_SOURCE,\n bindings: workflowLeaderBindings(enabled),\n });\n return {\n setMode(enabled) {\n contribution.update(workflowLeaderBindings(enabled));\n },\n dispose() {\n contribution.dispose();\n },\n };\n}\n"],"mappings":";;AAgBA,MAAM,wBAAwB;AAC9B,MAAM,gBAAgB;CACpB,KAAA;CACA,OAAO;CACP,QAAQ;CACR,OAAA;AACF;;;;;;;;AAeA,SAAgB,uBAAuB,MAAgC;CACrE,OAAO;EACL;GACE,IAAI,GAAG,sBAAsB;GAI7B,MAAM,CAAC,eAAe;IAAE,KAAK;IAAK,OAAO;IAAQ,QAAQ;GAA8B,CAAC;GACxF,QAAQ,EAAE,MAAM,sBAAsB;EACxC;EACA;GACE,IAAI,GAAG,sBAAsB;GAC7B,MAAM,CAAC,eAAe;IAAE,KAAK;IAAK,OAAO;IAAQ,QAAQ;GAAuB,CAAC;GACjF,QAAQ,EAAE,MAAM,qBAAqB;EACvC;EACA,OACI;GACE,IAAI,GAAG,sBAAsB;GAC7B,MAAM,CAAC,eAAe;IAAE,KAAK;IAAK,OAAO;IAAQ,QAAQ;IAA4B,MAAM;GAAO,CAAC;GACnG,QAAQ,EAAE,MAAM,sBAAsB;EACxC,IACA;GACE,IAAI,GAAG,sBAAsB;GAC7B,MAAM,CAAC,eAAe;IAAE,KAAK;IAAK,OAAO;IAAS,QAAQ;GAAgC,CAAC;GAC3F,QAAQ,EAAE,MAAM,qBAAqB;EACvC;EAGJ;GACE,IAAI,GAAG,sBAAsB;GAC7B,MAAM,CAAC,eAAe;IAAE,KAAK;IAAK,OAAO;IAAW,QAAQ;GAAqB,CAAC;GAClF,QAAQ,EAAE,MAAM,sBAAsB;EACxC;CACF;AACF;AAEA,SAAgB,2BAA2B,KAAuB,UAAU,OAA6B;CACvG,MAAM,eAAe,IAAI,eAAe;EACtC,QAAQ;EACR,UAAU,uBAAuB,OAAO;CAC1C,CAAC;CACD,OAAO;EACL,QAAQ,SAAS;GACf,aAAa,OAAO,uBAAuB,OAAO,CAAC;EACrD;EACA,UAAU;GACR,aAAa,QAAQ;EACvB;CACF;AACF"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
const require_rendering = require("./rendering.cjs");
|
|
2
|
+
let _earendil_works_pi_tui = require("@earendil-works/pi-tui");
|
|
3
|
+
//#region src/tui/workflow/doomOverlay.ts
|
|
4
|
+
const DEFAULT_TERMINAL_ROWS = 24;
|
|
5
|
+
const FULL_CHROME_ROWS = 6;
|
|
6
|
+
/** Two frame columns and two gutter columns, leaving content worth framing. */
|
|
7
|
+
const MIN_FRAMED_WIDTH = 8;
|
|
8
|
+
const GUTTER = " ";
|
|
9
|
+
const GUTTER_COLUMNS = 2;
|
|
10
|
+
/** Blank columns kept between a row's left cluster and its right-aligned status. */
|
|
11
|
+
const ROW_GAP = 2;
|
|
12
|
+
/** A secondary segment thinner than this is dropped rather than shredded into a stub. */
|
|
13
|
+
const MIN_SEGMENT_WIDTH = 8;
|
|
14
|
+
const ELLIPSIS = "…";
|
|
15
|
+
const BORDER_COLOR = "borderMuted";
|
|
16
|
+
const TEXT_COLOR = "text";
|
|
17
|
+
/** Filled key caps read as pressable, matching the doom mockups' footers. */
|
|
18
|
+
const HINT_CAP_BACKGROUND = "selectedBg";
|
|
19
|
+
const HINT_SEPARATOR = " ";
|
|
20
|
+
/** A cap's two pad columns plus the space before its label. */
|
|
21
|
+
const HINT_CHROME_COLUMNS = 6;
|
|
22
|
+
const TITLE_COLOR = "accent";
|
|
23
|
+
const SECONDARY_COLOR = "dim";
|
|
24
|
+
const HORIZONTAL_BORDER = "─";
|
|
25
|
+
const VERTICAL_BORDER = "│";
|
|
26
|
+
const TOP_CORNERS = ["╭", "╮"];
|
|
27
|
+
const DIVIDER_JOINTS = ["├", "┤"];
|
|
28
|
+
const BOTTOM_CORNERS = ["╰", "╯"];
|
|
29
|
+
/**
|
|
30
|
+
* One signature colour for every doom overlay: the frame and the title badge.
|
|
31
|
+
* Per-surface colours were tried and read as arbitrary, and they also borrowed
|
|
32
|
+
* tokens that mean something else (`warning`, `syntaxNumber`), so a theme edit
|
|
33
|
+
* elsewhere would have repainted a frame. Change it here to change them all.
|
|
34
|
+
*/
|
|
35
|
+
const DOOM_OVERLAY_ACCENT = "mdHeading";
|
|
36
|
+
const DOOM_FULLSCREEN_UI_OPTIONS = {
|
|
37
|
+
overlay: true,
|
|
38
|
+
overlayOptions: {
|
|
39
|
+
anchor: "top-left",
|
|
40
|
+
width: "100%",
|
|
41
|
+
maxHeight: "100%",
|
|
42
|
+
margin: 0
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Fits a secondary segment into `budget`, or drops it entirely when too few
|
|
47
|
+
* columns remain for it to stay readable. Truncating everything to fit is what
|
|
48
|
+
* makes a tight header read as one run-on string.
|
|
49
|
+
*/
|
|
50
|
+
function fitSegment(text, budget) {
|
|
51
|
+
if (!text || budget <= 0) return "";
|
|
52
|
+
return budget < Math.min((0, _earendil_works_pi_tui.visibleWidth)(text), MIN_SEGMENT_WIDTH) ? "" : (0, _earendil_works_pi_tui.truncateToWidth)(text, budget, ELLIPSIS);
|
|
53
|
+
}
|
|
54
|
+
var DoomOverlay = class {
|
|
55
|
+
tui;
|
|
56
|
+
theme;
|
|
57
|
+
constructor(tui, theme) {
|
|
58
|
+
this.tui = tui;
|
|
59
|
+
this.theme = theme;
|
|
60
|
+
}
|
|
61
|
+
invalidate() {
|
|
62
|
+
this.tui.requestRender();
|
|
63
|
+
}
|
|
64
|
+
render(width) {
|
|
65
|
+
const safeWidth = Math.max(0, Math.floor(width));
|
|
66
|
+
const height = Math.max(0, Math.floor(this.tui.terminal?.rows ?? DEFAULT_TERMINAL_ROWS));
|
|
67
|
+
if (safeWidth === 0 || height === 0) return [];
|
|
68
|
+
const chrome = this.getChrome();
|
|
69
|
+
if (height < FULL_CHROME_ROWS || safeWidth < MIN_FRAMED_WIDTH) return this.renderCompact(chrome, safeWidth, height);
|
|
70
|
+
const innerWidth = safeWidth - GUTTER_COLUMNS;
|
|
71
|
+
const contentWidth = innerWidth - GUTTER_COLUMNS;
|
|
72
|
+
const bodyHeight = height - FULL_CHROME_ROWS;
|
|
73
|
+
const body = this.renderBody(contentWidth, bodyHeight).slice(0, bodyHeight);
|
|
74
|
+
while (body.length < bodyHeight) body.push("");
|
|
75
|
+
const frame = chrome.accent ?? BORDER_COLOR;
|
|
76
|
+
return [
|
|
77
|
+
this.borderRow(TOP_CORNERS, innerWidth, frame),
|
|
78
|
+
this.contentRow(this.headerRow(chrome, contentWidth), contentWidth, safeWidth, frame),
|
|
79
|
+
this.borderRow(DIVIDER_JOINTS, innerWidth, frame, BORDER_COLOR),
|
|
80
|
+
...body.map((line) => this.contentRow(line, contentWidth, safeWidth, frame)),
|
|
81
|
+
this.borderRow(DIVIDER_JOINTS, innerWidth, frame, BORDER_COLOR),
|
|
82
|
+
this.contentRow(this.footerRow(chrome, contentWidth), contentWidth, safeWidth, frame),
|
|
83
|
+
this.borderRow(BOTTOM_CORNERS, innerWidth, frame)
|
|
84
|
+
].map((line) => require_rendering.padLine(line, safeWidth));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Edge glyphs and the rule between them are coloured separately: the outer
|
|
88
|
+
* rectangle carries the signature colour while an internal separator stays
|
|
89
|
+
* muted, meeting the frame at accent-coloured junctions.
|
|
90
|
+
*/
|
|
91
|
+
borderRow([left, right], innerWidth, edge = BORDER_COLOR, fill = edge) {
|
|
92
|
+
const edgeColour = edge ?? BORDER_COLOR;
|
|
93
|
+
return [
|
|
94
|
+
this.theme.fg(edgeColour, left),
|
|
95
|
+
this.theme.fg(fill ?? edgeColour, HORIZONTAL_BORDER.repeat(innerWidth)),
|
|
96
|
+
this.theme.fg(edgeColour, right)
|
|
97
|
+
].join("");
|
|
98
|
+
}
|
|
99
|
+
contentRow(content, contentWidth, width, colour = BORDER_COLOR) {
|
|
100
|
+
const edge = this.theme.fg(colour ?? BORDER_COLOR, VERTICAL_BORDER);
|
|
101
|
+
return require_rendering.frameLine(`${GUTTER}${require_rendering.padLine(content, contentWidth)}${GUTTER}`, width, edge, edge);
|
|
102
|
+
}
|
|
103
|
+
headerRow(chrome, width) {
|
|
104
|
+
const accent = chrome.accent;
|
|
105
|
+
const titleBudget = accent ? width - GUTTER_COLUMNS : width;
|
|
106
|
+
const title = (0, _earendil_works_pi_tui.truncateToWidth)(chrome.title, Math.max(0, titleBudget), ELLIPSIS);
|
|
107
|
+
let left = accent ? this.theme.inverse(this.theme.bold(this.theme.fg(accent, ` ${title} `))) : this.theme.bold(this.theme.fg(TITLE_COLOR, title));
|
|
108
|
+
let leftWidth = (0, _earendil_works_pi_tui.visibleWidth)(title) + (accent ? GUTTER_COLUMNS : 0);
|
|
109
|
+
const breadcrumb = fitSegment(chrome.breadcrumb, width - leftWidth - ROW_GAP);
|
|
110
|
+
if (breadcrumb) {
|
|
111
|
+
left += `${" ".repeat(ROW_GAP)}${this.theme.fg(SECONDARY_COLOR, breadcrumb)}`;
|
|
112
|
+
leftWidth += ROW_GAP + (0, _earendil_works_pi_tui.visibleWidth)(breadcrumb);
|
|
113
|
+
}
|
|
114
|
+
return this.withRightStatus(left, leftWidth, chrome.headerRight, width);
|
|
115
|
+
}
|
|
116
|
+
footerRow(chrome, width) {
|
|
117
|
+
const footer = chrome.footerHints?.length ? this.hintLegend(chrome.footerHints, width) : this.theme.fg(SECONDARY_COLOR, (0, _earendil_works_pi_tui.truncateToWidth)(chrome.footer, width, ELLIPSIS));
|
|
118
|
+
return this.withRightStatus(footer, (0, _earendil_works_pi_tui.visibleWidth)(footer), chrome.footerRight, width);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Key legend with each key in a filled cap. Every segment sets its own colour
|
|
122
|
+
* so the caps survive: a cap's reset would otherwise strip the surrounding
|
|
123
|
+
* dim from the labels that follow it.
|
|
124
|
+
*/
|
|
125
|
+
hintLegend(hints, width) {
|
|
126
|
+
let legend = "";
|
|
127
|
+
let used = 0;
|
|
128
|
+
for (const [key, label] of hints) {
|
|
129
|
+
const segmentWidth = (0, _earendil_works_pi_tui.visibleWidth)(key) + (0, _earendil_works_pi_tui.visibleWidth)(label) + HINT_CHROME_COLUMNS;
|
|
130
|
+
if (used + segmentWidth > width) break;
|
|
131
|
+
const cap = this.theme.bg(HINT_CAP_BACKGROUND, this.theme.fg(TEXT_COLOR, ` ${key} `));
|
|
132
|
+
legend += `${legend ? HINT_SEPARATOR : ""}${cap}${this.theme.fg(SECONDARY_COLOR, ` ${label}`)}`;
|
|
133
|
+
used += segmentWidth;
|
|
134
|
+
}
|
|
135
|
+
return legend;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Right-aligns a status cluster, dropping it whole when the row cannot spare
|
|
139
|
+
* the columns. A clipped status reads as a stub (`doom-log…`) that carries
|
|
140
|
+
* less than the blank space it costs.
|
|
141
|
+
*/
|
|
142
|
+
withRightStatus(left, leftWidth, right, width) {
|
|
143
|
+
const statusWidth = right ? (0, _earendil_works_pi_tui.visibleWidth)(right) : 0;
|
|
144
|
+
if (!right || statusWidth === 0 || leftWidth + ROW_GAP + statusWidth > width) return left;
|
|
145
|
+
return `${left}${" ".repeat(width - leftWidth - statusWidth)}${this.theme.fg(SECONDARY_COLOR, right)}`;
|
|
146
|
+
}
|
|
147
|
+
renderCompact(chrome, width, height) {
|
|
148
|
+
const lines = Array.from({ length: height }, () => "");
|
|
149
|
+
lines[0] = this.theme.bold(this.theme.fg(TITLE_COLOR, chrome.title));
|
|
150
|
+
if (height > 1) lines[height - 1] = this.theme.fg(SECONDARY_COLOR, chrome.footer);
|
|
151
|
+
return lines.map((line) => require_rendering.padLine(require_rendering.fitLine(line, width), width));
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
//#endregion
|
|
155
|
+
exports.DOOM_FULLSCREEN_UI_OPTIONS = DOOM_FULLSCREEN_UI_OPTIONS;
|
|
156
|
+
exports.DOOM_OVERLAY_ACCENT = DOOM_OVERLAY_ACCENT;
|
|
157
|
+
exports.DoomOverlay = DoomOverlay;
|
|
158
|
+
|
|
159
|
+
//# sourceMappingURL=doomOverlay.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doomOverlay.cjs","names":["visibleWidth","truncateToWidth","padLine","frameLine","fitLine"],"sources":["../../../../src/tui/workflow/doomOverlay.ts"],"sourcesContent":["import type { Theme } from '@earendil-works/pi-coding-agent';\nimport { type Component, truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nimport { fitLine, frameLine, padLine } from './rendering';\n\nconst DEFAULT_TERMINAL_ROWS = 24;\nconst FULL_CHROME_ROWS = 6;\n/** Two frame columns and two gutter columns, leaving content worth framing. */\nconst MIN_FRAMED_WIDTH = 8;\nconst GUTTER = ' ';\nconst GUTTER_COLUMNS = 2;\n/** Blank columns kept between a row's left cluster and its right-aligned status. */\nconst ROW_GAP = 2;\n/** A secondary segment thinner than this is dropped rather than shredded into a stub. */\nconst MIN_SEGMENT_WIDTH = 8;\nconst ELLIPSIS = '…';\nconst BORDER_COLOR = 'borderMuted';\nconst TEXT_COLOR = 'text';\n/** Filled key caps read as pressable, matching the doom mockups' footers. */\nconst HINT_CAP_BACKGROUND = 'selectedBg';\nconst HINT_SEPARATOR = ' ';\n/** A cap's two pad columns plus the space before its label. */\nconst HINT_CHROME_COLUMNS = 6;\nconst TITLE_COLOR = 'accent';\nconst SECONDARY_COLOR = 'dim';\nconst HORIZONTAL_BORDER = '─';\nconst VERTICAL_BORDER = '│';\nconst TOP_CORNERS = ['╭', '╮'] as const;\nconst DIVIDER_JOINTS = ['├', '┤'] as const;\nconst BOTTOM_CORNERS = ['╰', '╯'] as const;\n\nexport interface DoomOverlayTui {\n terminal?: {\n rows: number;\n columns?: number;\n };\n requestRender(force?: boolean): void;\n}\n\nexport interface DoomOverlayChrome {\n title: string;\n breadcrumb?: string;\n headerRight?: string;\n footer: string;\n footerRight?: string;\n /**\n * Key/label pairs rendered as filled caps, e.g. `[ enter ] edit subject`.\n * Takes precedence over `footer`, which stays for surfaces that want a plain\n * sentence rather than a key legend.\n */\n footerHints?: readonly (readonly [string, string])[];\n /**\n * Signature colour for the surface. When set, the frame takes it and the\n * title renders as a filled badge rather than plain accent text, matching the\n * doom mockups. Left unset, the frame stays muted and the title plain.\n */\n accent?: Parameters<Theme['fg']>[0];\n}\n\n/**\n * One signature colour for every doom overlay: the frame and the title badge.\n * Per-surface colours were tried and read as arbitrary, and they also borrowed\n * tokens that mean something else (`warning`, `syntaxNumber`), so a theme edit\n * elsewhere would have repainted a frame. Change it here to change them all.\n */\nexport const DOOM_OVERLAY_ACCENT = 'mdHeading' satisfies DoomOverlayChrome['accent'];\n\nexport const DOOM_FULLSCREEN_UI_OPTIONS = {\n overlay: true,\n overlayOptions: {\n anchor: 'top-left',\n width: '100%',\n maxHeight: '100%',\n margin: 0,\n },\n} as const;\n\n/**\n * Fits a secondary segment into `budget`, or drops it entirely when too few\n * columns remain for it to stay readable. Truncating everything to fit is what\n * makes a tight header read as one run-on string.\n */\nfunction fitSegment(text: string | undefined, budget: number): string {\n if (!text || budget <= 0) return '';\n return budget < Math.min(visibleWidth(text), MIN_SEGMENT_WIDTH) ? '' : truncateToWidth(text, budget, ELLIPSIS);\n}\n\nexport abstract class DoomOverlay implements Component {\n protected constructor(\n protected readonly tui: DoomOverlayTui,\n protected readonly theme: Theme,\n ) {}\n\n invalidate(): void {\n this.tui.requestRender();\n }\n\n render(width: number): string[] {\n const safeWidth = Math.max(0, Math.floor(width));\n const height = Math.max(0, Math.floor(this.tui.terminal?.rows ?? DEFAULT_TERMINAL_ROWS));\n if (safeWidth === 0 || height === 0) return [];\n\n const chrome = this.getChrome();\n if (height < FULL_CHROME_ROWS || safeWidth < MIN_FRAMED_WIDTH) {\n return this.renderCompact(chrome, safeWidth, height);\n }\n\n const innerWidth = safeWidth - GUTTER_COLUMNS;\n const contentWidth = innerWidth - GUTTER_COLUMNS;\n const bodyHeight = height - FULL_CHROME_ROWS;\n const body = this.renderBody(contentWidth, bodyHeight).slice(0, bodyHeight);\n while (body.length < bodyHeight) body.push('');\n\n const frame = chrome.accent ?? BORDER_COLOR;\n return [\n this.borderRow(TOP_CORNERS, innerWidth, frame),\n this.contentRow(this.headerRow(chrome, contentWidth), contentWidth, safeWidth, frame),\n this.borderRow(DIVIDER_JOINTS, innerWidth, frame, BORDER_COLOR),\n ...body.map((line) => this.contentRow(line, contentWidth, safeWidth, frame)),\n this.borderRow(DIVIDER_JOINTS, innerWidth, frame, BORDER_COLOR),\n this.contentRow(this.footerRow(chrome, contentWidth), contentWidth, safeWidth, frame),\n this.borderRow(BOTTOM_CORNERS, innerWidth, frame),\n ].map((line) => padLine(line, safeWidth));\n }\n\n protected abstract getChrome(): DoomOverlayChrome;\n\n protected abstract renderBody(width: number, height: number): string[];\n\n /**\n * Edge glyphs and the rule between them are coloured separately: the outer\n * rectangle carries the signature colour while an internal separator stays\n * muted, meeting the frame at accent-coloured junctions.\n */\n private borderRow(\n [left, right]: readonly [string, string],\n innerWidth: number,\n edge: DoomOverlayChrome['accent'] = BORDER_COLOR,\n fill: DoomOverlayChrome['accent'] = edge,\n ): string {\n const edgeColour = edge ?? BORDER_COLOR;\n return [\n this.theme.fg(edgeColour, left),\n this.theme.fg(fill ?? edgeColour, HORIZONTAL_BORDER.repeat(innerWidth)),\n this.theme.fg(edgeColour, right),\n ].join('');\n }\n\n private contentRow(\n content: string,\n contentWidth: number,\n width: number,\n colour: DoomOverlayChrome['accent'] = BORDER_COLOR,\n ): string {\n const edge = this.theme.fg(colour ?? BORDER_COLOR, VERTICAL_BORDER);\n return frameLine(`${GUTTER}${padLine(content, contentWidth)}${GUTTER}`, width, edge, edge);\n }\n\n private headerRow(chrome: DoomOverlayChrome, width: number): string {\n // A signature colour turns the title into a filled badge, as the mockups\n // show; without one it stays plain accent text.\n const accent = chrome.accent;\n const titleBudget = accent ? width - GUTTER_COLUMNS : width;\n const title = truncateToWidth(chrome.title, Math.max(0, titleBudget), ELLIPSIS);\n let left = accent\n ? this.theme.inverse(this.theme.bold(this.theme.fg(accent, ` ${title} `)))\n : this.theme.bold(this.theme.fg(TITLE_COLOR, title));\n let leftWidth = visibleWidth(title) + (accent ? GUTTER_COLUMNS : 0);\n\n // The breadcrumb claims room before the right status: it says where you are,\n // which outranks ambient context when the terminal is narrow.\n const breadcrumb = fitSegment(chrome.breadcrumb, width - leftWidth - ROW_GAP);\n if (breadcrumb) {\n left += `${' '.repeat(ROW_GAP)}${this.theme.fg(SECONDARY_COLOR, breadcrumb)}`;\n leftWidth += ROW_GAP + visibleWidth(breadcrumb);\n }\n return this.withRightStatus(left, leftWidth, chrome.headerRight, width);\n }\n\n private footerRow(chrome: DoomOverlayChrome, width: number): string {\n const footer = chrome.footerHints?.length\n ? this.hintLegend(chrome.footerHints, width)\n : this.theme.fg(SECONDARY_COLOR, truncateToWidth(chrome.footer, width, ELLIPSIS));\n return this.withRightStatus(footer, visibleWidth(footer), chrome.footerRight, width);\n }\n\n /**\n * Key legend with each key in a filled cap. Every segment sets its own colour\n * so the caps survive: a cap's reset would otherwise strip the surrounding\n * dim from the labels that follow it.\n */\n private hintLegend(hints: readonly (readonly [string, string])[], width: number): string {\n let legend = '';\n let used = 0;\n for (const [key, label] of hints) {\n const segmentWidth = visibleWidth(key) + visibleWidth(label) + HINT_CHROME_COLUMNS;\n if (used + segmentWidth > width) break;\n const cap = this.theme.bg(HINT_CAP_BACKGROUND, this.theme.fg(TEXT_COLOR, ` ${key} `));\n legend += `${legend ? HINT_SEPARATOR : ''}${cap}${this.theme.fg(SECONDARY_COLOR, ` ${label}`)}`;\n used += segmentWidth;\n }\n return legend;\n }\n\n /**\n * Right-aligns a status cluster, dropping it whole when the row cannot spare\n * the columns. A clipped status reads as a stub (`doom-log…`) that carries\n * less than the blank space it costs.\n */\n private withRightStatus(left: string, leftWidth: number, right: string | undefined, width: number): string {\n const statusWidth = right ? visibleWidth(right) : 0;\n if (!right || statusWidth === 0 || leftWidth + ROW_GAP + statusWidth > width) return left;\n return `${left}${' '.repeat(width - leftWidth - statusWidth)}${this.theme.fg(SECONDARY_COLOR, right)}`;\n }\n\n private renderCompact(chrome: DoomOverlayChrome, width: number, height: number): string[] {\n const lines = Array.from({ length: height }, () => '');\n lines[0] = this.theme.bold(this.theme.fg(TITLE_COLOR, chrome.title));\n if (height > 1) lines[height - 1] = this.theme.fg(SECONDARY_COLOR, chrome.footer);\n return lines.map((line) => padLine(fitLine(line, width), width));\n }\n}\n"],"mappings":"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"}
|