@agimon-ai/doompi-workflow 0.0.1-alpha.80 → 0.0.1-alpha.82
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/{src/schemas/apiContracts.cjs → apiContracts.cjs} +11 -9
- package/dist/apiContracts.cjs.map +1 -0
- package/dist/{src/schemas/apiContracts.d.mts.map → apiContracts.d.mts.map} +1 -1
- package/dist/{src/schemas/apiContracts.mjs → apiContracts.mjs} +2 -2
- package/dist/apiContracts.mjs.map +1 -0
- package/dist/extensions/pi.cjs +5311 -24
- package/dist/extensions/pi.cjs.map +1 -1
- package/dist/extensions/pi.d.mts +35 -2
- package/dist/extensions/pi.d.mts.map +1 -1
- package/dist/extensions/pi.mjs +5302 -15
- package/dist/extensions/pi.mjs.map +1 -1
- package/dist/extensions/server.cjs +1521 -37
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.mts +1 -1
- package/dist/extensions/server.d.mts.map +1 -1
- package/dist/extensions/server.mjs +1504 -23
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.d.mts +52 -2
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +1 -1
- package/dist/{src/services/workflowLaunchCommand/index.cjs → workflowLaunchCommand-7y8xg5YF.cjs} +25 -5
- package/dist/workflowLaunchCommand-7y8xg5YF.cjs.map +1 -0
- package/dist/{src/services/workflowLaunchCommand/index.mjs → workflowLaunchCommand-Bhr-PvdD.mjs} +2 -2
- package/dist/workflowLaunchCommand-Bhr-PvdD.mjs.map +1 -0
- package/dist/workflowTerminal-Bj4KKpoA.mjs +148 -0
- package/dist/workflowTerminal-Bj4KKpoA.mjs.map +1 -0
- package/dist/workflowTerminal-WM_cpxIO.cjs +200 -0
- package/dist/workflowTerminal-WM_cpxIO.cjs.map +1 -0
- package/package.json +21 -20
- package/dist/_virtual/_rolldown/runtime.cjs +0 -23
- package/dist/api-contracts.cjs +0 -7
- package/dist/api-contracts.d.cts +0 -2
- package/dist/api-contracts.d.mts +0 -2
- package/dist/api-contracts.mjs +0 -2
- package/dist/extensions/pi.d.cts +0 -6
- package/dist/extensions/pi.d.cts.map +0 -1
- package/dist/extensions/server.d.cts +0 -5
- package/dist/extensions/server.d.cts.map +0 -1
- package/dist/index.d.cts +0 -2
- package/dist/src/constants/workflow.cjs +0 -32
- package/dist/src/constants/workflow.cjs.map +0 -1
- package/dist/src/constants/workflow.mjs +0 -21
- package/dist/src/constants/workflow.mjs.map +0 -1
- package/dist/src/extensions/(backend)/_lib/index.server.cjs +0 -12
- package/dist/src/extensions/(backend)/_lib/index.server.cjs.map +0 -1
- package/dist/src/extensions/(backend)/_lib/index.server.mjs +0 -12
- package/dist/src/extensions/(backend)/_lib/index.server.mjs.map +0 -1
- package/dist/src/extensions/(backend)/api/workflow/route.server.cjs +0 -7
- package/dist/src/extensions/(backend)/api/workflow/route.server.cjs.map +0 -1
- package/dist/src/extensions/(backend)/api/workflow/route.server.mjs +0 -8
- package/dist/src/extensions/(backend)/api/workflow/route.server.mjs.map +0 -1
- package/dist/src/extensions/(backend)/channel/workflow-catalog.server.cjs +0 -7
- package/dist/src/extensions/(backend)/channel/workflow-catalog.server.cjs.map +0 -1
- package/dist/src/extensions/(backend)/channel/workflow-catalog.server.mjs +0 -8
- package/dist/src/extensions/(backend)/channel/workflow-catalog.server.mjs.map +0 -1
- package/dist/src/extensions/(backend)/channel/workflows.server.cjs +0 -7
- package/dist/src/extensions/(backend)/channel/workflows.server.cjs.map +0 -1
- package/dist/src/extensions/(backend)/channel/workflows.server.mjs +0 -8
- package/dist/src/extensions/(backend)/channel/workflows.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.cjs +0 -100
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.mjs +0 -100
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.cjs +0 -11
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.mjs +0 -11
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.cjs +0 -12
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.mjs +0 -12
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.cjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.mjs +0 -8
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs +0 -15
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs +0 -16
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs +0 -17
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs +0 -18
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.cjs +0 -50
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.mjs +0 -47
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.cjs +0 -36
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.mjs +0 -35
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.cjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.mjs +0 -8
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.cjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.mjs +0 -8
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.mjs.map +0 -1
- package/dist/src/schemas/apiContracts.cjs.map +0 -1
- package/dist/src/schemas/apiContracts.d.cts +0 -53
- package/dist/src/schemas/apiContracts.d.cts.map +0 -1
- package/dist/src/schemas/apiContracts.mjs.map +0 -1
- package/dist/src/schemas/workflowPi.cjs +0 -77
- package/dist/src/schemas/workflowPi.cjs.map +0 -1
- package/dist/src/schemas/workflowPi.d.cts +0 -1
- package/dist/src/schemas/workflowPi.d.mts +0 -1
- package/dist/src/schemas/workflowPi.mjs +0 -74
- package/dist/src/schemas/workflowPi.mjs.map +0 -1
- package/dist/src/services/backgroundWork/index.cjs +0 -61
- package/dist/src/services/backgroundWork/index.cjs.map +0 -1
- package/dist/src/services/backgroundWork/index.mjs +0 -61
- package/dist/src/services/backgroundWork/index.mjs.map +0 -1
- package/dist/src/services/piToolBridge/index.cjs +0 -205
- package/dist/src/services/piToolBridge/index.cjs.map +0 -1
- package/dist/src/services/piToolBridge/index.mjs +0 -195
- package/dist/src/services/piToolBridge/index.mjs.map +0 -1
- package/dist/src/services/serverRuntime/index.cjs +0 -387
- package/dist/src/services/serverRuntime/index.cjs.map +0 -1
- package/dist/src/services/serverRuntime/index.mjs +0 -387
- package/dist/src/services/serverRuntime/index.mjs.map +0 -1
- package/dist/src/services/webWorkflowCatalog/index.cjs +0 -53
- package/dist/src/services/webWorkflowCatalog/index.cjs.map +0 -1
- package/dist/src/services/webWorkflowCatalog/index.mjs +0 -52
- package/dist/src/services/webWorkflowCatalog/index.mjs.map +0 -1
- package/dist/src/services/workflowCatalogChannel/index.cjs +0 -74
- package/dist/src/services/workflowCatalogChannel/index.cjs.map +0 -1
- package/dist/src/services/workflowCatalogChannel/index.mjs +0 -74
- package/dist/src/services/workflowCatalogChannel/index.mjs.map +0 -1
- package/dist/src/services/workflowCatalogDeps/index.cjs +0 -25
- package/dist/src/services/workflowCatalogDeps/index.cjs.map +0 -1
- package/dist/src/services/workflowCatalogDeps/index.mjs +0 -25
- package/dist/src/services/workflowCatalogDeps/index.mjs.map +0 -1
- package/dist/src/services/workflowExecution/index.cjs +0 -205
- package/dist/src/services/workflowExecution/index.cjs.map +0 -1
- package/dist/src/services/workflowExecution/index.d.cts +0 -6
- package/dist/src/services/workflowExecution/index.d.mts +0 -6
- package/dist/src/services/workflowExecution/index.mjs +0 -200
- package/dist/src/services/workflowExecution/index.mjs.map +0 -1
- package/dist/src/services/workflowFence/index.cjs +0 -170
- package/dist/src/services/workflowFence/index.cjs.map +0 -1
- package/dist/src/services/workflowFence/index.mjs +0 -166
- package/dist/src/services/workflowFence/index.mjs.map +0 -1
- package/dist/src/services/workflowHubApi/index.cjs +0 -415
- package/dist/src/services/workflowHubApi/index.cjs.map +0 -1
- package/dist/src/services/workflowHubApi/index.mjs +0 -411
- package/dist/src/services/workflowHubApi/index.mjs.map +0 -1
- package/dist/src/services/workflowLaunchCommand/index.cjs.map +0 -1
- package/dist/src/services/workflowLaunchCommand/index.d.cts +0 -52
- package/dist/src/services/workflowLaunchCommand/index.d.cts.map +0 -1
- package/dist/src/services/workflowLaunchCommand/index.d.mts +0 -52
- package/dist/src/services/workflowLaunchCommand/index.d.mts.map +0 -1
- package/dist/src/services/workflowLaunchCommand/index.mjs.map +0 -1
- package/dist/src/services/workflowLauncher/index.cjs +0 -181
- package/dist/src/services/workflowLauncher/index.cjs.map +0 -1
- package/dist/src/services/workflowLauncher/index.mjs +0 -177
- package/dist/src/services/workflowLauncher/index.mjs.map +0 -1
- package/dist/src/services/workflowNarration/index.cjs +0 -19
- package/dist/src/services/workflowNarration/index.cjs.map +0 -1
- package/dist/src/services/workflowNarration/index.mjs +0 -19
- package/dist/src/services/workflowNarration/index.mjs.map +0 -1
- package/dist/src/services/workflowResource/index.cjs +0 -27
- package/dist/src/services/workflowResource/index.cjs.map +0 -1
- package/dist/src/services/workflowResource/index.mjs +0 -24
- package/dist/src/services/workflowResource/index.mjs.map +0 -1
- package/dist/src/services/workflowRuns/index.cjs +0 -333
- package/dist/src/services/workflowRuns/index.cjs.map +0 -1
- package/dist/src/services/workflowRuns/index.mjs +0 -319
- package/dist/src/services/workflowRuns/index.mjs.map +0 -1
- package/dist/src/services/workflowTerminal/index.cjs +0 -69
- package/dist/src/services/workflowTerminal/index.cjs.map +0 -1
- package/dist/src/services/workflowTerminal/index.mjs +0 -69
- package/dist/src/services/workflowTerminal/index.mjs.map +0 -1
- package/dist/src/services/workflowTools/index.cjs +0 -221
- package/dist/src/services/workflowTools/index.cjs.map +0 -1
- package/dist/src/services/workflowTools/index.mjs +0 -221
- package/dist/src/services/workflowTools/index.mjs.map +0 -1
- package/dist/src/services/workflowWatcher/index.cjs +0 -78
- package/dist/src/services/workflowWatcher/index.cjs.map +0 -1
- package/dist/src/services/workflowWatcher/index.mjs +0 -74
- package/dist/src/services/workflowWatcher/index.mjs.map +0 -1
- package/dist/src/services/workflowsHubChannel/index.cjs +0 -58
- package/dist/src/services/workflowsHubChannel/index.cjs.map +0 -1
- package/dist/src/services/workflowsHubChannel/index.mjs +0 -58
- package/dist/src/services/workflowsHubChannel/index.mjs.map +0 -1
- package/dist/src/tui/leader.cjs +0 -84
- package/dist/src/tui/leader.cjs.map +0 -1
- package/dist/src/tui/leader.mjs +0 -83
- package/dist/src/tui/leader.mjs.map +0 -1
- package/dist/src/tui/workflow/doomOverlay.cjs +0 -159
- package/dist/src/tui/workflow/doomOverlay.cjs.map +0 -1
- package/dist/src/tui/workflow/doomOverlay.mjs +0 -157
- package/dist/src/tui/workflow/doomOverlay.mjs.map +0 -1
- package/dist/src/tui/workflow/overlayText.cjs +0 -83
- package/dist/src/tui/workflow/overlayText.cjs.map +0 -1
- package/dist/src/tui/workflow/overlayText.mjs +0 -78
- package/dist/src/tui/workflow/overlayText.mjs.map +0 -1
- package/dist/src/tui/workflow/rendering.cjs +0 -22
- package/dist/src/tui/workflow/rendering.cjs.map +0 -1
- package/dist/src/tui/workflow/rendering.mjs +0 -20
- package/dist/src/tui/workflow/rendering.mjs.map +0 -1
- package/dist/src/tui/workflow/workflowCatalog.cjs +0 -336
- package/dist/src/tui/workflow/workflowCatalog.cjs.map +0 -1
- package/dist/src/tui/workflow/workflowCatalog.mjs +0 -333
- package/dist/src/tui/workflow/workflowCatalog.mjs.map +0 -1
- package/dist/src/tui/workflow/workflowFinishedMessage.cjs +0 -50
- package/dist/src/tui/workflow/workflowFinishedMessage.cjs.map +0 -1
- package/dist/src/tui/workflow/workflowFinishedMessage.mjs +0 -47
- package/dist/src/tui/workflow/workflowFinishedMessage.mjs.map +0 -1
- package/dist/src/tui/workflow/workflowInspector.cjs +0 -276
- package/dist/src/tui/workflow/workflowInspector.cjs.map +0 -1
- package/dist/src/tui/workflow/workflowInspector.mjs +0 -276
- package/dist/src/tui/workflow/workflowInspector.mjs.map +0 -1
- package/dist/src/tui/workflow/workflowOverlay.cjs +0 -126
- package/dist/src/tui/workflow/workflowOverlay.cjs.map +0 -1
- package/dist/src/tui/workflow/workflowOverlay.mjs +0 -125
- package/dist/src/tui/workflow/workflowOverlay.mjs.map +0 -1
- package/dist/src/tui/workflow/workflowPicker.cjs +0 -138
- package/dist/src/tui/workflow/workflowPicker.cjs.map +0 -1
- package/dist/src/tui/workflow/workflowPicker.mjs +0 -136
- package/dist/src/tui/workflow/workflowPicker.mjs.map +0 -1
- package/dist/src/tui/workflow/workflowProgressOverlay.cjs +0 -197
- package/dist/src/tui/workflow/workflowProgressOverlay.cjs.map +0 -1
- package/dist/src/tui/workflow/workflowProgressOverlay.mjs +0 -192
- package/dist/src/tui/workflow/workflowProgressOverlay.mjs.map +0 -1
- package/dist/src/tui/workflow/workflowPrompt.cjs +0 -142
- package/dist/src/tui/workflow/workflowPrompt.cjs.map +0 -1
- package/dist/src/tui/workflow/workflowPrompt.mjs +0 -139
- package/dist/src/tui/workflow/workflowPrompt.mjs.map +0 -1
- package/dist/src/tui/workflow/workflowRunPanel.cjs +0 -95
- package/dist/src/tui/workflow/workflowRunPanel.cjs.map +0 -1
- package/dist/src/tui/workflow/workflowRunPanel.mjs +0 -94
- package/dist/src/tui/workflow/workflowRunPanel.mjs.map +0 -1
- package/dist/src/tui/workflow/workflowStatusRow.cjs +0 -20
- package/dist/src/tui/workflow/workflowStatusRow.cjs.map +0 -1
- package/dist/src/tui/workflow/workflowStatusRow.mjs +0 -20
- package/dist/src/tui/workflow/workflowStatusRow.mjs.map +0 -1
- package/dist/src/tui/workflow/workflowStepMessage.cjs +0 -32
- package/dist/src/tui/workflow/workflowStepMessage.cjs.map +0 -1
- package/dist/src/tui/workflow/workflowStepMessage.mjs +0 -31
- package/dist/src/tui/workflow/workflowStepMessage.mjs.map +0 -1
- package/dist/src/tui/workflow/workflowToolRender.cjs +0 -491
- package/dist/src/tui/workflow/workflowToolRender.cjs.map +0 -1
- package/dist/src/tui/workflow/workflowToolRender.mjs +0 -490
- package/dist/src/tui/workflow/workflowToolRender.mjs.map +0 -1
- package/dist/src/tui/workflowRuntime.cjs +0 -1934
- package/dist/src/tui/workflowRuntime.cjs.map +0 -1
- package/dist/src/tui/workflowRuntime.d.cts +0 -33
- package/dist/src/tui/workflowRuntime.d.cts.map +0 -1
- package/dist/src/tui/workflowRuntime.d.mts +0 -33
- package/dist/src/tui/workflowRuntime.d.mts.map +0 -1
- package/dist/src/tui/workflowRuntime.mjs +0 -1930
- package/dist/src/tui/workflowRuntime.mjs.map +0 -1
- package/dist/src/types/apiRoutes.cjs +0 -82
- package/dist/src/types/apiRoutes.cjs.map +0 -1
- package/dist/src/types/apiRoutes.mjs +0 -80
- package/dist/src/types/apiRoutes.mjs.map +0 -1
- package/dist/src/types/webWorkflowTerminal.cjs +0 -23
- package/dist/src/types/webWorkflowTerminal.cjs.map +0 -1
- package/dist/src/types/webWorkflowTerminal.mjs +0 -22
- package/dist/src/types/webWorkflowTerminal.mjs.map +0 -1
- package/dist/src/types/webWorkflows.cjs +0 -8
- package/dist/src/types/webWorkflows.cjs.map +0 -1
- package/dist/src/types/webWorkflows.mjs +0 -7
- package/dist/src/types/webWorkflows.mjs.map +0 -1
- /package/dist/{src/schemas/apiContracts.d.mts → apiContracts.d.mts} +0 -0
|
@@ -2,23 +2,1510 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
let
|
|
21
|
-
let
|
|
5
|
+
const require_workflowTerminal = require("../workflowTerminal-WM_cpxIO.cjs");
|
|
6
|
+
const require_workflowLaunchCommand = require("../workflowLaunchCommand-7y8xg5YF.cjs");
|
|
7
|
+
let _agimon_ai_doompi_core_extensionFile = require("@agimon-ai/doompi-core/extensionFile");
|
|
8
|
+
let node_fs = require("node:fs");
|
|
9
|
+
node_fs = require_workflowTerminal.__toESM(node_fs, 1);
|
|
10
|
+
let node_path = require("node:path");
|
|
11
|
+
node_path = require_workflowTerminal.__toESM(node_path, 1);
|
|
12
|
+
let _agimon_ai_workflow_mcp = require("@agimon-ai/workflow-mcp");
|
|
13
|
+
let zod = require("zod");
|
|
14
|
+
let node_crypto = require("node:crypto");
|
|
15
|
+
let _agimon_ai_doompi_minor_mode = require("@agimon-ai/doompi-minor-mode");
|
|
16
|
+
let _agimon_ai_doompi_core_serverFacet = require("@agimon-ai/doompi-core/serverFacet");
|
|
17
|
+
let node_os = require("node:os");
|
|
18
|
+
node_os = require_workflowTerminal.__toESM(node_os, 1);
|
|
19
|
+
let node_stream = require("node:stream");
|
|
20
|
+
let hono = require("hono");
|
|
21
|
+
let hono_streaming = require("hono/streaming");
|
|
22
|
+
let _agimon_ai_doompi_core_web = require("@agimon-ai/doompi-core/web");
|
|
23
|
+
//#region src/services/webWorkflowCatalog/index.ts
|
|
24
|
+
function unchanged(left, right) {
|
|
25
|
+
return left !== void 0 && right !== void 0 && left.size === right.size && left.modifiedAt === right.modifiedAt;
|
|
26
|
+
}
|
|
27
|
+
function createWorkflowCatalogReader(deps) {
|
|
28
|
+
const cache = /* @__PURE__ */ new Map();
|
|
29
|
+
const detailFor = (path) => {
|
|
30
|
+
const stamp = deps.stamp(path);
|
|
31
|
+
const cached = cache.get(path);
|
|
32
|
+
if (cached && unchanged(cached.stamp, stamp)) return cached.detail;
|
|
33
|
+
const detail = deps.summarize(path);
|
|
34
|
+
if (stamp !== void 0) cache.set(path, {
|
|
35
|
+
stamp,
|
|
36
|
+
detail
|
|
37
|
+
});
|
|
38
|
+
return detail;
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
async read(directory) {
|
|
42
|
+
return (await deps.list(directory)).map((entry) => {
|
|
43
|
+
const detail = detailFor(entry.path);
|
|
44
|
+
return {
|
|
45
|
+
path: entry.path,
|
|
46
|
+
relativePath: entry.relativePath,
|
|
47
|
+
name: entry.name === "" ? entry.relativePath : entry.name,
|
|
48
|
+
description: entry.description,
|
|
49
|
+
tags: entry.tags,
|
|
50
|
+
triggers: detail.triggers,
|
|
51
|
+
inputs: detail.inputs,
|
|
52
|
+
jobs: detail.jobs,
|
|
53
|
+
artifacts: detail.artifacts,
|
|
54
|
+
...detail.runners === void 0 ? {} : { runners: detail.runners },
|
|
55
|
+
...detail.error === void 0 ? {} : { error: detail.error }
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
forget(keep) {
|
|
60
|
+
for (const path of cache.keys()) if (!keep.has(path)) cache.delete(path);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** The launchable rows first, then the ones that would not parse, name ordered. */
|
|
65
|
+
function presentWorkflowCatalog(entries) {
|
|
66
|
+
return [...entries].sort((left, right) => {
|
|
67
|
+
if (left.error === void 0 !== (right.error === void 0)) return left.error === void 0 ? -1 : 1;
|
|
68
|
+
return left.name.localeCompare(right.name);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/services/workflowCatalogDeps/index.ts
|
|
73
|
+
/** Connect the pure catalog projection service to the workflow engine and filesystem. */
|
|
74
|
+
function defaultCatalogDeps() {
|
|
75
|
+
return {
|
|
76
|
+
list: (directory) => (0, _agimon_ai_workflow_mcp.readWorkflowCatalog)(directory),
|
|
77
|
+
summarize: (workflowPath) => (0, _agimon_ai_workflow_mcp.summarizeWorkflow)(workflowPath),
|
|
78
|
+
stamp: (workflowPath) => {
|
|
79
|
+
try {
|
|
80
|
+
const stats = (0, node_fs.statSync)(workflowPath);
|
|
81
|
+
return {
|
|
82
|
+
size: stats.size,
|
|
83
|
+
modifiedAt: stats.mtimeMs
|
|
84
|
+
};
|
|
85
|
+
} catch {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/services/workflowRuns/index.ts
|
|
93
|
+
/**
|
|
94
|
+
* MIRRORS @agimon-ai/workflow-mcp's on-disk registry
|
|
95
|
+
* (src/services/WorkflowRegistryService.ts and WorkflowProgressService.ts in
|
|
96
|
+
* that package). The engine keeps one directory per run under
|
|
97
|
+
* `<home>/workspaces/<workspace>/<stage>/<runKey>/` holding a `run.json`
|
|
98
|
+
* record and an append-only `progress.ndjson` job/step log; the hub only ever
|
|
99
|
+
* reads them. The derivation is duplicated rather than imported because
|
|
100
|
+
* doompi-web must not depend on the engine at runtime; the unit suite pins
|
|
101
|
+
* this mirror against the package's published types.
|
|
102
|
+
*/
|
|
103
|
+
const DEFAULT_WORKFLOW_HOME_DIR_NAME = ".workflow-mcp";
|
|
104
|
+
const WORKSPACES_DIR_NAME = "workspaces";
|
|
105
|
+
const RUN_RECORD_FILE_NAME = "run.json";
|
|
106
|
+
const PROGRESS_FILE_NAME = "progress.ndjson";
|
|
107
|
+
const WORKFLOW_STAGES = [
|
|
108
|
+
"running",
|
|
109
|
+
"completed",
|
|
110
|
+
"error"
|
|
111
|
+
];
|
|
112
|
+
/**
|
|
113
|
+
* Errored runs stay a day, which is how long recovery has to act on them.
|
|
114
|
+
*
|
|
115
|
+
* Finished runs have no retention of their own: a session keeps every run it
|
|
116
|
+
* launched, grouped by outcome, for as long as the session lives. A run leaves
|
|
117
|
+
* the view when the engine prunes its registry directory, not on a timer here,
|
|
118
|
+
* because "what did this session run today" is a question asked long after the
|
|
119
|
+
* run settled.
|
|
120
|
+
*/
|
|
121
|
+
const WORKFLOW_ERROR_RETENTION_MS = 864e5;
|
|
122
|
+
/** The env key doompi-workflow stamps on runs it launches; ties a run to a Pi session. */
|
|
123
|
+
const PI_SESSION_ENV = "PI_SESSION_ID";
|
|
124
|
+
const PROGRESS_STATES = /* @__PURE__ */ new Set([
|
|
125
|
+
"running",
|
|
126
|
+
"completed",
|
|
127
|
+
"skipped",
|
|
128
|
+
"failed",
|
|
129
|
+
"pause_requested",
|
|
130
|
+
"paused",
|
|
131
|
+
"resumed"
|
|
132
|
+
]);
|
|
133
|
+
const OUTCOMES = /* @__PURE__ */ new Set([
|
|
134
|
+
"success",
|
|
135
|
+
"skipped",
|
|
136
|
+
"failed",
|
|
137
|
+
"interrupted"
|
|
138
|
+
]);
|
|
139
|
+
const EXECUTION_STATES = /* @__PURE__ */ new Set([
|
|
140
|
+
"running",
|
|
141
|
+
"pause_requested",
|
|
142
|
+
"paused",
|
|
143
|
+
"resume_requested"
|
|
144
|
+
]);
|
|
145
|
+
const STEP_TERMINAL_STATES = /* @__PURE__ */ new Set([
|
|
146
|
+
"completed",
|
|
147
|
+
"skipped",
|
|
148
|
+
"failed"
|
|
149
|
+
]);
|
|
150
|
+
/** The engine records its pre:/post: blocks under these reserved pseudo-job names. */
|
|
151
|
+
const PHASE_JOB_PRE = "pre";
|
|
152
|
+
const PHASE_JOB_POST = "post";
|
|
153
|
+
const ANSI_ESCAPE_PATTERN = /\u001b\[[0-9;]*[A-Za-z]/g;
|
|
154
|
+
/** Where workflow-mcp keeps its registry, mirroring the engine's own resolution. */
|
|
155
|
+
function resolveWorkflowHome(input) {
|
|
156
|
+
return (0, node_path.resolve)(input.envValue !== void 0 && input.envValue !== "" ? input.envValue : (0, node_path.resolve)(input.homeDir, DEFAULT_WORKFLOW_HOME_DIR_NAME));
|
|
157
|
+
}
|
|
158
|
+
function isRecord(value) {
|
|
159
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
160
|
+
}
|
|
161
|
+
function asOptionalString(value) {
|
|
162
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
163
|
+
}
|
|
164
|
+
function asOptionalNumber(value) {
|
|
165
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
166
|
+
}
|
|
167
|
+
function stripAnsi(text) {
|
|
168
|
+
return text.replace(ANSI_ESCAPE_PATTERN, "").trim();
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Validates one run.json into the wire shape plus scoping facts.
|
|
172
|
+
*
|
|
173
|
+
* Returns undefined for anything unreadable or a foreign format. The record
|
|
174
|
+
* is trusted for its own stage: the registry rewrites it when a run moves
|
|
175
|
+
* between stage directories.
|
|
176
|
+
*/
|
|
177
|
+
function parseWorkflowRunRecord(raw) {
|
|
178
|
+
let parsed;
|
|
179
|
+
try {
|
|
180
|
+
parsed = JSON.parse(raw);
|
|
181
|
+
} catch {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (!isRecord(parsed)) return void 0;
|
|
185
|
+
const runKey = asOptionalString(parsed.runKey);
|
|
186
|
+
const workspace = asOptionalString(parsed.workspace);
|
|
187
|
+
const workflowPath = asOptionalString(parsed.workflowPath);
|
|
188
|
+
const startedAt = asOptionalString(parsed.startedAt);
|
|
189
|
+
const stage = asOptionalString(parsed.stage);
|
|
190
|
+
if (!runKey || !workspace || !workflowPath || !startedAt) return void 0;
|
|
191
|
+
if (stage === void 0 || !WORKFLOW_STAGES.includes(stage)) return void 0;
|
|
192
|
+
const outcome = asOptionalString(parsed.outcome);
|
|
193
|
+
const executionState = asOptionalString(parsed.executionState);
|
|
194
|
+
const rawError = asOptionalString(parsed.errorMessage);
|
|
195
|
+
const env = isRecord(parsed.env) ? parsed.env : void 0;
|
|
196
|
+
const view = {
|
|
197
|
+
runKey,
|
|
198
|
+
workspace,
|
|
199
|
+
displayName: asOptionalString(parsed.displayName) ?? runKey,
|
|
200
|
+
...asOptionalString(parsed.workflowName) === void 0 ? {} : { workflowName: asOptionalString(parsed.workflowName) },
|
|
201
|
+
workflowPath,
|
|
202
|
+
stage,
|
|
203
|
+
...outcome !== void 0 && OUTCOMES.has(outcome) ? { outcome } : {},
|
|
204
|
+
...executionState !== void 0 && EXECUTION_STATES.has(executionState) ? { executionState } : {},
|
|
205
|
+
...asOptionalString(parsed.prompt) === void 0 ? {} : { prompt: asOptionalString(parsed.prompt) },
|
|
206
|
+
startedAt,
|
|
207
|
+
...asOptionalString(parsed.finishedAt) === void 0 ? {} : { finishedAt: asOptionalString(parsed.finishedAt) },
|
|
208
|
+
...rawError === void 0 ? {} : { errorMessage: stripAnsi(rawError) },
|
|
209
|
+
...asOptionalString(parsed.failedJob) === void 0 ? {} : { failedJob: asOptionalString(parsed.failedJob) },
|
|
210
|
+
...parsed.stale === true ? { stale: true } : {},
|
|
211
|
+
...asOptionalString(parsed.staleReason) === void 0 ? {} : { staleReason: asOptionalString(parsed.staleReason) },
|
|
212
|
+
...asOptionalString(parsed.worktreeBranch) === void 0 ? {} : { worktreeBranch: asOptionalString(parsed.worktreeBranch) },
|
|
213
|
+
jobs: []
|
|
214
|
+
};
|
|
215
|
+
const piSessionId = env === void 0 ? void 0 : asOptionalString(env[PI_SESSION_ENV]);
|
|
216
|
+
return {
|
|
217
|
+
view,
|
|
218
|
+
...piSessionId === void 0 ? {} : { piSessionId }
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Parses the append-only progress log. Malformed lines are skipped rather
|
|
223
|
+
* than failing the file: a reader routinely catches a torn final line
|
|
224
|
+
* mid-append.
|
|
225
|
+
*/
|
|
226
|
+
function parseWorkflowProgress(raw) {
|
|
227
|
+
const events = [];
|
|
228
|
+
for (const line of raw.split("\n")) {
|
|
229
|
+
const trimmed = line.trim();
|
|
230
|
+
if (trimmed === "") continue;
|
|
231
|
+
let parsed;
|
|
232
|
+
try {
|
|
233
|
+
parsed = JSON.parse(trimmed);
|
|
234
|
+
} catch {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (!isRecord(parsed)) continue;
|
|
238
|
+
const type = parsed.type;
|
|
239
|
+
const status = asOptionalString(parsed.status);
|
|
240
|
+
const job = asOptionalString(parsed.job);
|
|
241
|
+
const at = asOptionalString(parsed.at);
|
|
242
|
+
if (type !== "job" && type !== "step" || !job || !at) continue;
|
|
243
|
+
if (status === void 0 || !PROGRESS_STATES.has(status)) continue;
|
|
244
|
+
const step = asOptionalString(parsed.step);
|
|
245
|
+
const index = asOptionalNumber(parsed.index);
|
|
246
|
+
const total = asOptionalNumber(parsed.total);
|
|
247
|
+
const reason = asOptionalString(parsed.reason);
|
|
248
|
+
events.push({
|
|
249
|
+
type,
|
|
250
|
+
status,
|
|
251
|
+
job,
|
|
252
|
+
...step === void 0 ? {} : { step },
|
|
253
|
+
...index === void 0 ? {} : { index },
|
|
254
|
+
...total === void 0 ? {} : { total },
|
|
255
|
+
...reason === void 0 ? {} : { reason },
|
|
256
|
+
at
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
return events;
|
|
260
|
+
}
|
|
261
|
+
function jobPhase(name) {
|
|
262
|
+
if (name === PHASE_JOB_PRE) return PHASE_JOB_PRE;
|
|
263
|
+
if (name === PHASE_JOB_POST) return PHASE_JOB_POST;
|
|
264
|
+
return "job";
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Folds the event log into the current job tree; later events win, so a job
|
|
268
|
+
* that started and later failed reads as failed. Jobs and steps keep the
|
|
269
|
+
* order of their first appearance.
|
|
270
|
+
*/
|
|
271
|
+
function foldWorkflowProgress(events) {
|
|
272
|
+
const jobs = [];
|
|
273
|
+
const jobByName = /* @__PURE__ */ new Map();
|
|
274
|
+
for (const event of events) {
|
|
275
|
+
let job = jobByName.get(event.job);
|
|
276
|
+
if (job === void 0) {
|
|
277
|
+
job = {
|
|
278
|
+
name: event.job,
|
|
279
|
+
phase: jobPhase(event.job),
|
|
280
|
+
status: event.status,
|
|
281
|
+
steps: []
|
|
282
|
+
};
|
|
283
|
+
jobByName.set(event.job, job);
|
|
284
|
+
jobs.push(job);
|
|
285
|
+
}
|
|
286
|
+
if (event.type === "job") {
|
|
287
|
+
job.status = event.status;
|
|
288
|
+
if (event.reason !== void 0) job.reason = event.reason;
|
|
289
|
+
if (event.index !== void 0) job.index = event.index;
|
|
290
|
+
if (event.total !== void 0) job.total = event.total;
|
|
291
|
+
if (event.status === "running" && job.startedAt === void 0) job.startedAt = event.at;
|
|
292
|
+
if (STEP_TERMINAL_STATES.has(event.status)) job.endedAt = event.at;
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
if (event.step === void 0) continue;
|
|
296
|
+
let step = job.steps.find((candidate) => candidate.name === event.step);
|
|
297
|
+
if (step === void 0) {
|
|
298
|
+
step = {
|
|
299
|
+
name: event.step,
|
|
300
|
+
status: event.status
|
|
301
|
+
};
|
|
302
|
+
job.steps.push(step);
|
|
303
|
+
}
|
|
304
|
+
step.status = event.status;
|
|
305
|
+
if (event.reason !== void 0) step.reason = event.reason;
|
|
306
|
+
if (event.status === "running" && step.startedAt === void 0) step.startedAt = event.at;
|
|
307
|
+
if (STEP_TERMINAL_STATES.has(event.status)) step.endedAt = event.at;
|
|
308
|
+
}
|
|
309
|
+
return jobs;
|
|
310
|
+
}
|
|
311
|
+
const ACTIVE_PROGRESS_STATES = /* @__PURE__ */ new Set([
|
|
312
|
+
"running",
|
|
313
|
+
"pause_requested",
|
|
314
|
+
"paused",
|
|
315
|
+
"resumed"
|
|
316
|
+
]);
|
|
317
|
+
/** The job and step a run is on right now, for the NOW breadcrumb. */
|
|
318
|
+
function workflowPosition(jobs) {
|
|
319
|
+
for (let jobIndex = jobs.length - 1; jobIndex >= 0; jobIndex -= 1) {
|
|
320
|
+
const job = jobs[jobIndex];
|
|
321
|
+
if (!ACTIVE_PROGRESS_STATES.has(job.status)) continue;
|
|
322
|
+
for (let stepIndex = job.steps.length - 1; stepIndex >= 0; stepIndex -= 1) {
|
|
323
|
+
const step = job.steps[stepIndex];
|
|
324
|
+
if (ACTIVE_PROGRESS_STATES.has(step.status)) return {
|
|
325
|
+
job: job.name,
|
|
326
|
+
step: step.name,
|
|
327
|
+
...job.index === void 0 ? {} : { index: job.index },
|
|
328
|
+
...job.total === void 0 ? {} : { total: job.total }
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
job: job.name,
|
|
333
|
+
...job.index === void 0 ? {} : { index: job.index },
|
|
334
|
+
...job.total === void 0 ? {} : { total: job.total }
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
/** The finished view: record fields plus the folded job tree and position. */
|
|
339
|
+
function completeWorkflowRunView(view, jobs) {
|
|
340
|
+
const position = view.stage === "running" ? workflowPosition(jobs) : void 0;
|
|
341
|
+
return {
|
|
342
|
+
...view,
|
|
343
|
+
jobs,
|
|
344
|
+
...position === void 0 ? {} : { position }
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Whether a run belongs on a session's workflow tab: launched by that Pi
|
|
349
|
+
* session, which is the same env test doompi-workflow's isSessionRun applies.
|
|
350
|
+
*
|
|
351
|
+
* The registry is one directory under $HOME shared by every repository and
|
|
352
|
+
* every Pi session on the machine, so repository proximity is not ownership.
|
|
353
|
+
* Scoping on it as well let two sessions open in one repo read each other's
|
|
354
|
+
* history, and kept a dead session's runs on the board of every session that
|
|
355
|
+
* replaced it. Fails closed on an unstamped record, which is what a launch
|
|
356
|
+
* from the CLI rather than from a session leaves behind.
|
|
357
|
+
*/
|
|
358
|
+
function runBelongsToSession(run, sessionId) {
|
|
359
|
+
return run.piSessionId !== void 0 && run.piSessionId === sessionId;
|
|
360
|
+
}
|
|
361
|
+
function parseTime(value) {
|
|
362
|
+
if (value === void 0) return 0;
|
|
363
|
+
const time = Date.parse(value);
|
|
364
|
+
return Number.isFinite(time) ? time : 0;
|
|
365
|
+
}
|
|
366
|
+
const STAGE_ORDER = {
|
|
367
|
+
running: 0,
|
|
368
|
+
error: 1,
|
|
369
|
+
completed: 2
|
|
370
|
+
};
|
|
371
|
+
/**
|
|
372
|
+
* Whether a run still belongs in the view.
|
|
373
|
+
*
|
|
374
|
+
* Only errored runs age out here, and slowly: everything else a session
|
|
375
|
+
* started stays until the engine forgets the run itself.
|
|
376
|
+
*/
|
|
377
|
+
function withinRetention(run, now) {
|
|
378
|
+
if (run.stage !== "error") return true;
|
|
379
|
+
return now - (parseTime(run.finishedAt) || parseTime(run.startedAt)) < WORKFLOW_ERROR_RETENTION_MS;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* When a run last moved, which is what orders it within its group.
|
|
383
|
+
*
|
|
384
|
+
* A running run has only its start; a settled one is ordered by when it
|
|
385
|
+
* settled, because a list kept for the whole session is read as a history and
|
|
386
|
+
* two runs started together can finish an hour apart.
|
|
387
|
+
*/
|
|
388
|
+
function lastMovedAt(run) {
|
|
389
|
+
return run.stage === "running" ? parseTime(run.startedAt) : parseTime(run.finishedAt) || parseTime(run.startedAt);
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Running runs first, then errored (recovery acts on them), then finished;
|
|
393
|
+
* newest first within a group, and each group capped on its own.
|
|
394
|
+
*/
|
|
395
|
+
function presentWorkflowRuns(runs, now) {
|
|
396
|
+
const groups = /* @__PURE__ */ new Map();
|
|
397
|
+
for (const run of runs) {
|
|
398
|
+
if (!withinRetention(run, now)) continue;
|
|
399
|
+
const group = groups.get(run.stage);
|
|
400
|
+
if (group) group.push(run);
|
|
401
|
+
else groups.set(run.stage, [run]);
|
|
402
|
+
}
|
|
403
|
+
return [...groups.entries()].sort(([left], [right]) => STAGE_ORDER[left] - STAGE_ORDER[right]).flatMap(([, group]) => group.sort((left, right) => lastMovedAt(right) - lastMovedAt(left)).slice(0, 24));
|
|
404
|
+
}
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region src/services/workflowWatcher/index.ts
|
|
407
|
+
/**
|
|
408
|
+
* Read the durable workflow registry once.
|
|
409
|
+
*
|
|
410
|
+
* The registry is an initial snapshot only. Live delivery belongs to the
|
|
411
|
+
* session lifecycle and is routed through the host-owned direct event bus.
|
|
412
|
+
*/
|
|
413
|
+
function readWorkflowRuns(options = {}) {
|
|
414
|
+
const environment = options.environment;
|
|
415
|
+
const homeDir = options.homeDir ?? resolveWorkflowHome({
|
|
416
|
+
envValue: environment?.["WORKFLOW_MCP_HOME"],
|
|
417
|
+
homeDir: node_os.default.homedir()
|
|
418
|
+
});
|
|
419
|
+
const workspacesDir = node_path.default.join(homeDir, WORKSPACES_DIR_NAME);
|
|
420
|
+
const recordCache = /* @__PURE__ */ new Map();
|
|
421
|
+
const progressCache = /* @__PURE__ */ new Map();
|
|
422
|
+
const cachedParse = (cache, filePath, parse, empty) => {
|
|
423
|
+
let stat;
|
|
424
|
+
try {
|
|
425
|
+
stat = node_fs.default.statSync(filePath);
|
|
426
|
+
} catch {
|
|
427
|
+
cache.delete(filePath);
|
|
428
|
+
return empty;
|
|
429
|
+
}
|
|
430
|
+
const cached = cache.get(filePath);
|
|
431
|
+
if (cached && cached.size === stat.size && cached.mtimeMs === stat.mtimeMs) return cached.value;
|
|
432
|
+
let raw;
|
|
433
|
+
try {
|
|
434
|
+
raw = node_fs.default.readFileSync(filePath, "utf8");
|
|
435
|
+
} catch {
|
|
436
|
+
cache.delete(filePath);
|
|
437
|
+
return empty;
|
|
438
|
+
}
|
|
439
|
+
const value = parse(raw);
|
|
440
|
+
cache.set(filePath, {
|
|
441
|
+
size: stat.size,
|
|
442
|
+
mtimeMs: stat.mtimeMs,
|
|
443
|
+
value
|
|
444
|
+
});
|
|
445
|
+
return value;
|
|
446
|
+
};
|
|
447
|
+
const listDir = (directory) => {
|
|
448
|
+
try {
|
|
449
|
+
return node_fs.default.readdirSync(directory).sort();
|
|
450
|
+
} catch {
|
|
451
|
+
return [];
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
const runs = [];
|
|
455
|
+
for (const workspace of listDir(workspacesDir)) for (const stage of WORKFLOW_STAGES) {
|
|
456
|
+
const stageDir = node_path.default.join(workspacesDir, workspace, stage);
|
|
457
|
+
for (const runKey of listDir(stageDir)) {
|
|
458
|
+
const runDir = node_path.default.join(stageDir, runKey);
|
|
459
|
+
const recordPath = node_path.default.join(runDir, RUN_RECORD_FILE_NAME);
|
|
460
|
+
const progressPath = node_path.default.join(runDir, PROGRESS_FILE_NAME);
|
|
461
|
+
const parsed = cachedParse(recordCache, recordPath, parseWorkflowRunRecord, void 0);
|
|
462
|
+
if (parsed === void 0) continue;
|
|
463
|
+
const jobs = cachedParse(progressCache, progressPath, (raw) => foldWorkflowProgress(parseWorkflowProgress(raw)), []);
|
|
464
|
+
runs.push({
|
|
465
|
+
...parsed,
|
|
466
|
+
view: completeWorkflowRunView(parsed.view, jobs)
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return runs;
|
|
471
|
+
}
|
|
472
|
+
//#endregion
|
|
473
|
+
//#region src/types/webWorkflows.ts
|
|
474
|
+
const WORKFLOW_RUNS_TYPE = "workflow_runs";
|
|
475
|
+
const WORKFLOW_CATALOG_TYPE = "workflow_catalog";
|
|
476
|
+
//#endregion
|
|
477
|
+
//#region src/services/serverRuntime/index.ts
|
|
478
|
+
const SOURCE = "@agimon-ai/doompi-workflow";
|
|
479
|
+
const WORKFLOW_MODE_ID = "workflow";
|
|
480
|
+
const LIST_TOOL = "list_workflows";
|
|
481
|
+
const LAUNCH_TOOL = "launch_workflow";
|
|
482
|
+
const RUN_TOOL = "workflow_run";
|
|
483
|
+
function callResult(value) {
|
|
484
|
+
const content = [];
|
|
485
|
+
if (typeof value === "object" && value !== null && "content" in value && Array.isArray(value.content)) for (const item of value.content) {
|
|
486
|
+
if (typeof item !== "object" || item === null || !("type" in item)) continue;
|
|
487
|
+
const record = item;
|
|
488
|
+
if (record.type === "text" && typeof record.text === "string") content.push({
|
|
489
|
+
type: "text",
|
|
490
|
+
text: record.text
|
|
491
|
+
});
|
|
492
|
+
else if (record.type === "image" && typeof record.data === "string" && typeof record.mimeType === "string") content.push({
|
|
493
|
+
type: "image",
|
|
494
|
+
data: record.data,
|
|
495
|
+
mimeType: record.mimeType
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
if (content.length === 0) content.push({
|
|
499
|
+
type: "text",
|
|
500
|
+
text: JSON.stringify(value, null, 2)
|
|
501
|
+
});
|
|
502
|
+
return {
|
|
503
|
+
content,
|
|
504
|
+
details: value
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
function createWorkflowServerRuntime(host, serverHost) {
|
|
508
|
+
if (serverHost.context.directEvents === void 0) throw new Error("Workflow headless facet requires the session direct event bus.");
|
|
509
|
+
const directEvents = serverHost.context.directEvents;
|
|
510
|
+
let runProvider;
|
|
511
|
+
const catalogReader = createWorkflowCatalogReader(defaultCatalogDeps());
|
|
512
|
+
const publishLifecycle = async (executionContext) => {
|
|
513
|
+
const records = readWorkflowRuns({ environment: executionContext.environment }).filter((run) => runBelongsToSession(run, executionContext.sessionId));
|
|
514
|
+
const activeItems = records.filter((run) => run.view.stage === "running" && run.view.stale !== true).map((run) => ({
|
|
515
|
+
id: `${run.view.workspace}/${run.view.runKey}`,
|
|
516
|
+
sessionId: executionContext.sessionId
|
|
517
|
+
}));
|
|
518
|
+
runProvider?.update(activeItems);
|
|
519
|
+
const runs = presentWorkflowRuns(records.map((run) => run.view), Date.now());
|
|
520
|
+
directEvents.publish(WORKFLOW_RUNS_TYPE, executionContext.sessionId, { runs });
|
|
521
|
+
try {
|
|
522
|
+
directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {
|
|
523
|
+
cwd: executionContext.cwd,
|
|
524
|
+
workflows: presentWorkflowCatalog(await catalogReader.read(executionContext.cwd))
|
|
525
|
+
});
|
|
526
|
+
} catch (error) {
|
|
527
|
+
const warning = error instanceof Error ? error.message : String(error);
|
|
528
|
+
directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {
|
|
529
|
+
cwd: executionContext.cwd,
|
|
530
|
+
workflows: [],
|
|
531
|
+
warning
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
return activeItems.length > 0;
|
|
535
|
+
};
|
|
536
|
+
const feature = (0, _agimon_ai_workflow_mcp.createEmbeddedWorkflowFeature)();
|
|
537
|
+
let control;
|
|
538
|
+
let controlDisposers = [];
|
|
539
|
+
const disposeControl = () => {
|
|
540
|
+
for (const dispose of controlDisposers.splice(0)) dispose();
|
|
541
|
+
control?.dispose();
|
|
542
|
+
control = void 0;
|
|
543
|
+
};
|
|
544
|
+
let modeOwner;
|
|
545
|
+
const modeSelected = () => (host.context.selection.state?.["minor-mode"] ?? []).includes(WORKFLOW_MODE_ID);
|
|
546
|
+
const modeState = () => {
|
|
547
|
+
const active = modeSelected();
|
|
548
|
+
return {
|
|
549
|
+
activation: active ? "active" : "inactive",
|
|
550
|
+
condition: "ready",
|
|
551
|
+
...active ? { detail: "workflow tools available" } : {},
|
|
552
|
+
actions: [{
|
|
553
|
+
id: "activate",
|
|
554
|
+
enabled: !active,
|
|
555
|
+
...!active ? {} : { disabledReason: "Workflow mode is active." }
|
|
556
|
+
}, {
|
|
557
|
+
id: "deactivate",
|
|
558
|
+
enabled: active,
|
|
559
|
+
...active ? {} : { disabledReason: "Workflow mode is inactive." }
|
|
560
|
+
}]
|
|
561
|
+
};
|
|
562
|
+
};
|
|
563
|
+
const selectMode = async (enabled) => {
|
|
564
|
+
const modes = (host.context.selection.state?.["minor-mode"] ?? []).filter((mode) => mode !== WORKFLOW_MODE_ID);
|
|
565
|
+
await host.changeSelection({
|
|
566
|
+
axis: "state",
|
|
567
|
+
key: "minor-mode",
|
|
568
|
+
values: enabled ? [...modes, WORKFLOW_MODE_ID] : modes
|
|
569
|
+
});
|
|
570
|
+
modeOwner?.publish();
|
|
571
|
+
};
|
|
572
|
+
modeOwner = (0, _agimon_ai_doompi_minor_mode.defineMinorMode)({
|
|
573
|
+
descriptor: {
|
|
574
|
+
source: SOURCE,
|
|
575
|
+
id: WORKFLOW_MODE_ID,
|
|
576
|
+
label: "Workflow",
|
|
577
|
+
description: "Workflow discovery, launch, inspection, control, and recovery tools.",
|
|
578
|
+
order: 20,
|
|
579
|
+
actions: [{
|
|
580
|
+
id: "activate",
|
|
581
|
+
label: "Activate",
|
|
582
|
+
description: "Enable workflow tools for this session.",
|
|
583
|
+
contexts: ["headless"],
|
|
584
|
+
parameters: []
|
|
585
|
+
}, {
|
|
586
|
+
id: "deactivate",
|
|
587
|
+
label: "Deactivate",
|
|
588
|
+
description: "Disable workflow tools without stopping active runs.",
|
|
589
|
+
contexts: ["headless"],
|
|
590
|
+
parameters: []
|
|
591
|
+
}]
|
|
592
|
+
},
|
|
593
|
+
state: modeState,
|
|
594
|
+
async handleAction(_runtime, actionId, _argumentsValue, execution) {
|
|
595
|
+
execution.signal.throwIfAborted();
|
|
596
|
+
if (actionId === "activate") {
|
|
597
|
+
await selectMode(true);
|
|
598
|
+
return { message: "Workflow mode activated." };
|
|
599
|
+
}
|
|
600
|
+
if (actionId === "deactivate") {
|
|
601
|
+
await selectMode(false);
|
|
602
|
+
return { message: "Workflow mode deactivated." };
|
|
603
|
+
}
|
|
604
|
+
throw new Error(`Unknown workflow mode action: ${actionId}`);
|
|
605
|
+
}
|
|
606
|
+
}).createOwner(void 0);
|
|
607
|
+
return {
|
|
608
|
+
services: [(0, _agimon_ai_doompi_minor_mode.serverMinorModes)([modeOwner]), (context) => {
|
|
609
|
+
const provider = require_workflowTerminal.registerRunProvider(context);
|
|
610
|
+
runProvider = provider;
|
|
611
|
+
return () => {
|
|
612
|
+
provider.dispose();
|
|
613
|
+
if (runProvider === provider) runProvider = void 0;
|
|
614
|
+
};
|
|
615
|
+
}],
|
|
616
|
+
hooks: [{
|
|
617
|
+
event: "tool_execution_end",
|
|
618
|
+
handle: async (_event, executionContext) => {
|
|
619
|
+
await publishLifecycle(executionContext);
|
|
620
|
+
}
|
|
621
|
+
}, {
|
|
622
|
+
when: {
|
|
623
|
+
state: { "minor-mode": WORKFLOW_MODE_ID },
|
|
624
|
+
attribution: {
|
|
625
|
+
kind: "minor",
|
|
626
|
+
mode: WORKFLOW_MODE_ID
|
|
627
|
+
}
|
|
628
|
+
},
|
|
629
|
+
event: "session_shutdown",
|
|
630
|
+
handle: disposeControl
|
|
631
|
+
}],
|
|
632
|
+
resources: [
|
|
633
|
+
{
|
|
634
|
+
when: {
|
|
635
|
+
state: { "minor-mode": WORKFLOW_MODE_ID },
|
|
636
|
+
attribution: {
|
|
637
|
+
kind: "minor",
|
|
638
|
+
mode: WORKFLOW_MODE_ID
|
|
639
|
+
}
|
|
640
|
+
},
|
|
641
|
+
name: "doompi-author-workflow",
|
|
642
|
+
kind: "skill",
|
|
643
|
+
read: () => require_workflowTerminal.readWorkflowSkill("doompi-author-workflow")
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
when: {
|
|
647
|
+
state: { "minor-mode": WORKFLOW_MODE_ID },
|
|
648
|
+
attribution: {
|
|
649
|
+
kind: "minor",
|
|
650
|
+
mode: WORKFLOW_MODE_ID
|
|
651
|
+
}
|
|
652
|
+
},
|
|
653
|
+
name: "doompi-use-workflow",
|
|
654
|
+
kind: "skill",
|
|
655
|
+
read: () => require_workflowTerminal.readWorkflowSkill("doompi-use-workflow")
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
when: {
|
|
659
|
+
state: { "minor-mode": WORKFLOW_MODE_ID },
|
|
660
|
+
attribution: {
|
|
661
|
+
kind: "minor",
|
|
662
|
+
mode: WORKFLOW_MODE_ID
|
|
663
|
+
}
|
|
664
|
+
},
|
|
665
|
+
name: "workflow-recovery",
|
|
666
|
+
kind: "skill",
|
|
667
|
+
read: () => require_workflowTerminal.readWorkflowSkill("workflow-recovery")
|
|
668
|
+
}
|
|
669
|
+
],
|
|
670
|
+
activities: [{
|
|
671
|
+
when: {
|
|
672
|
+
state: { "minor-mode": WORKFLOW_MODE_ID },
|
|
673
|
+
attribution: {
|
|
674
|
+
kind: "minor",
|
|
675
|
+
mode: WORKFLOW_MODE_ID
|
|
676
|
+
}
|
|
677
|
+
},
|
|
678
|
+
name: SOURCE,
|
|
679
|
+
async start(executionContext) {
|
|
680
|
+
const reportFailure = (error) => {
|
|
681
|
+
process.emitWarning(`Could not publish headless workflow state: ${String(error)}`);
|
|
682
|
+
};
|
|
683
|
+
const stopFor = (ownedControl) => () => {
|
|
684
|
+
publishLifecycle(executionContext).then((active) => {
|
|
685
|
+
if (!active && !modeSelected() && control === ownedControl) disposeControl();
|
|
686
|
+
}).catch(reportFailure);
|
|
687
|
+
};
|
|
688
|
+
if (control !== void 0) {
|
|
689
|
+
const ownedControl = control;
|
|
690
|
+
await publishLifecycle(executionContext);
|
|
691
|
+
return stopFor(ownedControl);
|
|
692
|
+
}
|
|
693
|
+
control = feature.createRunControl({});
|
|
694
|
+
const ownedControl = control;
|
|
695
|
+
const refresh = () => {
|
|
696
|
+
publishLifecycle(executionContext).then((active) => {
|
|
697
|
+
if (!active && !modeSelected() && control === ownedControl) disposeControl();
|
|
698
|
+
}).catch(reportFailure);
|
|
699
|
+
};
|
|
700
|
+
controlDisposers = [
|
|
701
|
+
ownedControl.on("runStarted", refresh),
|
|
702
|
+
ownedControl.on("runUpdated", refresh),
|
|
703
|
+
ownedControl.on("runFinished", refresh)
|
|
704
|
+
];
|
|
705
|
+
try {
|
|
706
|
+
await ownedControl.start();
|
|
707
|
+
await publishLifecycle(executionContext);
|
|
708
|
+
return stopFor(ownedControl);
|
|
709
|
+
} catch (error) {
|
|
710
|
+
if (control === ownedControl) disposeControl();
|
|
711
|
+
throw error;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}],
|
|
715
|
+
tools: [
|
|
716
|
+
{
|
|
717
|
+
when: {
|
|
718
|
+
state: { "minor-mode": WORKFLOW_MODE_ID },
|
|
719
|
+
attribution: {
|
|
720
|
+
kind: "minor",
|
|
721
|
+
mode: WORKFLOW_MODE_ID
|
|
722
|
+
}
|
|
723
|
+
},
|
|
724
|
+
name: LIST_TOOL,
|
|
725
|
+
label: "List Workflows",
|
|
726
|
+
description: "List workflow definitions available in this repository.",
|
|
727
|
+
parameters: zod.z.toJSONSchema(feature.listWorkflowsTool.getInputSchema()),
|
|
728
|
+
executionMode: "serial",
|
|
729
|
+
async execute(_toolCallId, parameters, signal) {
|
|
730
|
+
signal?.throwIfAborted();
|
|
731
|
+
return callResult(await feature.listWorkflowsTool.execute(parameters));
|
|
732
|
+
}
|
|
733
|
+
},
|
|
734
|
+
{
|
|
735
|
+
when: {
|
|
736
|
+
state: { "minor-mode": WORKFLOW_MODE_ID },
|
|
737
|
+
attribution: {
|
|
738
|
+
kind: "minor",
|
|
739
|
+
mode: WORKFLOW_MODE_ID
|
|
740
|
+
}
|
|
741
|
+
},
|
|
742
|
+
name: LAUNCH_TOOL,
|
|
743
|
+
label: "Launch Workflow",
|
|
744
|
+
description: "Start a workflow run and return its recorded launch result.",
|
|
745
|
+
parameters: zod.z.toJSONSchema(feature.runTool.getInputSchema()),
|
|
746
|
+
executionMode: "serial",
|
|
747
|
+
async execute(_toolCallId, parameters, signal) {
|
|
748
|
+
signal?.throwIfAborted();
|
|
749
|
+
return callResult(await feature.runTool.execute(parameters));
|
|
750
|
+
}
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
when: {
|
|
754
|
+
state: { "minor-mode": WORKFLOW_MODE_ID },
|
|
755
|
+
attribution: {
|
|
756
|
+
kind: "minor",
|
|
757
|
+
mode: WORKFLOW_MODE_ID
|
|
758
|
+
}
|
|
759
|
+
},
|
|
760
|
+
name: RUN_TOOL,
|
|
761
|
+
label: "Workflow Run",
|
|
762
|
+
description: "Inspect the status of a workflow run or request cooperative control.",
|
|
763
|
+
parameters: {
|
|
764
|
+
type: "object",
|
|
765
|
+
properties: {
|
|
766
|
+
action: {
|
|
767
|
+
type: "string",
|
|
768
|
+
enum: [
|
|
769
|
+
"status",
|
|
770
|
+
"pause",
|
|
771
|
+
"resume",
|
|
772
|
+
"stop"
|
|
773
|
+
]
|
|
774
|
+
},
|
|
775
|
+
runKey: {
|
|
776
|
+
type: "string",
|
|
777
|
+
minLength: 1
|
|
778
|
+
},
|
|
779
|
+
workspace: { type: "string" },
|
|
780
|
+
reason: { type: "string" },
|
|
781
|
+
expectedRunId: { type: "string" }
|
|
782
|
+
},
|
|
783
|
+
required: ["action", "runKey"],
|
|
784
|
+
additionalProperties: false
|
|
785
|
+
},
|
|
786
|
+
executionMode: "serial",
|
|
787
|
+
async execute(_toolCallId, parameters, signal) {
|
|
788
|
+
signal?.throwIfAborted();
|
|
789
|
+
const input = parameters;
|
|
790
|
+
const runs = readWorkflowRuns({ environment: host.context.environment }).filter((run) => runBelongsToSession(run, host.context.sessionId) && run.view.runKey === input.runKey && (input.workspace === void 0 || run.view.workspace === input.workspace));
|
|
791
|
+
if (runs.length !== 1) return {
|
|
792
|
+
...callResult({ error: runs.length === 0 ? "Workflow run was not found in this session." : "Specify the workspace for this run key." }),
|
|
793
|
+
isError: true
|
|
794
|
+
};
|
|
795
|
+
const run = runs[0].view;
|
|
796
|
+
if (input.action === "status") return callResult(run);
|
|
797
|
+
if (!control) return callResult({ error: "Workflow activity is not active." });
|
|
798
|
+
if (typeof input.expectedRunId !== "string" || input.expectedRunId.length === 0) return callResult({ error: "expectedRunId is required for workflow control." });
|
|
799
|
+
return callResult(input.action === "pause" ? await control.pause(input.runKey, input.expectedRunId, input.workspace, input.reason) : input.action === "resume" ? await control.resume(input.runKey, input.expectedRunId, input.workspace) : await control.stop(input.runKey, input.expectedRunId, input.workspace, input.reason));
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
],
|
|
803
|
+
commands: [{
|
|
804
|
+
when: {
|
|
805
|
+
state: { "minor-mode": WORKFLOW_MODE_ID },
|
|
806
|
+
attribution: {
|
|
807
|
+
kind: "minor",
|
|
808
|
+
mode: WORKFLOW_MODE_ID
|
|
809
|
+
}
|
|
810
|
+
},
|
|
811
|
+
name: "workflow-launch",
|
|
812
|
+
description: "Launch a workflow from a slash command.",
|
|
813
|
+
async execute(args, execution) {
|
|
814
|
+
const parsed = require_workflowLaunchCommand.parseWorkflowLaunchCommand(args);
|
|
815
|
+
if ("error" in parsed) {
|
|
816
|
+
await execution.client.notify({
|
|
817
|
+
body: parsed.error,
|
|
818
|
+
level: "error"
|
|
819
|
+
});
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
const rendered = callResult(await feature.runTool.execute({
|
|
823
|
+
workflowPath: parsed.workflow,
|
|
824
|
+
...parsed.runner === void 0 ? {} : { runner: parsed.runner },
|
|
825
|
+
...Object.keys(parsed.inputs).length === 0 ? {} : { inputs: parsed.inputs },
|
|
826
|
+
...parsed.prompt === void 0 ? {} : { prompt: parsed.prompt }
|
|
827
|
+
})).content.find((entry) => entry.type === "text");
|
|
828
|
+
await execution.client.notify({
|
|
829
|
+
body: rendered?.type === "text" ? rendered.text : "Workflow launch requested.",
|
|
830
|
+
level: "info"
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
}],
|
|
834
|
+
onDispose() {
|
|
835
|
+
disposeControl();
|
|
836
|
+
runProvider?.dispose();
|
|
837
|
+
runProvider = void 0;
|
|
838
|
+
}
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
//#endregion
|
|
842
|
+
//#region src/types/apiRoutes.ts
|
|
843
|
+
/**
|
|
844
|
+
* This package's routes, as data.
|
|
845
|
+
*
|
|
846
|
+
* No scope and no base path. The build reads both off
|
|
847
|
+
* `src/extensions/(backend)/api/workflow/`, so the mount is stated once, by the
|
|
848
|
+
* folder that creates it. The same API answers at all three scopes, because a
|
|
849
|
+
* global contribution cascades into workspace and session; the folder under
|
|
850
|
+
* `workspaces/sessions/` only re-mounts it for a session's own server.
|
|
851
|
+
*
|
|
852
|
+
* This is the one file the routes, the Hono app and the browser all read, so a
|
|
853
|
+
* path cannot move on one side alone. The page used to build the hub's own
|
|
854
|
+
* absolute URL and then rewrite its plugin prefix with String.replace to reach
|
|
855
|
+
* a session, which is exactly the kind of copy that can move by one character
|
|
856
|
+
* without anything noticing.
|
|
857
|
+
*
|
|
858
|
+
* `:workspace` and `:runKey` are Hono's own parameter syntax, because the app
|
|
859
|
+
* registers `path` verbatim.
|
|
860
|
+
*/
|
|
861
|
+
/** One run, which every route below addresses. */
|
|
862
|
+
const RUN = "/runs/:workspace/:runKey";
|
|
863
|
+
var apiRoutes_default = (0, _agimon_ai_doompi_core_web.defineApiRoutes)({
|
|
864
|
+
/**
|
|
865
|
+
* The terminal, as server-sent events.
|
|
866
|
+
*
|
|
867
|
+
* `stream: true` gets a URL and no call method: the consumer is the browser's
|
|
868
|
+
* own `EventSource`, and a relayed call would buffer a stream that never ends.
|
|
869
|
+
*/
|
|
870
|
+
screen: {
|
|
871
|
+
method: "GET",
|
|
872
|
+
path: `${RUN}/screen/stream`,
|
|
873
|
+
stream: true
|
|
874
|
+
},
|
|
875
|
+
control: {
|
|
876
|
+
method: "POST",
|
|
877
|
+
path: `${RUN}/control`,
|
|
878
|
+
response: (0, _agimon_ai_doompi_core_web.apiResponse)()
|
|
879
|
+
},
|
|
880
|
+
keys: {
|
|
881
|
+
method: "POST",
|
|
882
|
+
path: `${RUN}/keys`
|
|
883
|
+
},
|
|
884
|
+
resize: {
|
|
885
|
+
method: "POST",
|
|
886
|
+
path: `${RUN}/resize`,
|
|
887
|
+
response: (0, _agimon_ai_doompi_core_web.apiResponse)()
|
|
888
|
+
},
|
|
889
|
+
remove: {
|
|
890
|
+
method: "DELETE",
|
|
891
|
+
path: RUN,
|
|
892
|
+
response: (0, _agimon_ai_doompi_core_web.apiResponse)()
|
|
893
|
+
},
|
|
894
|
+
artifacts: {
|
|
895
|
+
method: "GET",
|
|
896
|
+
path: `${RUN}/artifacts`,
|
|
897
|
+
response: (0, _agimon_ai_doompi_core_web.apiResponse)()
|
|
898
|
+
},
|
|
899
|
+
/** One artifact: its metadata and text, or its raw bytes under `raw=1`. */
|
|
900
|
+
artifact: {
|
|
901
|
+
method: "GET",
|
|
902
|
+
path: `${RUN}/artifacts/:name{.+}`,
|
|
903
|
+
query: ["raw", "download"],
|
|
904
|
+
response: (0, _agimon_ai_doompi_core_web.apiResponse)()
|
|
905
|
+
}
|
|
906
|
+
});
|
|
907
|
+
//#endregion
|
|
908
|
+
//#region src/types/webWorkflowTerminal.ts
|
|
909
|
+
/**
|
|
910
|
+
* The wire contract between this package's hub API and its cockpit client:
|
|
911
|
+
* one run's terminal, and the files its run directory holds.
|
|
912
|
+
*
|
|
913
|
+
* Both halves of the cockpit import these names, so the route strings and the
|
|
914
|
+
* event names live here rather than being spelled twice.
|
|
915
|
+
*/
|
|
916
|
+
/**
|
|
917
|
+
* Segment this package's API is mounted under, below /api/plugins/.
|
|
918
|
+
*
|
|
919
|
+
* The same word names `src/extensions/(backend)/api/workflow/`, which is where
|
|
920
|
+
* the build reads the mount for the browser's client, so the two cannot drift.
|
|
921
|
+
* The routes themselves are declared in `apiRoutes.ts`.
|
|
922
|
+
*/
|
|
923
|
+
const WORKFLOW_API_BASE_PATH = "workflow";
|
|
924
|
+
/** The SSE event name the screen stream writes. */
|
|
925
|
+
const WORKFLOW_SCREEN_EVENT = "screen";
|
|
926
|
+
//#endregion
|
|
927
|
+
//#region src/services/workflowHubApi/index.ts
|
|
928
|
+
/** Stages a run can be recorded under, newest first: a live run is the common case. */
|
|
929
|
+
const STAGES = [
|
|
930
|
+
"running",
|
|
931
|
+
"error",
|
|
932
|
+
"completed"
|
|
933
|
+
];
|
|
934
|
+
/** Lines of screen the stream sends, which is a terminal's visible height plus room. */
|
|
935
|
+
const SCREEN_LINES = 48;
|
|
936
|
+
/** How often the stream re-reads; the service coalesces, so this is an upper bound. */
|
|
937
|
+
const STREAM_TICK_MS = 500;
|
|
938
|
+
/** How often a settled run is re-checked before the stream closes itself. */
|
|
939
|
+
const SETTLED_POLL_TICKS = 4;
|
|
940
|
+
/** Bytes of one textual artifact returned as JSON; binary previews use a stream. */
|
|
941
|
+
const MAX_ARTIFACT_BYTES = 524288;
|
|
942
|
+
/** Path segments a client supplies are names, never paths. */
|
|
943
|
+
const SAFE_SEGMENT = /^[\w.@-]+$/;
|
|
944
|
+
const ARTIFACT_MIME_TYPES = {
|
|
945
|
+
".aac": "audio/aac",
|
|
946
|
+
".bmp": "image/bmp",
|
|
947
|
+
".css": "text/css",
|
|
948
|
+
".csv": "text/csv",
|
|
949
|
+
".gif": "image/gif",
|
|
950
|
+
".htm": "text/html",
|
|
951
|
+
".html": "text/html",
|
|
952
|
+
".ico": "image/x-icon",
|
|
953
|
+
".jpeg": "image/jpeg",
|
|
954
|
+
".jpg": "image/jpeg",
|
|
955
|
+
".js": "text/javascript",
|
|
956
|
+
".json": "application/json",
|
|
957
|
+
".jsx": "text/jsx",
|
|
958
|
+
".m4a": "audio/mp4",
|
|
959
|
+
".markdown": "text/markdown",
|
|
960
|
+
".md": "text/markdown",
|
|
961
|
+
".mov": "video/quicktime",
|
|
962
|
+
".mp3": "audio/mpeg",
|
|
963
|
+
".mp4": "video/mp4",
|
|
964
|
+
".oga": "audio/ogg",
|
|
965
|
+
".ogg": "audio/ogg",
|
|
966
|
+
".ogv": "video/ogg",
|
|
967
|
+
".pdf": "application/pdf",
|
|
968
|
+
".png": "image/png",
|
|
969
|
+
".sh": "text/x-shellscript",
|
|
970
|
+
".svg": "image/svg+xml",
|
|
971
|
+
".toml": "text/toml",
|
|
972
|
+
".ts": "text/typescript",
|
|
973
|
+
".tsv": "text/tab-separated-values",
|
|
974
|
+
".tsx": "text/tsx",
|
|
975
|
+
".txt": "text/plain",
|
|
976
|
+
".wav": "audio/wav",
|
|
977
|
+
".webm": "video/webm",
|
|
978
|
+
".webp": "image/webp",
|
|
979
|
+
".xml": "application/xml",
|
|
980
|
+
".yaml": "text/yaml",
|
|
981
|
+
".yml": "text/yaml"
|
|
982
|
+
};
|
|
983
|
+
/**
|
|
984
|
+
* One request's JSON body as a plain record.
|
|
985
|
+
*
|
|
986
|
+
* A body that is absent, malformed, or not an object reads as empty rather
|
|
987
|
+
* than failing the route: every field is checked by the route anyway, and a
|
|
988
|
+
* 400 naming the missing field beats a parse error naming nothing.
|
|
989
|
+
*/
|
|
990
|
+
async function jsonBody(context) {
|
|
991
|
+
const parsed = await context.req.json().catch(() => void 0);
|
|
992
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
993
|
+
}
|
|
994
|
+
/** Rejects anything that could climb out of the registry before a path is built. */
|
|
995
|
+
function isSafeSegment(value) {
|
|
996
|
+
return value !== "" && value !== "../adapters" && value !== ".." && SAFE_SEGMENT.test(value);
|
|
997
|
+
}
|
|
998
|
+
/** One run's identity for caches and leases, stable across stage moves. */
|
|
999
|
+
function runIdentityOf(workspace, runKey) {
|
|
1000
|
+
return `${workspace}/${runKey}`;
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* This package's HTTP surface: one workflow run's terminal, and the files its
|
|
1004
|
+
* run directory holds.
|
|
1005
|
+
*
|
|
1006
|
+
* Mounted in the hub rather than in a session's server, because a run's
|
|
1007
|
+
* terminal belongs to its multiplexer rather than to the session that launched
|
|
1008
|
+
* it: any process can read a tmux pane, and the session's own server cannot
|
|
1009
|
+
* reach anything more. The routes therefore name a run, never a session.
|
|
1010
|
+
*/
|
|
1011
|
+
function createWorkflowHubApi(options = {}) {
|
|
1012
|
+
const registry = options.registry ?? new _agimon_ai_workflow_mcp.WorkflowRegistryService();
|
|
1013
|
+
const facade = options.terminal ?? new _agimon_ai_workflow_mcp.WorkflowTerminalService();
|
|
1014
|
+
const terminal = require_workflowTerminal.createWorkflowTerminalService({
|
|
1015
|
+
terminal: facade,
|
|
1016
|
+
now: options.now ?? (() => Date.now())
|
|
1017
|
+
});
|
|
1018
|
+
const app = new hono.Hono();
|
|
1019
|
+
/** The record behind a request, whichever stage it now sits in. */
|
|
1020
|
+
const runOf = async (workspace, runKey) => {
|
|
1021
|
+
if (!isSafeSegment(workspace) || !isSafeSegment(runKey)) return void 0;
|
|
1022
|
+
for (const stage of STAGES) try {
|
|
1023
|
+
return await registry.readRunByKey(workspace, stage, runKey);
|
|
1024
|
+
} catch {}
|
|
1025
|
+
};
|
|
1026
|
+
const missing = (workspace, runKey) => ({ error: `No workflow run '${runKey}' in workspace '${workspace}'.` });
|
|
1027
|
+
app.get(apiRoutes_default.screen.path, async (context) => {
|
|
1028
|
+
const workspace = context.req.param("workspace");
|
|
1029
|
+
const runKey = context.req.param("runKey");
|
|
1030
|
+
const record = await runOf(workspace, runKey);
|
|
1031
|
+
if (record === void 0) return context.json(missing(workspace, runKey), 404);
|
|
1032
|
+
const identity = runIdentityOf(workspace, runKey);
|
|
1033
|
+
return (0, hono_streaming.streamSSE)(context, async (stream) => {
|
|
1034
|
+
let settledTicks = 0;
|
|
1035
|
+
let running = true;
|
|
1036
|
+
stream.onAbort(() => {
|
|
1037
|
+
running = false;
|
|
1038
|
+
});
|
|
1039
|
+
while (running) {
|
|
1040
|
+
const current = await runOf(workspace, runKey) ?? record;
|
|
1041
|
+
const capabilities = terminal.capabilities(current);
|
|
1042
|
+
const lines = capabilities.readable ? await terminal.screen(identity, current, SCREEN_LINES) : [];
|
|
1043
|
+
const settled = current.stage !== "running";
|
|
1044
|
+
if (settled) settledTicks += 1;
|
|
1045
|
+
const ended = settled && settledTicks >= SETTLED_POLL_TICKS;
|
|
1046
|
+
const event = {
|
|
1047
|
+
lines,
|
|
1048
|
+
capabilities,
|
|
1049
|
+
...ended ? { ended: true } : {}
|
|
1050
|
+
};
|
|
1051
|
+
await stream.writeSSE({
|
|
1052
|
+
event: WORKFLOW_SCREEN_EVENT,
|
|
1053
|
+
data: JSON.stringify(event)
|
|
1054
|
+
});
|
|
1055
|
+
if (ended) break;
|
|
1056
|
+
await stream.sleep(STREAM_TICK_MS);
|
|
1057
|
+
}
|
|
1058
|
+
terminal.forget(/* @__PURE__ */ new Set());
|
|
1059
|
+
});
|
|
1060
|
+
});
|
|
1061
|
+
app.post(apiRoutes_default.control.path, async (context) => {
|
|
1062
|
+
const workspace = context.req.param("workspace");
|
|
1063
|
+
const runKey = context.req.param("runKey");
|
|
1064
|
+
const record = await runOf(workspace, runKey);
|
|
1065
|
+
if (record === void 0) return context.json(missing(workspace, runKey), 404);
|
|
1066
|
+
const identity = runIdentityOf(workspace, runKey);
|
|
1067
|
+
const body = await jsonBody(context);
|
|
1068
|
+
const capabilities = terminal.capabilities(record);
|
|
1069
|
+
if (body.release === true) {
|
|
1070
|
+
if (typeof body.token === "string") terminal.releaseControl(identity, body.token);
|
|
1071
|
+
return context.json({ held: false });
|
|
1072
|
+
}
|
|
1073
|
+
if (!capabilities.writable) {
|
|
1074
|
+
const refused = {
|
|
1075
|
+
held: false,
|
|
1076
|
+
reason: capabilities.reason
|
|
1077
|
+
};
|
|
1078
|
+
return context.json(refused, 409);
|
|
1079
|
+
}
|
|
1080
|
+
const token = typeof body.token === "string" && body.token !== "" ? body.token : (0, node_crypto.randomUUID)();
|
|
1081
|
+
if (!terminal.takeControl(identity, token)) return context.json({
|
|
1082
|
+
held: false,
|
|
1083
|
+
reason: "Another reader holds the keyboard."
|
|
1084
|
+
}, 409);
|
|
1085
|
+
const held = {
|
|
1086
|
+
held: true,
|
|
1087
|
+
token
|
|
1088
|
+
};
|
|
1089
|
+
return context.json(held);
|
|
1090
|
+
});
|
|
1091
|
+
app.post(apiRoutes_default.keys.path, async (context) => {
|
|
1092
|
+
const workspace = context.req.param("workspace");
|
|
1093
|
+
const runKey = context.req.param("runKey");
|
|
1094
|
+
const record = await runOf(workspace, runKey);
|
|
1095
|
+
if (record === void 0) return context.json(missing(workspace, runKey), 404);
|
|
1096
|
+
const body = await jsonBody(context);
|
|
1097
|
+
if (typeof body.token !== "string" || typeof body.data !== "string") return context.json({ error: "A keystroke needs a control token and its data." }, 400);
|
|
1098
|
+
try {
|
|
1099
|
+
await terminal.write(runIdentityOf(workspace, runKey), record, body.token, body.data);
|
|
1100
|
+
} catch (error) {
|
|
1101
|
+
return context.json({ error: error instanceof Error ? error.message : String(error) }, 409);
|
|
1102
|
+
}
|
|
1103
|
+
return context.body(null, 204);
|
|
1104
|
+
});
|
|
1105
|
+
app.post(apiRoutes_default.resize.path, async (context) => {
|
|
1106
|
+
const workspace = context.req.param("workspace");
|
|
1107
|
+
const runKey = context.req.param("runKey");
|
|
1108
|
+
const record = await runOf(workspace, runKey);
|
|
1109
|
+
if (record === void 0) return context.json(missing(workspace, runKey), 404);
|
|
1110
|
+
const { token, columns, rows } = await jsonBody(context);
|
|
1111
|
+
if (typeof token !== "string" || typeof columns !== "number" || typeof rows !== "number") return context.json({ error: "A resize needs a control token, columns and rows." }, 400);
|
|
1112
|
+
try {
|
|
1113
|
+
const resized = await terminal.resize(runIdentityOf(workspace, runKey), record, token, columns, rows);
|
|
1114
|
+
return context.json({ resized });
|
|
1115
|
+
} catch (error) {
|
|
1116
|
+
return context.json({ error: error instanceof Error ? error.message : String(error) }, 409);
|
|
1117
|
+
}
|
|
1118
|
+
});
|
|
1119
|
+
app.delete(apiRoutes_default.remove.path, async (context) => {
|
|
1120
|
+
const workspace = context.req.param("workspace");
|
|
1121
|
+
const runKey = context.req.param("runKey");
|
|
1122
|
+
const record = await runOf(workspace, runKey);
|
|
1123
|
+
if (record === void 0) return context.json(missing(workspace, runKey), 404);
|
|
1124
|
+
if (record.stage === "running") return context.json({ error: "A running workflow must be stopped before it can be deleted." }, 409);
|
|
1125
|
+
try {
|
|
1126
|
+
node_fs.default.rmSync(registry.runDirectoryFor(record), {
|
|
1127
|
+
recursive: true,
|
|
1128
|
+
force: true
|
|
1129
|
+
});
|
|
1130
|
+
} catch (error) {
|
|
1131
|
+
return context.json({ error: error instanceof Error ? error.message : String(error) }, 409);
|
|
1132
|
+
}
|
|
1133
|
+
return context.json({ deleted: true });
|
|
1134
|
+
});
|
|
1135
|
+
app.get(apiRoutes_default.artifacts.path, async (context) => {
|
|
1136
|
+
const workspace = context.req.param("workspace");
|
|
1137
|
+
const runKey = context.req.param("runKey");
|
|
1138
|
+
const record = await runOf(workspace, runKey);
|
|
1139
|
+
if (record === void 0) return context.json(missing(workspace, runKey), 404);
|
|
1140
|
+
const runDir = registry.runDirectoryFor(record);
|
|
1141
|
+
const body = {
|
|
1142
|
+
runDir,
|
|
1143
|
+
description: record.runDirectory?.description ?? "",
|
|
1144
|
+
artifacts: readArtifacts(runDir, record)
|
|
1145
|
+
};
|
|
1146
|
+
return context.json(body);
|
|
1147
|
+
});
|
|
1148
|
+
app.get(apiRoutes_default.artifact.path, async (context) => {
|
|
1149
|
+
const workspace = context.req.param("workspace");
|
|
1150
|
+
const runKey = context.req.param("runKey");
|
|
1151
|
+
const record = await runOf(workspace, runKey);
|
|
1152
|
+
if (record === void 0) return context.json(missing(workspace, runKey), 404);
|
|
1153
|
+
const runDir = registry.runDirectoryFor(record);
|
|
1154
|
+
const requested = context.req.param("name");
|
|
1155
|
+
const resolved = resolveInside(runDir, requested);
|
|
1156
|
+
if (resolved === void 0) return context.json({ error: `'${requested}' is not inside this run.` }, 400);
|
|
1157
|
+
if (context.req.query("raw") === "1") return streamArtifact(resolved, requested, context.req.header("range"), context.req.query("download") === "1") ?? context.json({ error: `'${requested}' has not been written.` }, 404);
|
|
1158
|
+
const body = readArtifact(resolved, requested);
|
|
1159
|
+
if (body === void 0) return context.json({ error: `'${requested}' has not been written.` }, 404);
|
|
1160
|
+
return context.json(body);
|
|
1161
|
+
});
|
|
1162
|
+
return app;
|
|
1163
|
+
}
|
|
1164
|
+
/**
|
|
1165
|
+
* A path inside the run directory, or undefined when it points anywhere else.
|
|
1166
|
+
*
|
|
1167
|
+
* The client supplies this one verbatim, unlike the run key, so it is resolved
|
|
1168
|
+
* and then checked rather than trusted: without the check the route would read
|
|
1169
|
+
* any file the hub can reach.
|
|
1170
|
+
*/
|
|
1171
|
+
function resolveInside(runDir, requested) {
|
|
1172
|
+
const resolved = node_path.default.resolve(runDir, requested);
|
|
1173
|
+
const root = node_path.default.resolve(runDir);
|
|
1174
|
+
if (resolved !== root && !resolved.startsWith(`${root}${node_path.default.sep}`)) return void 0;
|
|
1175
|
+
return resolved;
|
|
1176
|
+
}
|
|
1177
|
+
/** Size and modification time of one path, or undefined when it is not there. */
|
|
1178
|
+
function statOf(target) {
|
|
1179
|
+
try {
|
|
1180
|
+
return node_fs.default.statSync(target);
|
|
1181
|
+
} catch {
|
|
1182
|
+
return;
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
function stateOf(stats) {
|
|
1186
|
+
if (stats === void 0) return "pending";
|
|
1187
|
+
if (stats.isDirectory()) return "written";
|
|
1188
|
+
return stats.size === 0 ? "empty" : "written";
|
|
1189
|
+
}
|
|
1190
|
+
function viewOf(runDir, entry) {
|
|
1191
|
+
const stats = statOf(node_path.default.join(runDir, entry.path));
|
|
1192
|
+
return {
|
|
1193
|
+
...entry,
|
|
1194
|
+
state: stateOf(stats),
|
|
1195
|
+
...stats === void 0 ? {} : {
|
|
1196
|
+
size: stats.size,
|
|
1197
|
+
modifiedAt: stats.mtime.toISOString()
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
/**
|
|
1202
|
+
* What the run directory holds: the workflow's own declaration first, then the
|
|
1203
|
+
* files nobody declared.
|
|
1204
|
+
*
|
|
1205
|
+
* The declaration is the point of the folder, so it leads and keeps its order
|
|
1206
|
+
* even for entries no job has written yet. The rest follows rather than being
|
|
1207
|
+
* hidden: the engine's own context.md and progress log are often exactly what a
|
|
1208
|
+
* reader is looking for.
|
|
1209
|
+
*/
|
|
1210
|
+
function readArtifacts(runDir, record) {
|
|
1211
|
+
const declared = (record.runDirectory?.entries ?? []).map((entry) => viewOf(runDir, {
|
|
1212
|
+
path: entry.path,
|
|
1213
|
+
kind: entry.kind,
|
|
1214
|
+
description: entry.description,
|
|
1215
|
+
producedBy: entry["produced-by"] ?? [],
|
|
1216
|
+
declared: true
|
|
1217
|
+
}));
|
|
1218
|
+
const claimed = new Set(declared.map((entry) => entry.path));
|
|
1219
|
+
let names;
|
|
1220
|
+
try {
|
|
1221
|
+
names = node_fs.default.readdirSync(runDir, { withFileTypes: true });
|
|
1222
|
+
} catch {
|
|
1223
|
+
return declared;
|
|
1224
|
+
}
|
|
1225
|
+
const found = names.filter((entry) => !claimed.has(entry.name)).map((entry) => viewOf(runDir, {
|
|
1226
|
+
path: entry.name,
|
|
1227
|
+
kind: entry.isDirectory() ? "directory" : "file",
|
|
1228
|
+
description: "",
|
|
1229
|
+
producedBy: [],
|
|
1230
|
+
declared: false
|
|
1231
|
+
})).sort((left, right) => left.path.localeCompare(right.path));
|
|
1232
|
+
return [...declared, ...found];
|
|
1233
|
+
}
|
|
1234
|
+
/** Browser content type inferred from a filename without trusting client input. */
|
|
1235
|
+
function artifactMimeType(requested) {
|
|
1236
|
+
return ARTIFACT_MIME_TYPES[node_path.default.extname(requested).toLowerCase()] ?? "application/octet-stream";
|
|
1237
|
+
}
|
|
1238
|
+
function isTextArtifact(mimeType) {
|
|
1239
|
+
return mimeType.startsWith("text/") || mimeType === "application/json" || mimeType === "application/xml";
|
|
1240
|
+
}
|
|
1241
|
+
/** One artifact's metadata and bounded text, or undefined when it is not readable. */
|
|
1242
|
+
function readArtifact(resolved, requested) {
|
|
1243
|
+
const stats = statOf(resolved);
|
|
1244
|
+
if (stats === void 0 || stats.isDirectory()) return void 0;
|
|
1245
|
+
const mimeType = artifactMimeType(requested);
|
|
1246
|
+
let text;
|
|
1247
|
+
if (isTextArtifact(mimeType)) try {
|
|
1248
|
+
const handle = node_fs.default.openSync(resolved, "r");
|
|
1249
|
+
try {
|
|
1250
|
+
const buffer = Buffer.alloc(Math.min(stats.size, MAX_ARTIFACT_BYTES));
|
|
1251
|
+
node_fs.default.readSync(handle, buffer, 0, buffer.length, 0);
|
|
1252
|
+
text = buffer.toString("utf8");
|
|
1253
|
+
} finally {
|
|
1254
|
+
node_fs.default.closeSync(handle);
|
|
1255
|
+
}
|
|
1256
|
+
} catch {
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1259
|
+
return {
|
|
1260
|
+
path: requested,
|
|
1261
|
+
size: stats.size,
|
|
1262
|
+
modifiedAt: stats.mtime.toISOString(),
|
|
1263
|
+
mimeType,
|
|
1264
|
+
...text === void 0 ? {} : { text },
|
|
1265
|
+
truncated: text !== void 0 && stats.size > MAX_ARTIFACT_BYTES
|
|
1266
|
+
};
|
|
1267
|
+
}
|
|
1268
|
+
/** Streams media with byte-range support so browser audio, video, and PDF controls can seek. */
|
|
1269
|
+
function streamArtifact(resolved, requested, rangeHeader, download) {
|
|
1270
|
+
const stats = statOf(resolved);
|
|
1271
|
+
if (stats === void 0 || stats.isDirectory()) return void 0;
|
|
1272
|
+
const mimeType = artifactMimeType(requested);
|
|
1273
|
+
let start = 0;
|
|
1274
|
+
let end = Math.max(0, stats.size - 1);
|
|
1275
|
+
let partial = false;
|
|
1276
|
+
const match = rangeHeader?.match(/^bytes=(\d*)-(\d*)$/);
|
|
1277
|
+
if (match !== null && match !== void 0 && stats.size > 0) {
|
|
1278
|
+
const requestedStart = match[1] === "" ? void 0 : Number(match[1]);
|
|
1279
|
+
const requestedEnd = match[2] === "" ? void 0 : Number(match[2]);
|
|
1280
|
+
if (requestedStart === void 0 && requestedEnd !== void 0) start = Math.max(0, stats.size - requestedEnd);
|
|
1281
|
+
else if (requestedStart !== void 0) {
|
|
1282
|
+
start = requestedStart;
|
|
1283
|
+
end = requestedEnd === void 0 ? end : Math.min(requestedEnd, end);
|
|
1284
|
+
}
|
|
1285
|
+
if (start >= stats.size || start > end) return new Response(null, {
|
|
1286
|
+
status: 416,
|
|
1287
|
+
headers: { "content-range": `bytes */${String(stats.size)}` }
|
|
1288
|
+
});
|
|
1289
|
+
partial = true;
|
|
1290
|
+
}
|
|
1291
|
+
const filename = node_path.default.basename(requested).replace(/["\\\r\n]/g, "_");
|
|
1292
|
+
const headers = new Headers({
|
|
1293
|
+
"accept-ranges": "bytes",
|
|
1294
|
+
"content-disposition": `${download || mimeType === "text/html" ? "attachment" : "inline"}; filename="${filename}"`,
|
|
1295
|
+
"content-length": String(stats.size === 0 ? 0 : end - start + 1),
|
|
1296
|
+
"content-type": mimeType,
|
|
1297
|
+
"x-content-type-options": "nosniff"
|
|
1298
|
+
});
|
|
1299
|
+
if (partial) headers.set("content-range", `bytes ${String(start)}-${String(end)}/${String(stats.size)}`);
|
|
1300
|
+
if (stats.size === 0) return new Response(null, {
|
|
1301
|
+
status: 200,
|
|
1302
|
+
headers
|
|
1303
|
+
});
|
|
1304
|
+
const body = node_stream.Readable.toWeb(node_fs.default.createReadStream(resolved, {
|
|
1305
|
+
start,
|
|
1306
|
+
end
|
|
1307
|
+
}));
|
|
1308
|
+
return new Response(body, {
|
|
1309
|
+
status: partial ? 206 : 200,
|
|
1310
|
+
headers
|
|
1311
|
+
});
|
|
1312
|
+
}
|
|
1313
|
+
/** The named export a host imports from this package's built hub entry. */
|
|
1314
|
+
const api = {
|
|
1315
|
+
basePath: WORKFLOW_API_BASE_PATH,
|
|
1316
|
+
start(_context) {
|
|
1317
|
+
const app = createWorkflowHubApi();
|
|
1318
|
+
return {
|
|
1319
|
+
fetch: (request) => app.fetch(request),
|
|
1320
|
+
close: () => void 0
|
|
1321
|
+
};
|
|
1322
|
+
}
|
|
1323
|
+
};
|
|
1324
|
+
//#endregion
|
|
1325
|
+
//#region src/extensions/workspaces/sessions/(backend)/_lib/index.server.ts
|
|
1326
|
+
var index_server_default$1 = (({ agent, host }) => ({
|
|
1327
|
+
api: [api],
|
|
1328
|
+
...agent ? createWorkflowServerRuntime(agent, host) : {}
|
|
1329
|
+
}));
|
|
1330
|
+
//#endregion
|
|
1331
|
+
//#region src/extensions/workspaces/sessions/(backend)/root.server.ts
|
|
1332
|
+
var root_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoot)((context) => {
|
|
1333
|
+
const value = index_server_default$1(context);
|
|
1334
|
+
return {
|
|
1335
|
+
value,
|
|
1336
|
+
services: value.services,
|
|
1337
|
+
activities: value.activities,
|
|
1338
|
+
onStart: value.onStart,
|
|
1339
|
+
onStop: value.onStop,
|
|
1340
|
+
onDispose: value.onDispose
|
|
1341
|
+
};
|
|
1342
|
+
});
|
|
1343
|
+
//#endregion
|
|
1344
|
+
//#region src/services/workflowCatalogChannel/index.ts
|
|
1345
|
+
/**
|
|
1346
|
+
* The workflow catalog channel. Durable state seeds a session once, then
|
|
1347
|
+
* session lifecycle events deliver updates over the direct event bus.
|
|
1348
|
+
*/
|
|
1349
|
+
function createWorkflowCatalogChannel(options = {}) {
|
|
1350
|
+
const reader = createWorkflowCatalogReader(options.deps ?? defaultCatalogDeps());
|
|
1351
|
+
return {
|
|
1352
|
+
frameType: WORKFLOW_CATALOG_TYPE,
|
|
1353
|
+
start(host) {
|
|
1354
|
+
const scopes = /* @__PURE__ */ new Map();
|
|
1355
|
+
const latest = /* @__PURE__ */ new Map();
|
|
1356
|
+
const subscriptions = /* @__PURE__ */ new Map();
|
|
1357
|
+
const publish = (scope, payload) => {
|
|
1358
|
+
latest.set(scope.sessionId, payload);
|
|
1359
|
+
host.publish(scope.sessionId, payload);
|
|
1360
|
+
};
|
|
1361
|
+
const readInitial = async (scope) => {
|
|
1362
|
+
let payload;
|
|
1363
|
+
try {
|
|
1364
|
+
payload = {
|
|
1365
|
+
cwd: scope.cwd,
|
|
1366
|
+
workflows: presentWorkflowCatalog(await reader.read(scope.cwd))
|
|
1367
|
+
};
|
|
1368
|
+
} catch (error) {
|
|
1369
|
+
const warning = error instanceof Error ? error.message : String(error);
|
|
1370
|
+
payload = {
|
|
1371
|
+
cwd: scope.cwd,
|
|
1372
|
+
workflows: [],
|
|
1373
|
+
warning
|
|
1374
|
+
};
|
|
1375
|
+
host.onNotice(`workflow catalog for ${scope.cwd} is unavailable (${warning})`);
|
|
1376
|
+
}
|
|
1377
|
+
if (scopes.get(scope.sessionId) === scope) publish(scope, payload);
|
|
1378
|
+
};
|
|
1379
|
+
return {
|
|
1380
|
+
payloadFor(scope) {
|
|
1381
|
+
return scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : void 0;
|
|
1382
|
+
},
|
|
1383
|
+
sessionAdded(scope) {
|
|
1384
|
+
scopes.set(scope.sessionId, scope);
|
|
1385
|
+
subscriptions.get(scope.sessionId)?.();
|
|
1386
|
+
const unsubscribe = host.directEvents.subscribe(WORKFLOW_CATALOG_TYPE, scope.sessionId, (value) => {
|
|
1387
|
+
if (isWorkflowCatalogPayload(value)) publish(scope, value);
|
|
1388
|
+
}, { replayLatest: true });
|
|
1389
|
+
subscriptions.set(scope.sessionId, unsubscribe);
|
|
1390
|
+
readInitial(scope);
|
|
1391
|
+
},
|
|
1392
|
+
sessionRemoved(sessionId) {
|
|
1393
|
+
subscriptions.get(sessionId)?.();
|
|
1394
|
+
subscriptions.delete(sessionId);
|
|
1395
|
+
scopes.delete(sessionId);
|
|
1396
|
+
latest.delete(sessionId);
|
|
1397
|
+
},
|
|
1398
|
+
close() {
|
|
1399
|
+
for (const unsubscribe of subscriptions.values()) unsubscribe();
|
|
1400
|
+
subscriptions.clear();
|
|
1401
|
+
scopes.clear();
|
|
1402
|
+
latest.clear();
|
|
1403
|
+
}
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
};
|
|
1407
|
+
}
|
|
1408
|
+
function isWorkflowCatalogPayload(value) {
|
|
1409
|
+
return typeof value === "object" && value !== null && typeof value.cwd === "string" && Array.isArray(value.workflows);
|
|
1410
|
+
}
|
|
1411
|
+
//#endregion
|
|
1412
|
+
//#region src/services/workflowsHubChannel/index.ts
|
|
1413
|
+
function isWorkflowRunsPayload(value) {
|
|
1414
|
+
return typeof value === "object" && value !== null && Array.isArray(value.runs);
|
|
1415
|
+
}
|
|
1416
|
+
/**
|
|
1417
|
+
* The workflow runs data channel. Durable registry state seeds each session
|
|
1418
|
+
* once; subsequent updates arrive through the host-owned direct event bus.
|
|
1419
|
+
*/
|
|
1420
|
+
function createWorkflowsChannel(options = {}) {
|
|
1421
|
+
const read = options.read ?? readWorkflowRuns;
|
|
1422
|
+
return {
|
|
1423
|
+
frameType: WORKFLOW_RUNS_TYPE,
|
|
1424
|
+
start(host) {
|
|
1425
|
+
const scopes = /* @__PURE__ */ new Map();
|
|
1426
|
+
const latest = /* @__PURE__ */ new Map();
|
|
1427
|
+
const subscriptions = /* @__PURE__ */ new Map();
|
|
1428
|
+
const runsFor = (scope, parsed) => presentWorkflowRuns(parsed.filter((run) => runBelongsToSession(run, scope.sessionId)).map((run) => run.view), Date.now());
|
|
1429
|
+
const publish = (scope, payload) => {
|
|
1430
|
+
latest.set(scope.sessionId, payload);
|
|
1431
|
+
host.publish(scope.sessionId, payload);
|
|
1432
|
+
};
|
|
1433
|
+
return {
|
|
1434
|
+
payloadFor(scope) {
|
|
1435
|
+
return scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : void 0;
|
|
1436
|
+
},
|
|
1437
|
+
sessionAdded(scope) {
|
|
1438
|
+
scopes.set(scope.sessionId, scope);
|
|
1439
|
+
subscriptions.get(scope.sessionId)?.();
|
|
1440
|
+
const unsubscribe = host.directEvents.subscribe(WORKFLOW_RUNS_TYPE, scope.sessionId, (value) => {
|
|
1441
|
+
if (isWorkflowRunsPayload(value)) publish(scope, value);
|
|
1442
|
+
}, { replayLatest: true });
|
|
1443
|
+
subscriptions.set(scope.sessionId, unsubscribe);
|
|
1444
|
+
const payload = { runs: runsFor(scope, read({ environment: scope.environment })) };
|
|
1445
|
+
publish(scope, payload);
|
|
1446
|
+
},
|
|
1447
|
+
sessionRemoved(sessionId) {
|
|
1448
|
+
subscriptions.get(sessionId)?.();
|
|
1449
|
+
subscriptions.delete(sessionId);
|
|
1450
|
+
scopes.delete(sessionId);
|
|
1451
|
+
latest.delete(sessionId);
|
|
1452
|
+
},
|
|
1453
|
+
close() {
|
|
1454
|
+
for (const unsubscribe of subscriptions.values()) unsubscribe();
|
|
1455
|
+
subscriptions.clear();
|
|
1456
|
+
scopes.clear();
|
|
1457
|
+
latest.clear();
|
|
1458
|
+
}
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
};
|
|
1462
|
+
}
|
|
1463
|
+
//#endregion
|
|
1464
|
+
//#region src/extensions/(backend)/_lib/index.server.ts
|
|
1465
|
+
var index_server_default = (({ host }) => host.scope === "session" ? {} : {
|
|
1466
|
+
channels: [createWorkflowsChannel, createWorkflowCatalogChannel],
|
|
1467
|
+
api: [api]
|
|
1468
|
+
});
|
|
1469
|
+
//#endregion
|
|
1470
|
+
//#region src/extensions/(backend)/api/workflow/route.server.ts
|
|
1471
|
+
var route_server_default$1 = (0, _agimon_ai_doompi_core_extensionFile.defineRoutedContribution)((context) => index_server_default(context).api?.[0], { cardinality: "optional" });
|
|
1472
|
+
//#endregion
|
|
1473
|
+
//#region src/extensions/(backend)/channel/workflow-catalog.server.ts
|
|
1474
|
+
var workflow_catalog_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineChannel)(createWorkflowCatalogChannel);
|
|
1475
|
+
//#endregion
|
|
1476
|
+
//#region src/extensions/(backend)/channel/workflows.server.ts
|
|
1477
|
+
var workflows_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineChannel)(createWorkflowsChannel);
|
|
1478
|
+
//#endregion
|
|
1479
|
+
//#region src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.ts
|
|
1480
|
+
var route_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoutedContribution)((context) => context.root.api?.[0], { cardinality: "optional" });
|
|
1481
|
+
//#endregion
|
|
1482
|
+
//#region src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.ts
|
|
1483
|
+
var workflow_launch_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoutedContribution)((context) => context.root.commands?.[0], { cardinality: "optional" });
|
|
1484
|
+
//#endregion
|
|
1485
|
+
//#region src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.ts
|
|
1486
|
+
var session_shutdown_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoutedContribution)((context) => context.root.hooks?.[1], { cardinality: "optional" });
|
|
1487
|
+
//#endregion
|
|
1488
|
+
//#region src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.ts
|
|
1489
|
+
var tool_execution_end_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoutedContribution)((context) => context.root.hooks?.[0], { cardinality: "optional" });
|
|
1490
|
+
//#endregion
|
|
1491
|
+
//#region src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.ts
|
|
1492
|
+
var doompi_author_workflow_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoutedContribution)((context) => context.root.resources?.[0], { cardinality: "optional" });
|
|
1493
|
+
//#endregion
|
|
1494
|
+
//#region src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.ts
|
|
1495
|
+
var doompi_use_workflow_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoutedContribution)((context) => context.root.resources?.[1], { cardinality: "optional" });
|
|
1496
|
+
//#endregion
|
|
1497
|
+
//#region src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.ts
|
|
1498
|
+
var workflow_recovery_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoutedContribution)((context) => context.root.resources?.[2], { cardinality: "optional" });
|
|
1499
|
+
//#endregion
|
|
1500
|
+
//#region src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.ts
|
|
1501
|
+
var launch_workflow_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoutedContribution)((context) => context.root.tools?.[1], { cardinality: "optional" });
|
|
1502
|
+
//#endregion
|
|
1503
|
+
//#region src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.ts
|
|
1504
|
+
var list_workflows_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoutedContribution)((context) => context.root.tools?.[0], { cardinality: "optional" });
|
|
1505
|
+
//#endregion
|
|
1506
|
+
//#region src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.ts
|
|
1507
|
+
var workflow_run_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoutedContribution)((context) => context.root.tools?.[2], { cardinality: "optional" });
|
|
1508
|
+
//#endregion
|
|
22
1509
|
//#region generated/server.ts
|
|
23
1510
|
const at = (value, context) => typeof value === "function" ? value(context) : value;
|
|
24
1511
|
/* v8 ignore next -- generated normalization branch */
|
|
@@ -27,59 +1514,56 @@ const via = (identity, value) => ({
|
|
|
27
1514
|
...identity,
|
|
28
1515
|
...value
|
|
29
1516
|
});
|
|
30
|
-
const facet = (0,
|
|
1517
|
+
const facet = (0, _agimon_ai_doompi_core_serverFacet.defineServerPlugin)({
|
|
31
1518
|
name: "@agimon-ai/doompi-workflow",
|
|
32
1519
|
global: (context) => ({
|
|
33
1520
|
get api() {
|
|
34
|
-
return defined([at(
|
|
1521
|
+
return defined([at(route_server_default$1, context)]);
|
|
35
1522
|
},
|
|
36
1523
|
get channels() {
|
|
37
|
-
return [() => via({ frameType: "workflow_catalog" },
|
|
1524
|
+
return [() => via({ frameType: "workflow_catalog" }, workflow_catalog_server_default()), () => via({ frameType: "workflows" }, workflows_server_default())];
|
|
38
1525
|
}
|
|
39
1526
|
}),
|
|
40
1527
|
workspace: (context) => ({
|
|
41
1528
|
get api() {
|
|
42
|
-
return defined([at(
|
|
1529
|
+
return defined([at(route_server_default$1, context)]);
|
|
43
1530
|
},
|
|
44
1531
|
get channels() {
|
|
45
|
-
return [() => via({ frameType: "workflow_catalog" },
|
|
1532
|
+
return [() => via({ frameType: "workflow_catalog" }, workflow_catalog_server_default()), () => via({ frameType: "workflows" }, workflows_server_default())];
|
|
46
1533
|
}
|
|
47
1534
|
}),
|
|
48
1535
|
session: async (context) => {
|
|
49
|
-
const scopeSession = await
|
|
1536
|
+
const scopeSession = await root_server_default(context);
|
|
50
1537
|
const contextSession = {
|
|
51
1538
|
...context,
|
|
52
1539
|
root: scopeSession.value
|
|
53
1540
|
};
|
|
54
1541
|
return {
|
|
55
|
-
...(0,
|
|
1542
|
+
...(0, _agimon_ai_doompi_core_extensionFile.composeRootHooks)(scopeSession),
|
|
56
1543
|
get api() {
|
|
57
|
-
return defined([at(
|
|
1544
|
+
return defined([at(route_server_default$1, context), at(route_server_default, contextSession)]);
|
|
58
1545
|
},
|
|
59
1546
|
get channels() {
|
|
60
|
-
return [() => via({ frameType: "workflow_catalog" },
|
|
1547
|
+
return [() => via({ frameType: "workflow_catalog" }, workflow_catalog_server_default()), () => via({ frameType: "workflows" }, workflows_server_default())];
|
|
61
1548
|
},
|
|
62
1549
|
get commands() {
|
|
63
|
-
return defined([via({ name: "workflow-launch" }, at(
|
|
1550
|
+
return defined([via({ name: "workflow-launch" }, at(workflow_launch_server_default, contextSession))]);
|
|
64
1551
|
},
|
|
65
1552
|
get hooks() {
|
|
66
|
-
return defined([via({ event: "session_shutdown" }, at(
|
|
1553
|
+
return defined([via({ event: "session_shutdown" }, at(session_shutdown_server_default, contextSession)), via({ event: "tool_execution_end" }, at(tool_execution_end_server_default, contextSession))]);
|
|
67
1554
|
},
|
|
68
1555
|
get resources() {
|
|
69
1556
|
return defined([
|
|
70
|
-
at(
|
|
71
|
-
at(
|
|
72
|
-
at(
|
|
1557
|
+
at(doompi_author_workflow_server_default, contextSession),
|
|
1558
|
+
at(doompi_use_workflow_server_default, contextSession),
|
|
1559
|
+
at(workflow_recovery_server_default, contextSession)
|
|
73
1560
|
]);
|
|
74
1561
|
},
|
|
75
|
-
get toolRestrictions() {
|
|
76
|
-
return defined([at(require_workflow_server.default, contextSession)]);
|
|
77
|
-
},
|
|
78
1562
|
get tools() {
|
|
79
1563
|
return defined([
|
|
80
|
-
via({ name: "launch_workflow" }, at(
|
|
81
|
-
via({ name: "list_workflows" }, at(
|
|
82
|
-
via({ name: "workflow_run" }, at(
|
|
1564
|
+
via({ name: "launch_workflow" }, at(launch_workflow_server_default, contextSession)),
|
|
1565
|
+
via({ name: "list_workflows" }, at(list_workflows_server_default, contextSession)),
|
|
1566
|
+
via({ name: "workflow_run" }, at(workflow_run_server_default, contextSession))
|
|
83
1567
|
]);
|
|
84
1568
|
},
|
|
85
1569
|
services: [...scopeSession.services ?? []],
|