@agimon-ai/doompi-workflow 0.0.1-alpha.70 → 0.0.1-alpha.72
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/README.md +13 -0
- package/dist/api-contracts.cjs +1 -0
- package/dist/api-contracts.d.cts +2 -0
- package/dist/api-contracts.d.mts +2 -0
- package/dist/api-contracts.mjs +1 -0
- package/dist/extensions/pi.cjs +2 -1
- package/dist/extensions/pi.cjs.map +1 -0
- package/dist/extensions/pi.d.cts +6 -2
- package/dist/extensions/pi.d.cts.map +1 -0
- package/dist/extensions/pi.d.mts +6 -2
- package/dist/extensions/pi.d.mts.map +1 -0
- package/dist/extensions/pi.mjs +2 -1
- package/dist/extensions/pi.mjs.map +1 -0
- package/dist/extensions/server.cjs +2 -0
- package/dist/extensions/server.cjs.map +1 -0
- package/dist/extensions/server.d.cts +5 -0
- package/dist/extensions/server.d.cts.map +1 -0
- package/dist/extensions/server.d.mts +5 -0
- package/dist/extensions/server.d.mts.map +1 -0
- package/dist/extensions/server.mjs +2 -0
- package/dist/extensions/server.mjs.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +2 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.mjs +1 -1
- package/dist/src/constants/workflow.cjs +2 -0
- package/dist/src/constants/workflow.cjs.map +1 -0
- package/dist/src/constants/workflow.mjs +2 -0
- package/dist/src/constants/workflow.mjs.map +1 -0
- package/dist/src/controllers/serverRuntime.cjs +2 -0
- package/dist/src/controllers/serverRuntime.cjs.map +1 -0
- package/dist/src/controllers/serverRuntime.mjs +2 -0
- package/dist/src/controllers/serverRuntime.mjs.map +1 -0
- package/dist/src/controllers/workflowCatalogChannel.cjs +2 -0
- package/dist/src/controllers/workflowCatalogChannel.cjs.map +1 -0
- package/dist/src/controllers/workflowCatalogChannel.mjs +2 -0
- package/dist/src/controllers/workflowCatalogChannel.mjs.map +1 -0
- package/dist/src/controllers/workflowHubApi.cjs +2 -0
- package/dist/src/controllers/workflowHubApi.cjs.map +1 -0
- package/dist/src/controllers/workflowHubApi.mjs +2 -0
- package/dist/src/controllers/workflowHubApi.mjs.map +1 -0
- package/dist/src/controllers/workflowsHubChannel.cjs +2 -0
- package/dist/src/controllers/workflowsHubChannel.cjs.map +1 -0
- package/dist/src/controllers/workflowsHubChannel.mjs +2 -0
- package/dist/src/controllers/workflowsHubChannel.mjs.map +1 -0
- package/dist/src/schemas/apiContracts.cjs +2 -0
- package/dist/src/schemas/apiContracts.cjs.map +1 -0
- package/dist/src/schemas/apiContracts.d.cts +53 -0
- package/dist/src/schemas/apiContracts.d.cts.map +1 -0
- package/dist/src/schemas/apiContracts.d.mts +53 -0
- package/dist/src/schemas/apiContracts.d.mts.map +1 -0
- package/dist/src/schemas/apiContracts.mjs +2 -0
- package/dist/src/schemas/apiContracts.mjs.map +1 -0
- package/dist/src/schemas/workflowPi.cjs.map +1 -0
- package/dist/src/schemas/workflowPi.d.cts +1 -0
- package/dist/src/schemas/workflowPi.d.mts +1 -0
- package/dist/{schemas/workflowPi.cjs.map → src/schemas/workflowPi.mjs.map} +1 -1
- package/dist/src/services/backgroundWork/index.cjs +2 -0
- package/dist/src/services/backgroundWork/index.cjs.map +1 -0
- package/dist/src/services/backgroundWork/index.mjs +2 -0
- package/dist/src/services/backgroundWork/index.mjs.map +1 -0
- package/dist/{adapters/pi/workflow/piToolBridge.cjs → src/services/piToolBridge/index.cjs} +1 -1
- package/dist/src/services/piToolBridge/index.cjs.map +1 -0
- package/dist/{adapters/pi/workflow/piToolBridge.mjs → src/services/piToolBridge/index.mjs} +1 -1
- package/dist/src/services/piToolBridge/index.mjs.map +1 -0
- package/dist/{services/webWorkflowCatalog.cjs → src/services/webWorkflowCatalog/index.cjs} +1 -1
- package/dist/src/services/webWorkflowCatalog/index.cjs.map +1 -0
- package/dist/{services/webWorkflowCatalog.mjs → src/services/webWorkflowCatalog/index.mjs} +1 -1
- package/dist/src/services/webWorkflowCatalog/index.mjs.map +1 -0
- package/dist/src/services/workflowCatalogDeps/index.cjs +2 -0
- package/dist/src/services/workflowCatalogDeps/index.cjs.map +1 -0
- package/dist/src/services/workflowCatalogDeps/index.mjs +2 -0
- package/dist/src/services/workflowCatalogDeps/index.mjs.map +1 -0
- package/dist/src/services/workflowExecution/index.cjs +2 -0
- package/dist/src/services/workflowExecution/index.cjs.map +1 -0
- package/dist/src/services/workflowExecution/index.d.cts +6 -0
- package/dist/src/services/workflowExecution/index.d.mts +6 -0
- package/dist/src/services/workflowExecution/index.mjs +2 -0
- package/dist/src/services/workflowExecution/index.mjs.map +1 -0
- package/dist/src/services/workflowFence/index.cjs +2 -0
- package/dist/src/services/workflowFence/index.cjs.map +1 -0
- package/dist/src/services/workflowFence/index.mjs +2 -0
- package/dist/src/services/workflowFence/index.mjs.map +1 -0
- package/dist/{services/workflowLaunchCommand.cjs → src/services/workflowLaunchCommand/index.cjs} +1 -1
- package/dist/src/services/workflowLaunchCommand/index.cjs.map +1 -0
- package/dist/src/services/workflowLaunchCommand/index.d.cts +52 -0
- package/dist/src/services/workflowLaunchCommand/index.d.cts.map +1 -0
- package/dist/src/services/workflowLaunchCommand/index.d.mts +52 -0
- package/dist/src/services/workflowLaunchCommand/index.d.mts.map +1 -0
- package/dist/{services/workflowLaunchCommand.mjs → src/services/workflowLaunchCommand/index.mjs} +1 -1
- package/dist/src/services/workflowLaunchCommand/index.mjs.map +1 -0
- package/dist/src/services/workflowLauncher/index.cjs +2 -0
- package/dist/{adapters/pi/workflow/workflowLauncher.mjs.map → src/services/workflowLauncher/index.cjs.map} +1 -1
- package/dist/src/services/workflowLauncher/index.mjs +2 -0
- package/dist/src/services/workflowLauncher/index.mjs.map +1 -0
- package/dist/{services/workflowNarration.cjs → src/services/workflowNarration/index.cjs} +1 -1
- package/dist/{services/workflowNarration.cjs.map → src/services/workflowNarration/index.cjs.map} +1 -1
- package/dist/{services/workflowNarration.mjs → src/services/workflowNarration/index.mjs} +1 -1
- package/dist/{services/workflowNarration.mjs.map → src/services/workflowNarration/index.mjs.map} +1 -1
- package/dist/src/services/workflowResource/index.cjs +2 -0
- package/dist/src/services/workflowResource/index.cjs.map +1 -0
- package/dist/src/services/workflowResource/index.mjs +2 -0
- package/dist/src/services/workflowResource/index.mjs.map +1 -0
- package/dist/{services/workflowRuns.cjs → src/services/workflowRuns/index.cjs} +1 -1
- package/dist/src/services/workflowRuns/index.cjs.map +1 -0
- package/dist/{services/workflowRuns.mjs → src/services/workflowRuns/index.mjs} +1 -1
- package/dist/src/services/workflowRuns/index.mjs.map +1 -0
- package/dist/{services/workflowTerminal.cjs → src/services/workflowTerminal/index.cjs} +1 -1
- package/dist/src/services/workflowTerminal/index.cjs.map +1 -0
- package/dist/{services/workflowTerminal.mjs → src/services/workflowTerminal/index.mjs} +1 -1
- package/dist/src/services/workflowTerminal/index.mjs.map +1 -0
- package/dist/src/services/workflowWatcher/index.cjs +2 -0
- package/dist/src/services/workflowWatcher/index.cjs.map +1 -0
- package/dist/src/services/workflowWatcher/index.mjs +2 -0
- package/dist/src/services/workflowWatcher/index.mjs.map +1 -0
- package/dist/src/tools/workflowTools.cjs +5 -0
- package/dist/src/tools/workflowTools.cjs.map +1 -0
- package/dist/src/tools/workflowTools.mjs +5 -0
- package/dist/src/tools/workflowTools.mjs.map +1 -0
- package/dist/src/tui/leader.cjs +2 -0
- package/dist/src/tui/leader.cjs.map +1 -0
- package/dist/src/tui/leader.mjs +2 -0
- package/dist/src/tui/leader.mjs.map +1 -0
- package/dist/src/tui/workflow/doomOverlay.cjs.map +1 -0
- package/dist/src/tui/workflow/doomOverlay.mjs.map +1 -0
- package/dist/src/tui/workflow/overlayText.cjs.map +1 -0
- package/dist/src/tui/workflow/overlayText.mjs.map +1 -0
- package/dist/src/tui/workflow/rendering.cjs.map +1 -0
- package/dist/src/tui/workflow/rendering.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowCatalog.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowCatalog.mjs.map +1 -0
- package/dist/{tui → src/tui}/workflow/workflowFinishedMessage.cjs +1 -1
- package/dist/src/tui/workflow/workflowFinishedMessage.cjs.map +1 -0
- package/dist/{tui → src/tui}/workflow/workflowFinishedMessage.mjs +1 -1
- package/dist/src/tui/workflow/workflowFinishedMessage.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowInspector.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowInspector.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowOverlay.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowOverlay.mjs.map +1 -0
- package/dist/{tui/workflow/workflowPicker.mjs.map → src/tui/workflow/workflowPicker.cjs.map} +1 -1
- package/dist/src/tui/workflow/workflowPicker.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowProgressOverlay.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowProgressOverlay.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowPrompt.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowPrompt.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowRunPanel.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowRunPanel.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowStatusRow.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowStatusRow.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowStepMessage.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowStepMessage.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowToolRender.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowToolRender.mjs.map +1 -0
- package/dist/src/tui/workflowRuntime.cjs +9 -0
- package/dist/src/tui/workflowRuntime.cjs.map +1 -0
- package/dist/src/tui/workflowRuntime.d.cts +33 -0
- package/dist/src/tui/workflowRuntime.d.cts.map +1 -0
- package/dist/src/tui/workflowRuntime.d.mts +33 -0
- package/dist/src/tui/workflowRuntime.d.mts.map +1 -0
- package/dist/src/tui/workflowRuntime.mjs +9 -0
- package/dist/src/tui/workflowRuntime.mjs.map +1 -0
- package/dist/src/types/webWorkflowTerminal.cjs +2 -0
- package/dist/src/types/webWorkflowTerminal.cjs.map +1 -0
- package/dist/src/types/webWorkflowTerminal.mjs +2 -0
- package/dist/src/types/webWorkflowTerminal.mjs.map +1 -0
- package/dist/src/types/webWorkflows.cjs.map +1 -0
- package/dist/src/types/webWorkflows.mjs.map +1 -0
- package/package.json +28 -22
- package/src/extensions/web.ts +80 -0
- package/src/types/webWorkflowTerminal.ts +2 -2
- package/src/types/webWorkflows.ts +5 -0
- package/src/web/api/terminalApi.ts +3 -4
- package/src/web/components/ArtifactsPane.tsx +5 -4
- package/src/web/components/LaunchWorkflowDialog.tsx +5 -4
- package/src/web/components/StepTerminalPanel.tsx +6 -5
- package/src/web/components/WorkflowCatalogDrawer.tsx +3 -2
- package/src/web/components/WorkflowToolMessage.tsx +3 -2
- package/src/web/components/WorkflowsActivitySection.tsx +6 -5
- package/src/web/components/WorkflowsPanel.tsx +13 -12
- package/src/web/lib/launchLine.ts +1 -1
- package/src/web/lib/workflowActivity.ts +2 -2
- package/src/web/lib/workflowToolRender.ts +1 -1
- package/src/web/stores/catalogStore.ts +3 -2
- package/src/web/stores/workflowsStore.ts +5 -4
- package/src/web/tsconfig.json +1 -1
- package/dist/adapters/pi/extension.cjs +0 -2
- package/dist/adapters/pi/extension.cjs.map +0 -1
- package/dist/adapters/pi/extension.d.cts +0 -8
- package/dist/adapters/pi/extension.d.cts.map +0 -1
- package/dist/adapters/pi/extension.d.mts +0 -8
- package/dist/adapters/pi/extension.d.mts.map +0 -1
- package/dist/adapters/pi/extension.mjs +0 -2
- package/dist/adapters/pi/extension.mjs.map +0 -1
- package/dist/adapters/pi/leader.cjs +0 -2
- package/dist/adapters/pi/leader.cjs.map +0 -1
- package/dist/adapters/pi/leader.mjs +0 -2
- package/dist/adapters/pi/leader.mjs.map +0 -1
- package/dist/adapters/pi/workflow/piExtension.cjs +0 -9
- package/dist/adapters/pi/workflow/piExtension.cjs.map +0 -1
- package/dist/adapters/pi/workflow/piExtension.mjs +0 -9
- package/dist/adapters/pi/workflow/piExtension.mjs.map +0 -1
- package/dist/adapters/pi/workflow/piToolBridge.cjs.map +0 -1
- package/dist/adapters/pi/workflow/piToolBridge.mjs.map +0 -1
- package/dist/adapters/pi/workflow/piTools.cjs +0 -5
- package/dist/adapters/pi/workflow/piTools.cjs.map +0 -1
- package/dist/adapters/pi/workflow/piTools.mjs +0 -5
- package/dist/adapters/pi/workflow/piTools.mjs.map +0 -1
- package/dist/adapters/pi/workflow/workflowLauncher.cjs +0 -2
- package/dist/adapters/pi/workflow/workflowLauncher.cjs.map +0 -1
- package/dist/adapters/pi/workflow/workflowLauncher.mjs +0 -2
- package/dist/adapters/workflowCatalogChannel.cjs +0 -2
- package/dist/adapters/workflowCatalogChannel.cjs.map +0 -1
- package/dist/adapters/workflowCatalogChannel.d.cts +0 -22
- package/dist/adapters/workflowCatalogChannel.d.cts.map +0 -1
- package/dist/adapters/workflowCatalogChannel.d.mts +0 -22
- package/dist/adapters/workflowCatalogChannel.d.mts.map +0 -1
- package/dist/adapters/workflowCatalogChannel.mjs +0 -2
- package/dist/adapters/workflowCatalogChannel.mjs.map +0 -1
- package/dist/adapters/workflowHubApi.cjs +0 -2
- package/dist/adapters/workflowHubApi.cjs.map +0 -1
- package/dist/adapters/workflowHubApi.d.cts +0 -23
- package/dist/adapters/workflowHubApi.d.cts.map +0 -1
- package/dist/adapters/workflowHubApi.d.mts +0 -23
- package/dist/adapters/workflowHubApi.d.mts.map +0 -1
- package/dist/adapters/workflowHubApi.mjs +0 -2
- package/dist/adapters/workflowHubApi.mjs.map +0 -1
- package/dist/adapters/workflowWatcher.cjs +0 -2
- package/dist/adapters/workflowWatcher.cjs.map +0 -1
- package/dist/adapters/workflowWatcher.d.cts +0 -23
- package/dist/adapters/workflowWatcher.d.cts.map +0 -1
- package/dist/adapters/workflowWatcher.d.mts +0 -23
- package/dist/adapters/workflowWatcher.d.mts.map +0 -1
- package/dist/adapters/workflowWatcher.mjs +0 -2
- package/dist/adapters/workflowWatcher.mjs.map +0 -1
- package/dist/adapters/workflowsHubChannel.cjs +0 -2
- package/dist/adapters/workflowsHubChannel.cjs.map +0 -1
- package/dist/adapters/workflowsHubChannel.d.cts +0 -19
- package/dist/adapters/workflowsHubChannel.d.cts.map +0 -1
- package/dist/adapters/workflowsHubChannel.d.mts +0 -19
- package/dist/adapters/workflowsHubChannel.d.mts.map +0 -1
- package/dist/adapters/workflowsHubChannel.mjs +0 -2
- package/dist/adapters/workflowsHubChannel.mjs.map +0 -1
- package/dist/hubApi.cjs +0 -1
- package/dist/hubApi.d.cts +0 -2
- package/dist/hubApi.d.mts +0 -2
- package/dist/hubApi.mjs +0 -1
- package/dist/schemas/workflowPi.mjs.map +0 -1
- package/dist/services/backgroundWork.cjs +0 -2
- package/dist/services/backgroundWork.cjs.map +0 -1
- package/dist/services/backgroundWork.mjs +0 -2
- package/dist/services/backgroundWork.mjs.map +0 -1
- package/dist/services/webWorkflowCatalog.cjs.map +0 -1
- package/dist/services/webWorkflowCatalog.d.cts +0 -48
- package/dist/services/webWorkflowCatalog.d.cts.map +0 -1
- package/dist/services/webWorkflowCatalog.d.mts +0 -48
- package/dist/services/webWorkflowCatalog.d.mts.map +0 -1
- package/dist/services/webWorkflowCatalog.mjs.map +0 -1
- package/dist/services/workflowLaunchCommand.cjs.map +0 -1
- package/dist/services/workflowLaunchCommand.mjs.map +0 -1
- package/dist/services/workflowRuns.cjs.map +0 -1
- package/dist/services/workflowRuns.d.cts +0 -14
- package/dist/services/workflowRuns.d.cts.map +0 -1
- package/dist/services/workflowRuns.d.mts +0 -14
- package/dist/services/workflowRuns.d.mts.map +0 -1
- package/dist/services/workflowRuns.mjs.map +0 -1
- package/dist/services/workflowTerminal.cjs.map +0 -1
- package/dist/services/workflowTerminal.mjs.map +0 -1
- package/dist/tui/workflow/doomOverlay.cjs.map +0 -1
- package/dist/tui/workflow/doomOverlay.mjs.map +0 -1
- package/dist/tui/workflow/overlayText.cjs.map +0 -1
- package/dist/tui/workflow/overlayText.mjs.map +0 -1
- package/dist/tui/workflow/rendering.cjs.map +0 -1
- package/dist/tui/workflow/rendering.mjs.map +0 -1
- package/dist/tui/workflow/workflowCatalog.cjs.map +0 -1
- package/dist/tui/workflow/workflowCatalog.mjs.map +0 -1
- package/dist/tui/workflow/workflowFinishedMessage.cjs.map +0 -1
- package/dist/tui/workflow/workflowFinishedMessage.mjs.map +0 -1
- package/dist/tui/workflow/workflowInspector.cjs.map +0 -1
- package/dist/tui/workflow/workflowInspector.mjs.map +0 -1
- package/dist/tui/workflow/workflowOverlay.cjs.map +0 -1
- package/dist/tui/workflow/workflowOverlay.mjs.map +0 -1
- package/dist/tui/workflow/workflowPicker.cjs.map +0 -1
- package/dist/tui/workflow/workflowProgressOverlay.cjs.map +0 -1
- package/dist/tui/workflow/workflowProgressOverlay.mjs.map +0 -1
- package/dist/tui/workflow/workflowPrompt.cjs.map +0 -1
- package/dist/tui/workflow/workflowPrompt.mjs.map +0 -1
- package/dist/tui/workflow/workflowRunPanel.cjs.map +0 -1
- package/dist/tui/workflow/workflowRunPanel.mjs.map +0 -1
- package/dist/tui/workflow/workflowStatusRow.cjs.map +0 -1
- package/dist/tui/workflow/workflowStatusRow.mjs.map +0 -1
- package/dist/tui/workflow/workflowStepMessage.cjs.map +0 -1
- package/dist/tui/workflow/workflowStepMessage.mjs.map +0 -1
- package/dist/tui/workflow/workflowToolRender.cjs.map +0 -1
- package/dist/tui/workflow/workflowToolRender.mjs.map +0 -1
- package/dist/types/index.cjs +0 -2
- package/dist/types/index.cjs.map +0 -1
- package/dist/types/index.mjs +0 -2
- package/dist/types/index.mjs.map +0 -1
- package/dist/types/webWorkflowTerminal.cjs +0 -2
- package/dist/types/webWorkflowTerminal.cjs.map +0 -1
- package/dist/types/webWorkflowTerminal.mjs +0 -2
- package/dist/types/webWorkflowTerminal.mjs.map +0 -1
- package/dist/types/webWorkflows.cjs.map +0 -1
- package/dist/types/webWorkflows.d.cts +0 -94
- package/dist/types/webWorkflows.d.cts.map +0 -1
- package/dist/types/webWorkflows.d.mts +0 -94
- package/dist/types/webWorkflows.d.mts.map +0 -1
- package/dist/types/webWorkflows.mjs.map +0 -1
- package/dist/webHub.cjs +0 -1
- package/dist/webHub.d.cts +0 -3
- package/dist/webHub.d.mts +0 -3
- package/dist/webHub.mjs +0 -1
- package/src/exports/webClient.ts +0 -1
- package/src/web/index.ts +0 -74
- /package/dist/{schemas → src/schemas}/workflowPi.cjs +0 -0
- /package/dist/{schemas → src/schemas}/workflowPi.mjs +0 -0
- /package/dist/{tui → src/tui}/workflow/doomOverlay.cjs +0 -0
- /package/dist/{tui → src/tui}/workflow/doomOverlay.mjs +0 -0
- /package/dist/{tui → src/tui}/workflow/overlayText.cjs +0 -0
- /package/dist/{tui → src/tui}/workflow/overlayText.mjs +0 -0
- /package/dist/{tui → src/tui}/workflow/rendering.cjs +0 -0
- /package/dist/{tui → src/tui}/workflow/rendering.mjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowCatalog.cjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowCatalog.mjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowInspector.cjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowInspector.mjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowOverlay.cjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowOverlay.mjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowPicker.cjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowPicker.mjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowProgressOverlay.cjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowProgressOverlay.mjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowPrompt.cjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowPrompt.mjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowRunPanel.cjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowRunPanel.mjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowStatusRow.cjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowStatusRow.mjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowStepMessage.cjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowStepMessage.mjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowToolRender.cjs +0 -0
- /package/dist/{tui → src/tui}/workflow/workflowToolRender.mjs +0 -0
- /package/dist/{types → src/types}/webWorkflows.cjs +0 -0
- /package/dist/{types → src/types}/webWorkflows.mjs +0 -0
package/README.md
CHANGED
|
@@ -128,3 +128,16 @@ The hub-side data source ships behind the `./web-hub` subpath and reads the work
|
|
|
128
128
|
|
|
129
129
|
MIT, except the `src/web` directory, which is source available under the DoomPi Web License (see
|
|
130
130
|
`src/web/LICENSE`): free to use, including commercially, but not to redistribute.
|
|
131
|
+
|
|
132
|
+
Workflow's host entries live in `src/extensions/pi.ts`, `server.ts`, and `web.ts`.
|
|
133
|
+
`src/exports` exposes reusable package APIs. Controllers declare server APIs and
|
|
134
|
+
contributions, tools declare native tools, and each service has its own folder.
|
|
135
|
+
Terminal presentation and its session coordinator live in `src/tui`.
|
|
136
|
+
|
|
137
|
+
The Pi helper owns registrations and service fibers. The Workflow runtime returns
|
|
138
|
+
commands, events, mode ownership, and tool dependencies. Session startup begins
|
|
139
|
+
readiness discovery; dependent calls await that session's readiness. On shutdown,
|
|
140
|
+
`onStop` interrupts inline runs and clears session resources, while `onDispose`
|
|
141
|
+
also handles startup failure. Both use the same idempotent cleanup. A generation
|
|
142
|
+
fence prevents retired callbacks from sending messages or updating the UI; only
|
|
143
|
+
explicit resource teardown may use a retired UI context.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./src/schemas/apiContracts.cjs");exports.apiContracts=e.apiContracts,exports.default=e.apiContracts;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{apiContracts as e}from"./src/schemas/apiContracts.mjs";export{e as apiContracts,e as default};
|
package/dist/extensions/pi.cjs
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
const e=require("../
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../src/constants/workflow.cjs"),t=require("../src/services/workflowFence/index.cjs"),n=require("../src/services/workflowResource/index.cjs"),r=require("../src/tools/workflowTools.cjs"),i=require("../src/tui/leader.cjs"),a=require("../src/tui/workflow/workflowToolRender.cjs"),o=require("../src/tui/workflowRuntime.cjs");let s=require("@agimon-ai/doompi-core/pi-extension"),c=require("@agimon-ai/doompi-core/skills"),l=require("@agimon-ai/doompi-core/ui-hub");const u=(0,s.definePiExtension)(e.PACKAGE_SOURCE,({pi:u,context:d,options:f,signal:p})=>{let m=f?.environment??Object.freeze({...process.env}),h=t.isWorkflowDispatcherProcess(m),g=t.createWorkflowFence(u,p),_=!1,v,y=o.createWorkflowPiRuntime(g.pi,{...f,environment:m,cordis:d,initialMode:h||f?.initialMode,isActive:g.isCurrentInvocation,runCleanup:g.runCleanup,onModeChange(e){_=e,v?.setMode(e),f?.onModeChange?.(e)}}),b=r.createWorkflowTools(y.toolDependencies,e=>({renderCall:(t,n)=>a.renderWorkflowToolCall(e,t,n),renderResult:(t,n,r,i)=>a.renderWorkflowToolResult(e,i.args,t,{...n,isError:i.isError},r)})),x=h?t.dispatcherTools(b,t.resolveDispatcherParentSession(m),m):b;return{services:[...y.services??[],t=>{t.inject([c.DOOM_SKILL_SOURCES_SERVICE],t=>{let r=n.workflowSkillDirectory(),i=(0,c.requireDoomSkillSourcesService)(t).register({source:e.PACKAGE_SOURCE,directories:[r]});return()=>i.dispose()}),h||t.inject([l.DOOM_UI_HUB_SERVICE],e=>{let t=i.registerLeaderContribution((0,l.requireDoomUiHub)(e),_);return v=t,()=>{t.dispose(),v===t&&(v=void 0)}})}],tools:x.map(e=>(0,s.definePiTool)(g.tool({...e,async execute(...t){return await y.waitForReadiness(t[2]),e.execute(...t)}}))),commands:y.commands.map(([e,t])=>g.command(e,t)),shortcuts:y.shortcuts?.map(([e,t])=>g.shortcut(e,t)),events:g.events(y.events??{}),messageRenderers:y.messageRenderers,toolRestrictions:[...y.toolRestrictions??[],...h?[{source:`${e.PACKAGE_SOURCE}/dispatcher`,restrict:t.dispatcherToolRestriction()}]:[]],resources:h?[]:[{source:e.PACKAGE_SOURCE,moduleUrl:require("url").pathToFileURL(__filename).href,skills:[{name:`doompi-author-workflow`,description:`Author DoomPi workflow definitions, job dependencies and host-executed steps.`},{name:`doompi-use-workflow`,description:`Discover, launch, monitor, control and recover DoomPi workflow runs.`}]}],async onStop(){g.beginDisposal(),await g.runCleanup(()=>y.dispose())},async onDispose(){g.beginDisposal();try{await g.runCleanup(()=>y.dispose())}finally{g.finishDisposal()}}}});exports.default=u,exports.workflowExtension=u;
|
|
2
|
+
//# sourceMappingURL=pi.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.cjs","names":["definePiExtension","PACKAGE_SOURCE","isWorkflowDispatcherProcess","createWorkflowFence","createWorkflowPiRuntime","createWorkflowTools","renderWorkflowToolCall","renderWorkflowToolResult","dispatcherTools","resolveDispatcherParentSession","DOOM_SKILL_SOURCES_SERVICE","workflowSkillDirectory","requireDoomSkillSourcesService","DOOM_UI_HUB_SERVICE","registerLeaderContribution","requireDoomUiHub","definePiTool","dispatcherToolRestriction"],"sources":["../../src/extensions/pi.ts"],"sourcesContent":["import { definePiExtension, definePiTool } from '@agimon-ai/doompi-core/pi-extension';\nimport { DOOM_SKILL_SOURCES_SERVICE, requireDoomSkillSourcesService } from '@agimon-ai/doompi-core/skills';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-core/ui-hub';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport { PACKAGE_SOURCE } from '../constants/workflow';\nimport {\n createWorkflowFence,\n dispatcherTools,\n dispatcherToolRestriction,\n isWorkflowDispatcherProcess,\n resolveDispatcherParentSession,\n} from '../services/workflowFence';\nimport { workflowSkillDirectory } from '../services/workflowResource';\nimport { createWorkflowTools } from '../tools/workflowTools';\nimport { registerLeaderContribution } from '../tui/leader';\nimport { renderWorkflowToolCall, renderWorkflowToolResult } from '../tui/workflow/workflowToolRender';\nimport { createWorkflowPiRuntime, type WorkflowPiExtensionOptions } from '../tui/workflowRuntime';\n\nexport const workflowExtension = definePiExtension<Partial<WorkflowPiExtensionOptions>>(\n PACKAGE_SOURCE,\n ({ pi, context, options, signal }) => {\n const environment = options?.environment ?? Object.freeze({ ...process.env });\n const dispatcher = isWorkflowDispatcherProcess(environment);\n const fence = createWorkflowFence(pi, signal);\n let workflowMode = false;\n let leader: ReturnType<typeof registerLeaderContribution> | undefined;\n const runtime = createWorkflowPiRuntime(fence.pi, {\n ...options,\n environment,\n cordis: context,\n initialMode: dispatcher || options?.initialMode,\n isActive: fence.isCurrentInvocation,\n runCleanup: fence.runCleanup,\n onModeChange(enabled) {\n workflowMode = enabled;\n leader?.setMode(enabled);\n options?.onModeChange?.(enabled);\n },\n });\n const nativeTools = createWorkflowTools(runtime.toolDependencies, (name) => ({\n renderCall: (args, theme) => renderWorkflowToolCall(name, args as Record<string, unknown>, theme),\n renderResult: (result, renderOptions, theme, renderContext) =>\n renderWorkflowToolResult(\n name,\n renderContext.args as Record<string, unknown>,\n result,\n { ...renderOptions, isError: renderContext.isError },\n theme,\n ),\n }));\n const selectedTools = dispatcher\n ? dispatcherTools(nativeTools, resolveDispatcherParentSession(environment), environment)\n : nativeTools;\n return {\n services: [\n ...(runtime.services ?? []),\n (cordis: Context) => {\n cordis.inject([DOOM_SKILL_SOURCES_SERVICE], (skillContext) => {\n const directory = workflowSkillDirectory();\n const contribution = requireDoomSkillSourcesService(skillContext).register({\n source: PACKAGE_SOURCE,\n directories: [directory],\n });\n return () => contribution.dispose();\n });\n if (!dispatcher)\n cordis.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n const contribution = registerLeaderContribution(requireDoomUiHub(uiContext), workflowMode);\n leader = contribution;\n return () => {\n contribution.dispose();\n if (leader === contribution) leader = undefined;\n };\n });\n },\n ],\n tools: selectedTools.map((tool) =>\n definePiTool(\n fence.tool({\n ...tool,\n async execute(...args) {\n await runtime.waitForReadiness(args[2]);\n return tool.execute(...args);\n },\n }),\n ),\n ),\n commands: runtime.commands.map(([name, command]) => fence.command(name, command)),\n shortcuts: runtime.shortcuts?.map(([key, shortcut]) => fence.shortcut(key, shortcut)),\n events: fence.events(runtime.events ?? {}),\n messageRenderers: runtime.messageRenderers,\n\n toolRestrictions: [\n ...(runtime.toolRestrictions ?? []),\n ...(dispatcher ? [{ source: `${PACKAGE_SOURCE}/dispatcher`, restrict: dispatcherToolRestriction() }] : []),\n ],\n resources: dispatcher\n ? []\n : [\n {\n source: PACKAGE_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-author-workflow',\n description: 'Author DoomPi workflow definitions, job dependencies and host-executed steps.',\n },\n {\n name: 'doompi-use-workflow',\n description: 'Discover, launch, monitor, control and recover DoomPi workflow runs.',\n },\n ],\n },\n ],\n async onStop() {\n fence.beginDisposal();\n await fence.runCleanup(() => runtime.dispose());\n },\n async onDispose() {\n fence.beginDisposal();\n try {\n await fence.runCleanup(() => runtime.dispose());\n } finally {\n fence.finishDisposal();\n }\n },\n };\n },\n);\nexport default workflowExtension;\n"],"mappings":"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"}
|
package/dist/extensions/pi.d.cts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { WorkflowPiExtensionOptions } from "../src/tui/workflowRuntime.cjs";
|
|
2
|
+
//#region src/extensions/pi.d.ts
|
|
3
|
+
export declare const workflowExtension: import("@agimon-ai/doompi-core/runtime-pi-extension").DefinedPiExtension<Partial<WorkflowPiExtensionOptions>>;
|
|
4
|
+
//#endregion
|
|
5
|
+
export { workflowExtension as default };
|
|
6
|
+
//# sourceMappingURL=pi.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.d.cts","names":[],"sources":["../../src/extensions/pi.ts"],"mappings":";;qBAmBa,yEAAiB,mBAAA,QAAA"}
|
package/dist/extensions/pi.d.mts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { WorkflowPiExtensionOptions } from "../src/tui/workflowRuntime.mjs";
|
|
2
|
+
//#region src/extensions/pi.d.ts
|
|
3
|
+
export declare const workflowExtension: import("@agimon-ai/doompi-core/runtime-pi-extension").DefinedPiExtension<Partial<WorkflowPiExtensionOptions>>;
|
|
4
|
+
//#endregion
|
|
5
|
+
export { workflowExtension as default };
|
|
6
|
+
//# sourceMappingURL=pi.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.d.mts","names":[],"sources":["../../src/extensions/pi.ts"],"mappings":";;qBAmBa,yEAAiB,mBAAA,QAAA"}
|
package/dist/extensions/pi.mjs
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import e from"../
|
|
1
|
+
import{PACKAGE_SOURCE as e}from"../src/constants/workflow.mjs";import{createWorkflowFence as t,dispatcherToolRestriction as n,dispatcherTools as r,isWorkflowDispatcherProcess as i,resolveDispatcherParentSession as a}from"../src/services/workflowFence/index.mjs";import{workflowSkillDirectory as o}from"../src/services/workflowResource/index.mjs";import{createWorkflowTools as s}from"../src/tools/workflowTools.mjs";import{registerLeaderContribution as c}from"../src/tui/leader.mjs";import{renderWorkflowToolCall as l,renderWorkflowToolResult as u}from"../src/tui/workflow/workflowToolRender.mjs";import{createWorkflowPiRuntime as d}from"../src/tui/workflowRuntime.mjs";import{definePiExtension as f,definePiTool as p}from"@agimon-ai/doompi-core/pi-extension";import{DOOM_SKILL_SOURCES_SERVICE as m,requireDoomSkillSourcesService as h}from"@agimon-ai/doompi-core/skills";import{DOOM_UI_HUB_SERVICE as g,requireDoomUiHub as _}from"@agimon-ai/doompi-core/ui-hub";const v=f(e,({pi:f,context:v,options:y,signal:b})=>{let x=y?.environment??Object.freeze({...process.env}),S=i(x),C=t(f,b),w=!1,T,E=d(C.pi,{...y,environment:x,cordis:v,initialMode:S||y?.initialMode,isActive:C.isCurrentInvocation,runCleanup:C.runCleanup,onModeChange(e){w=e,T?.setMode(e),y?.onModeChange?.(e)}}),D=s(E.toolDependencies,e=>({renderCall:(t,n)=>l(e,t,n),renderResult:(t,n,r,i)=>u(e,i.args,t,{...n,isError:i.isError},r)})),O=S?r(D,a(x),x):D;return{services:[...E.services??[],t=>{t.inject([m],t=>{let n=o(),r=h(t).register({source:e,directories:[n]});return()=>r.dispose()}),S||t.inject([g],e=>{let t=c(_(e),w);return T=t,()=>{t.dispose(),T===t&&(T=void 0)}})}],tools:O.map(e=>p(C.tool({...e,async execute(...t){return await E.waitForReadiness(t[2]),e.execute(...t)}}))),commands:E.commands.map(([e,t])=>C.command(e,t)),shortcuts:E.shortcuts?.map(([e,t])=>C.shortcut(e,t)),events:C.events(E.events??{}),messageRenderers:E.messageRenderers,toolRestrictions:[...E.toolRestrictions??[],...S?[{source:`${e}/dispatcher`,restrict:n()}]:[]],resources:S?[]:[{source:e,moduleUrl:import.meta.url,skills:[{name:`doompi-author-workflow`,description:`Author DoomPi workflow definitions, job dependencies and host-executed steps.`},{name:`doompi-use-workflow`,description:`Discover, launch, monitor, control and recover DoomPi workflow runs.`}]}],async onStop(){C.beginDisposal(),await C.runCleanup(()=>E.dispose())},async onDispose(){C.beginDisposal();try{await C.runCleanup(()=>E.dispose())}finally{C.finishDisposal()}}}});export{v as default,v as workflowExtension};
|
|
2
|
+
//# sourceMappingURL=pi.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.mjs","names":[],"sources":["../../src/extensions/pi.ts"],"sourcesContent":["import { definePiExtension, definePiTool } from '@agimon-ai/doompi-core/pi-extension';\nimport { DOOM_SKILL_SOURCES_SERVICE, requireDoomSkillSourcesService } from '@agimon-ai/doompi-core/skills';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-core/ui-hub';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport { PACKAGE_SOURCE } from '../constants/workflow';\nimport {\n createWorkflowFence,\n dispatcherTools,\n dispatcherToolRestriction,\n isWorkflowDispatcherProcess,\n resolveDispatcherParentSession,\n} from '../services/workflowFence';\nimport { workflowSkillDirectory } from '../services/workflowResource';\nimport { createWorkflowTools } from '../tools/workflowTools';\nimport { registerLeaderContribution } from '../tui/leader';\nimport { renderWorkflowToolCall, renderWorkflowToolResult } from '../tui/workflow/workflowToolRender';\nimport { createWorkflowPiRuntime, type WorkflowPiExtensionOptions } from '../tui/workflowRuntime';\n\nexport const workflowExtension = definePiExtension<Partial<WorkflowPiExtensionOptions>>(\n PACKAGE_SOURCE,\n ({ pi, context, options, signal }) => {\n const environment = options?.environment ?? Object.freeze({ ...process.env });\n const dispatcher = isWorkflowDispatcherProcess(environment);\n const fence = createWorkflowFence(pi, signal);\n let workflowMode = false;\n let leader: ReturnType<typeof registerLeaderContribution> | undefined;\n const runtime = createWorkflowPiRuntime(fence.pi, {\n ...options,\n environment,\n cordis: context,\n initialMode: dispatcher || options?.initialMode,\n isActive: fence.isCurrentInvocation,\n runCleanup: fence.runCleanup,\n onModeChange(enabled) {\n workflowMode = enabled;\n leader?.setMode(enabled);\n options?.onModeChange?.(enabled);\n },\n });\n const nativeTools = createWorkflowTools(runtime.toolDependencies, (name) => ({\n renderCall: (args, theme) => renderWorkflowToolCall(name, args as Record<string, unknown>, theme),\n renderResult: (result, renderOptions, theme, renderContext) =>\n renderWorkflowToolResult(\n name,\n renderContext.args as Record<string, unknown>,\n result,\n { ...renderOptions, isError: renderContext.isError },\n theme,\n ),\n }));\n const selectedTools = dispatcher\n ? dispatcherTools(nativeTools, resolveDispatcherParentSession(environment), environment)\n : nativeTools;\n return {\n services: [\n ...(runtime.services ?? []),\n (cordis: Context) => {\n cordis.inject([DOOM_SKILL_SOURCES_SERVICE], (skillContext) => {\n const directory = workflowSkillDirectory();\n const contribution = requireDoomSkillSourcesService(skillContext).register({\n source: PACKAGE_SOURCE,\n directories: [directory],\n });\n return () => contribution.dispose();\n });\n if (!dispatcher)\n cordis.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n const contribution = registerLeaderContribution(requireDoomUiHub(uiContext), workflowMode);\n leader = contribution;\n return () => {\n contribution.dispose();\n if (leader === contribution) leader = undefined;\n };\n });\n },\n ],\n tools: selectedTools.map((tool) =>\n definePiTool(\n fence.tool({\n ...tool,\n async execute(...args) {\n await runtime.waitForReadiness(args[2]);\n return tool.execute(...args);\n },\n }),\n ),\n ),\n commands: runtime.commands.map(([name, command]) => fence.command(name, command)),\n shortcuts: runtime.shortcuts?.map(([key, shortcut]) => fence.shortcut(key, shortcut)),\n events: fence.events(runtime.events ?? {}),\n messageRenderers: runtime.messageRenderers,\n\n toolRestrictions: [\n ...(runtime.toolRestrictions ?? []),\n ...(dispatcher ? [{ source: `${PACKAGE_SOURCE}/dispatcher`, restrict: dispatcherToolRestriction() }] : []),\n ],\n resources: dispatcher\n ? []\n : [\n {\n source: PACKAGE_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-author-workflow',\n description: 'Author DoomPi workflow definitions, job dependencies and host-executed steps.',\n },\n {\n name: 'doompi-use-workflow',\n description: 'Discover, launch, monitor, control and recover DoomPi workflow runs.',\n },\n ],\n },\n ],\n async onStop() {\n fence.beginDisposal();\n await fence.runCleanup(() => runtime.dispose());\n },\n async onDispose() {\n fence.beginDisposal();\n try {\n await fence.runCleanup(() => runtime.dispose());\n } finally {\n fence.finishDisposal();\n }\n },\n };\n },\n);\nexport default workflowExtension;\n"],"mappings":"g8BAmBA,MAAa,EAAoB,EAC/B,GACC,CAAE,KAAI,UAAS,UAAS,YAAa,CACpC,IAAM,EAAc,GAAS,aAAe,OAAO,OAAO,CAAE,GAAG,QAAQ,GAAI,CAAC,EACtE,EAAa,EAA4B,CAAW,EACpD,EAAQ,EAAoB,EAAI,CAAM,EACxC,EAAe,GACf,EACE,EAAU,EAAwB,EAAM,GAAI,CAChD,GAAG,EACH,cACA,OAAQ,EACR,YAAa,GAAc,GAAS,YACpC,SAAU,EAAM,oBAChB,WAAY,EAAM,WAClB,aAAa,EAAS,CACpB,EAAe,EACf,GAAQ,QAAQ,CAAO,EACvB,GAAS,eAAe,CAAO,CACjC,CACF,CAAC,EACK,EAAc,EAAoB,EAAQ,iBAAmB,IAAU,CAC3E,YAAa,EAAM,IAAU,EAAuB,EAAM,EAAiC,CAAK,EAChG,cAAe,EAAQ,EAAe,EAAO,IAC3C,EACE,EACA,EAAc,KACd,EACA,CAAE,GAAG,EAAe,QAAS,EAAc,OAAQ,EACnD,CACF,CACJ,EAAE,EACI,EAAgB,EAClB,EAAgB,EAAa,EAA+B,CAAW,EAAG,CAAW,EACrF,EACJ,MAAO,CACL,SAAU,CACR,GAAI,EAAQ,UAAY,CAAC,EACxB,GAAoB,CACnB,EAAO,OAAO,CAAC,CAA0B,EAAI,GAAiB,CAC5D,IAAM,EAAY,EAAuB,EACnC,EAAe,EAA+B,CAAY,CAAC,CAAC,SAAS,CACzE,OAAQ,EACR,YAAa,CAAC,CAAS,CACzB,CAAC,EACD,UAAa,EAAa,QAAQ,CACpC,CAAC,EACI,GACH,EAAO,OAAO,CAAC,CAAmB,EAAI,GAAc,CAClD,IAAM,EAAe,EAA2B,EAAiB,CAAS,EAAG,CAAY,EAEzF,MADA,GAAS,MACI,CACX,EAAa,QAAQ,EACjB,IAAW,IAAc,EAAS,IAAA,GACxC,CACF,CAAC,CACL,CACF,EACA,MAAO,EAAc,IAAK,GACxB,EACE,EAAM,KAAK,CACT,GAAG,EACH,MAAM,QAAQ,GAAG,EAAM,CAErB,OADA,MAAM,EAAQ,iBAAiB,EAAK,EAAE,EAC/B,EAAK,QAAQ,GAAG,CAAI,CAC7B,CACF,CAAC,CACH,CACF,EACA,SAAU,EAAQ,SAAS,KAAK,CAAC,EAAM,KAAa,EAAM,QAAQ,EAAM,CAAO,CAAC,EAChF,UAAW,EAAQ,WAAW,KAAK,CAAC,EAAK,KAAc,EAAM,SAAS,EAAK,CAAQ,CAAC,EACpF,OAAQ,EAAM,OAAO,EAAQ,QAAU,CAAC,CAAC,EACzC,iBAAkB,EAAQ,iBAE1B,iBAAkB,CAChB,GAAI,EAAQ,kBAAoB,CAAC,EACjC,GAAI,EAAa,CAAC,CAAE,OAAQ,GAAG,EAAe,aAAc,SAAU,EAA0B,CAAE,CAAC,EAAI,CAAC,CAC1G,EACA,UAAW,EACP,CAAC,EACD,CACE,CACE,OAAQ,EACR,UAAW,YAAY,IACvB,OAAQ,CACN,CACE,KAAM,yBACN,YAAa,+EACf,EACA,CACE,KAAM,sBACN,YAAa,sEACf,CACF,CACF,CACF,EACJ,MAAM,QAAS,CACb,EAAM,cAAc,EACpB,MAAM,EAAM,eAAiB,EAAQ,QAAQ,CAAC,CAChD,EACA,MAAM,WAAY,CAChB,EAAM,cAAc,EACpB,GAAI,CACF,MAAM,EAAM,eAAiB,EAAQ,QAAQ,CAAC,CAChD,QAAU,CACR,EAAM,eAAe,CACvB,CACF,CACF,CACF,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../src/constants/workflow.cjs"),t=require("../src/controllers/serverRuntime.cjs"),n=require("../src/controllers/workflowCatalogChannel.cjs"),r=require("../src/controllers/workflowHubApi.cjs"),i=require("../src/controllers/workflowsHubChannel.cjs"),a=(0,require("@agimon-ai/doompi-core/server-facet").defineServerPlugin)({name:e.PACKAGE_SOURCE,global:{channels:[i.createWorkflowsChannel,n.createWorkflowCatalogChannel],api:[r.api]},workspace:{channels:[i.createWorkflowsChannel,n.createWorkflowCatalogChannel],api:[r.api]},session:({agent:e,host:n})=>({api:[r.api],...e?t.createWorkflowServerRuntime(e,n):{}})});exports.default=a,exports.workflowServerFacet=a;
|
|
2
|
+
//# sourceMappingURL=server.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.cjs","names":["defineServerPlugin","PACKAGE_SOURCE","createWorkflowsChannel","createWorkflowCatalogChannel","api","createWorkflowServerRuntime"],"sources":["../../src/extensions/server.ts"],"sourcesContent":["import { defineServerPlugin } from '@agimon-ai/doompi-core/server-facet';\n\nimport { PACKAGE_SOURCE } from '../constants/workflow';\nimport { createWorkflowServerRuntime } from '../controllers/serverRuntime';\nimport { createWorkflowCatalogChannel } from '../controllers/workflowCatalogChannel';\nimport { api } from '../controllers/workflowHubApi';\nimport { createWorkflowsChannel } from '../controllers/workflowsHubChannel';\nexport const workflowServerFacet = defineServerPlugin({\n name: PACKAGE_SOURCE,\n global: { channels: [createWorkflowsChannel, createWorkflowCatalogChannel], api: [api] },\n workspace: { channels: [createWorkflowsChannel, createWorkflowCatalogChannel], api: [api] },\n session: ({ agent, host }) => ({ api: [api], ...(agent ? createWorkflowServerRuntime(agent, host) : {}) }),\n});\nexport default workflowServerFacet;\n"],"mappings":"wWAOa,GAAA,+CAAsBA,CAAAA,CAAAA,mBAAAA,CAAmB,CACpD,KAAMC,EAAAA,eACN,OAAQ,CAAE,SAAU,CAACC,EAAAA,uBAAwBC,EAAAA,4BAA4B,EAAG,IAAK,CAACC,EAAAA,GAAG,CAAE,EACvF,UAAW,CAAE,SAAU,CAACF,EAAAA,uBAAwBC,EAAAA,4BAA4B,EAAG,IAAK,CAACC,EAAAA,GAAG,CAAE,EAC1F,SAAU,CAAE,QAAO,WAAY,CAAE,IAAK,CAACA,EAAAA,GAAG,EAAG,GAAI,EAAQC,EAAAA,4BAA4B,EAAO,CAAI,EAAI,CAAC,CAAG,EAC1G,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.cts","names":[],"sources":["../../src/extensions/server.ts"],"mappings":";qBAOa,mEAAmB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.mts","names":[],"sources":["../../src/extensions/server.ts"],"mappings":";qBAOa,mEAAmB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{PACKAGE_SOURCE as e}from"../src/constants/workflow.mjs";import{createWorkflowServerRuntime as t}from"../src/controllers/serverRuntime.mjs";import{createWorkflowCatalogChannel as n}from"../src/controllers/workflowCatalogChannel.mjs";import{api as r}from"../src/controllers/workflowHubApi.mjs";import{createWorkflowsChannel as i}from"../src/controllers/workflowsHubChannel.mjs";import{defineServerPlugin as a}from"@agimon-ai/doompi-core/server-facet";const o=a({name:e,global:{channels:[i,n],api:[r]},workspace:{channels:[i,n],api:[r]},session:({agent:e,host:n})=>({api:[r],...e?t(e,n):{}})});export{o as default,o as workflowServerFacet};
|
|
2
|
+
//# sourceMappingURL=server.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.mjs","names":[],"sources":["../../src/extensions/server.ts"],"sourcesContent":["import { defineServerPlugin } from '@agimon-ai/doompi-core/server-facet';\n\nimport { PACKAGE_SOURCE } from '../constants/workflow';\nimport { createWorkflowServerRuntime } from '../controllers/serverRuntime';\nimport { createWorkflowCatalogChannel } from '../controllers/workflowCatalogChannel';\nimport { api } from '../controllers/workflowHubApi';\nimport { createWorkflowsChannel } from '../controllers/workflowsHubChannel';\nexport const workflowServerFacet = defineServerPlugin({\n name: PACKAGE_SOURCE,\n global: { channels: [createWorkflowsChannel, createWorkflowCatalogChannel], api: [api] },\n workspace: { channels: [createWorkflowsChannel, createWorkflowCatalogChannel], api: [api] },\n session: ({ agent, host }) => ({ api: [api], ...(agent ? createWorkflowServerRuntime(agent, host) : {}) }),\n});\nexport default workflowServerFacet;\n"],"mappings":"wcAOA,MAAa,EAAsB,EAAmB,CACpD,KAAM,EACN,OAAQ,CAAE,SAAU,CAAC,EAAwB,CAA4B,EAAG,IAAK,CAAC,CAAG,CAAE,EACvF,UAAW,CAAE,SAAU,CAAC,EAAwB,CAA4B,EAAG,IAAK,CAAC,CAAG,CAAE,EAC1F,SAAU,CAAE,QAAO,WAAY,CAAE,IAAK,CAAC,CAAG,EAAG,GAAI,EAAQ,EAA4B,EAAO,CAAI,EAAI,CAAC,CAAG,EAC1G,CAAC"}
|
package/dist/index.cjs
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./src/services/workflowLaunchCommand/index.cjs");exports.parseWorkflowLaunchCommand=e.parseWorkflowLaunchCommand,exports.validateWorkflowLaunch=e.validateWorkflowLaunch;
|
package/dist/index.d.cts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { parseWorkflowLaunchCommand, validateWorkflowLaunch } from "./src/services/workflowLaunchCommand/index.cjs";
|
|
2
|
+
export { parseWorkflowLaunchCommand, validateWorkflowLaunch };
|
package/dist/index.d.mts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { parseWorkflowLaunchCommand, validateWorkflowLaunch } from "./src/services/workflowLaunchCommand/index.mjs";
|
|
2
|
+
export { parseWorkflowLaunchCommand, validateWorkflowLaunch };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{};
|
|
1
|
+
import{parseWorkflowLaunchCommand as e,validateWorkflowLaunch as t}from"./src/services/workflowLaunchCommand/index.mjs";export{e as parseWorkflowLaunchCommand,t as validateWorkflowLaunch};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=`list_workflows`,t=`launch_workflow`,n=`workflow_run`,r=[e,t,n];exports.LAUNCH_WORKFLOW_TOOL_NAME=t,exports.LEADER_CATALOG_ACTION=`workflow.catalog`,exports.LEADER_DETAIL=`multi-step agent runs`,exports.LEADER_DISABLE_ACTION=`workflow.disable`,exports.LEADER_ENABLE_ACTION=`workflow.enable`,exports.LEADER_LABEL=`workflows`,exports.LEADER_MANAGE_ACTION=`workflow.manage`,exports.LEADER_RECOVER_ACTION=`workflow.recover`,exports.LIST_WORKFLOWS_TOOL_NAME=e,exports.PACKAGE_SOURCE=`@agimon-ai/doompi-workflow`,exports.WORKFLOW_PI_TOOL_NAMES=r,exports.WORKFLOW_RUN_TOOL_NAME=n;
|
|
2
|
+
//# sourceMappingURL=workflow.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.cjs","names":[],"sources":["../../../src/constants/workflow.ts"],"sourcesContent":["export const COMMAND_DESCRIPTION = 'Doom Pi workflow execution and monitoring integration';\nexport const PACKAGE_SOURCE = '@agimon-ai/doompi-workflow';\n\nexport const LEADER_KEY = 'w';\nexport const LEADER_LABEL = 'workflows';\nexport const LEADER_ORDER = 50;\nexport const LEADER_ENABLE_ACTION = 'workflow.enable';\nexport const LEADER_DISABLE_ACTION = 'workflow.disable';\nexport const LEADER_MANAGE_ACTION = 'workflow.manage';\nexport const LEADER_RECOVER_ACTION = 'workflow.recover';\nexport const LEADER_CATALOG_ACTION = 'workflow.catalog';\nexport const LEADER_DETAIL = 'multi-step agent runs';\n\nexport const LIST_WORKFLOWS_TOOL_NAME = 'list_workflows';\nexport const LAUNCH_WORKFLOW_TOOL_NAME = 'launch_workflow';\nexport const WORKFLOW_RUN_TOOL_NAME = 'workflow_run';\nexport const WORKFLOW_PI_TOOL_NAMES = [\n LIST_WORKFLOWS_TOOL_NAME,\n LAUNCH_WORKFLOW_TOOL_NAME,\n WORKFLOW_RUN_TOOL_NAME,\n] as const;\n"],"mappings":"AACA,MAYa,EAA2B,iBAC3B,EAA4B,kBAC5B,EAAyB,eACzB,EAAyB,CACpC,EACA,EACA,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=`@agimon-ai/doompi-workflow`,t=`workflows`,n=`workflow.enable`,r=`workflow.disable`,i=`workflow.manage`,a=`workflow.recover`,o=`workflow.catalog`,s=`multi-step agent runs`,c=`list_workflows`,l=`launch_workflow`,u=`workflow_run`,d=[c,l,u];export{l as LAUNCH_WORKFLOW_TOOL_NAME,o as LEADER_CATALOG_ACTION,s as LEADER_DETAIL,r as LEADER_DISABLE_ACTION,n as LEADER_ENABLE_ACTION,t as LEADER_LABEL,i as LEADER_MANAGE_ACTION,a as LEADER_RECOVER_ACTION,c as LIST_WORKFLOWS_TOOL_NAME,e as PACKAGE_SOURCE,d as WORKFLOW_PI_TOOL_NAMES,u as WORKFLOW_RUN_TOOL_NAME};
|
|
2
|
+
//# sourceMappingURL=workflow.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.mjs","names":[],"sources":["../../../src/constants/workflow.ts"],"sourcesContent":["export const COMMAND_DESCRIPTION = 'Doom Pi workflow execution and monitoring integration';\nexport const PACKAGE_SOURCE = '@agimon-ai/doompi-workflow';\n\nexport const LEADER_KEY = 'w';\nexport const LEADER_LABEL = 'workflows';\nexport const LEADER_ORDER = 50;\nexport const LEADER_ENABLE_ACTION = 'workflow.enable';\nexport const LEADER_DISABLE_ACTION = 'workflow.disable';\nexport const LEADER_MANAGE_ACTION = 'workflow.manage';\nexport const LEADER_RECOVER_ACTION = 'workflow.recover';\nexport const LEADER_CATALOG_ACTION = 'workflow.catalog';\nexport const LEADER_DETAIL = 'multi-step agent runs';\n\nexport const LIST_WORKFLOWS_TOOL_NAME = 'list_workflows';\nexport const LAUNCH_WORKFLOW_TOOL_NAME = 'launch_workflow';\nexport const WORKFLOW_RUN_TOOL_NAME = 'workflow_run';\nexport const WORKFLOW_PI_TOOL_NAMES = [\n LIST_WORKFLOWS_TOOL_NAME,\n LAUNCH_WORKFLOW_TOOL_NAME,\n WORKFLOW_RUN_TOOL_NAME,\n] as const;\n"],"mappings":"AACA,MAAa,EAAiB,6BAGjB,EAAe,YAEf,EAAuB,kBACvB,EAAwB,mBACxB,EAAuB,kBACvB,EAAwB,mBACxB,EAAwB,mBACxB,EAAgB,wBAEhB,EAA2B,iBAC3B,EAA4B,kBAC5B,EAAyB,eACzB,EAAyB,CACpC,EACA,EACA,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../services/workflowLaunchCommand/index.cjs"),t=require("../services/workflowResource/index.cjs"),n=require("../services/webWorkflowCatalog/index.cjs"),r=require("../services/workflowCatalogDeps/index.cjs"),i=require("../services/workflowRuns/index.cjs"),a=require("../services/workflowWatcher/index.cjs"),o=require("../types/webWorkflows.cjs");let s=require("@agimon-ai/workflow-mcp"),c=require("zod"),l=require("@agimon-ai/doompi-minor-mode");const u=`@agimon-ai/doompi-workflow`,d=`workflow`,f=`list_workflows`,p=`launch_workflow`,m=`workflow_run`;function h(e){let t=[];if(typeof e==`object`&&e&&`content`in e&&Array.isArray(e.content))for(let n of e.content){if(typeof n!=`object`||!n||!(`type`in n))continue;let e=n;e.type===`text`&&typeof e.text==`string`?t.push({type:`text`,text:e.text}):e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`&&t.push({type:`image`,data:e.data,mimeType:e.mimeType})}return t.length===0&&t.push({type:`text`,text:JSON.stringify(e,null,2)}),{content:t,details:e}}function g(g,_){if(_.context.directEvents===void 0)throw Error(`Workflow headless facet requires the session direct event bus.`);let v=_.context.directEvents,y=n.createWorkflowCatalogReader(r.defaultCatalogDeps()),b=async e=>{let t=i.presentWorkflowRuns(a.readWorkflowRuns({environment:e.environment}).filter(t=>i.runBelongsToSession(t,e.sessionId)).map(e=>e.view),Date.now());v.publish(o.WORKFLOW_RUNS_TYPE,e.sessionId,{runs:t});try{v.publish(o.WORKFLOW_CATALOG_TYPE,e.sessionId,{cwd:e.cwd,workflows:n.presentWorkflowCatalog(await y.read(e.cwd))})}catch(t){let n=t instanceof Error?t.message:String(t);v.publish(o.WORKFLOW_CATALOG_TYPE,e.sessionId,{cwd:e.cwd,workflows:[],warning:n})}},x=(0,s.createEmbeddedWorkflowFeature)(),S=x.createListStatusesTool({recordFilter:e=>{let t=g.context.sessionId;return e.env?.PI_SESSION_ID===void 0||e.env.PI_SESSION_ID===t}}),C,w,T=()=>(g.context.selection.state?.[`minor-mode`]??[]).includes(d),E=()=>{let e=T();return{activation:e?`active`:`inactive`,condition:`ready`,...e?{detail:`workflow tools available`}:{},actions:[{id:`activate`,enabled:!e,...e?{disabledReason:`Workflow mode is active.`}:{}},{id:`deactivate`,enabled:e,...e?{}:{disabledReason:`Workflow mode is inactive.`}}]}},D=async e=>{let t=(g.context.selection.state?.[`minor-mode`]??[]).filter(e=>e!==d);await g.changeSelection({axis:`state`,key:`minor-mode`,values:e?[...t,d]:t}),w?.publish()};return w=(0,l.defineMinorMode)({descriptor:{source:u,id:d,label:`Workflow`,description:`Workflow discovery, launch, inspection, control, and recovery tools.`,order:20,actions:[{id:`activate`,label:`Activate`,description:`Enable workflow tools for this session.`,contexts:[`headless`],parameters:[]},{id:`deactivate`,label:`Deactivate`,description:`Disable workflow tools without stopping active runs.`,contexts:[`headless`],parameters:[]}]},state:E,async handleAction(e,t,n,r){if(r.signal.throwIfAborted(),t===`activate`)return await D(!0),{message:`Workflow mode activated.`};if(t===`deactivate`)return await D(!1),{message:`Workflow mode deactivated.`};throw Error(`Unknown workflow mode action: ${t}`)}}).createOwner(void 0),{services:[(0,l.serverMinorModes)([w])],toolRestrictions:[{when:{state:{"minor-mode":d}},allowedTools:[f,p,m]}],hooks:[{event:`tool_execution_end`,handle:async(e,t)=>{await b(t)}},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},event:`session_shutdown`,handle:()=>{C?.dispose(),C=void 0}}],resources:[{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:`doompi-author-workflow`,kind:`skill`,read:()=>t.readWorkflowSkill(`doompi-author-workflow`)},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:`doompi-use-workflow`,kind:`skill`,read:()=>t.readWorkflowSkill(`doompi-use-workflow`)},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:`workflow-recovery`,kind:`skill`,read:()=>t.readWorkflowSkill(`workflow-recovery`)}],activities:[{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:u,async start(e){return C=x.createRunControl({}),await C.start(),await b(e),()=>{C?.dispose(),C=void 0}}}],tools:[{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:f,label:`List Workflows`,description:`List workflow definitions available in this repository.`,parameters:c.z.toJSONSchema(x.listWorkflowsTool.getInputSchema()),executionMode:`serial`,async execute(e,t,n){return n?.throwIfAborted(),h(await x.listWorkflowsTool.execute(t))}},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:p,label:`Launch Workflow`,description:`Start a workflow run and return its recorded launch result.`,parameters:c.z.toJSONSchema(x.runTool.getInputSchema()),executionMode:`serial`,async execute(e,t,n){return n?.throwIfAborted(),h(await x.runTool.execute(t))}},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:m,label:`Workflow Run`,description:`Inspect the status of a workflow run or request cooperative control.`,parameters:{type:`object`,properties:{action:{type:`string`,enum:[`status`,`pause`,`resume`,`stop`]},runKey:{type:`string`,minLength:1},workspace:{type:`string`},reason:{type:`string`},expectedRunId:{type:`string`}},required:[`action`,`runKey`],additionalProperties:!1},executionMode:`serial`,async execute(e,t,n){n?.throwIfAborted();let r=t;return r.action===`status`?h(await S.execute({workspace:r.workspace,pageSize:100})):C?typeof r.expectedRunId!=`string`||r.expectedRunId.length===0?h({error:`expectedRunId is required for workflow control.`}):h(r.action===`pause`?await C.pause(r.runKey,r.expectedRunId,r.workspace,r.reason):r.action===`resume`?await C.resume(r.runKey,r.expectedRunId,r.workspace):await C.stop(r.runKey,r.expectedRunId,r.workspace,r.reason)):h({error:`Workflow activity is not active.`})}}],commands:[{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:`workflow-launch`,description:`Launch a workflow from a slash command.`,async execute(t,n){let r=e.parseWorkflowLaunchCommand(t);if(`error`in r){await n.client.notify({body:r.error,level:`error`});return}let i=h(await x.runTool.execute({workflowPath:r.workflow,...r.runner===void 0?{}:{runner:r.runner},...Object.keys(r.inputs).length===0?{}:{inputs:r.inputs},...r.prompt===void 0?{}:{prompt:r.prompt}})).content.find(e=>e.type===`text`);await n.client.notify({body:i?.type===`text`?i.text:`Workflow launch requested.`,level:`info`})}}],onDispose(){C?.dispose(),C=void 0}}}exports.createWorkflowServerRuntime=g;
|
|
2
|
+
//# sourceMappingURL=serverRuntime.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serverRuntime.cjs","names":["createWorkflowCatalogReader","defaultCatalogDeps","presentWorkflowRuns","readWorkflowRuns","runBelongsToSession","WORKFLOW_RUNS_TYPE","WORKFLOW_CATALOG_TYPE","presentWorkflowCatalog","createEmbeddedWorkflowFeature","defineMinorMode","serverMinorModes","skill","z","parseWorkflowLaunchCommand"],"sources":["../../../src/controllers/serverRuntime.ts"],"sourcesContent":["import {\n type DoomHeadlessExecutionContext,\n type DoomHeadlessContent,\n type DoomHeadlessToolResult,\n} from '@agimon-ai/doompi-core/headless';\nimport { serverMinorModes } from '@agimon-ai/doompi-minor-mode';\nimport { defineMinorMode, type MinorModeOwner, type MinorModeState } from '@agimon-ai/doompi-minor-mode';\nimport { createEmbeddedWorkflowFeature } from '@agimon-ai/workflow-mcp';\nimport { z } from 'zod';\n\nimport { createWorkflowCatalogReader, presentWorkflowCatalog } from '../services/webWorkflowCatalog';\nimport { defaultCatalogDeps } from '../services/workflowCatalogDeps';\nimport { parseWorkflowLaunchCommand } from '../services/workflowLaunchCommand';\nimport { readWorkflowSkill as skill } from '../services/workflowResource';\nimport { presentWorkflowRuns, runBelongsToSession } from '../services/workflowRuns';\nimport { readWorkflowRuns } from '../services/workflowWatcher';\nimport { WORKFLOW_CATALOG_TYPE, WORKFLOW_RUNS_TYPE } from '../types/webWorkflows';\n\nconst SOURCE = '@agimon-ai/doompi-workflow';\nconst WORKFLOW_MODE_ID = 'workflow';\nconst LIST_TOOL = 'list_workflows';\nconst LAUNCH_TOOL = 'launch_workflow';\nconst RUN_TOOL = 'workflow_run';\n\nfunction callResult(value: unknown): DoomHeadlessToolResult {\n const content: DoomHeadlessContent[] = [];\n if (typeof value === 'object' && value !== null && 'content' in value && Array.isArray(value.content)) {\n for (const item of value.content) {\n if (typeof item !== 'object' || item === null || !('type' in item)) continue;\n const record = item as Record<string, unknown>;\n if (record.type === 'text' && typeof record.text === 'string') content.push({ type: 'text', text: record.text });\n else if (record.type === 'image' && typeof record.data === 'string' && typeof record.mimeType === 'string') {\n content.push({ type: 'image', data: record.data, mimeType: record.mimeType });\n }\n }\n }\n if (content.length === 0) content.push({ type: 'text', text: JSON.stringify(value, null, 2) });\n return { content, details: value };\n}\n\nimport { type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport { type DoomServerHostService, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\nexport function createWorkflowServerRuntime(\n host: DoomHeadlessHostService,\n serverHost: DoomServerHostService,\n): DoomServerSessionPlugin {\n if (serverHost.context.directEvents === undefined)\n throw new Error('Workflow headless facet requires the session direct event bus.');\n const directEvents = serverHost.context.directEvents;\n const catalogReader = createWorkflowCatalogReader(defaultCatalogDeps());\n const publishLifecycle = async (executionContext: typeof host.context): Promise<void> => {\n const runs = presentWorkflowRuns(\n readWorkflowRuns({ environment: executionContext.environment })\n .filter((run) => runBelongsToSession(run, executionContext.sessionId))\n .map((run) => run.view),\n Date.now(),\n );\n directEvents.publish(WORKFLOW_RUNS_TYPE, executionContext.sessionId, { runs });\n try {\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: presentWorkflowCatalog(await catalogReader.read(executionContext.cwd)),\n });\n } catch (error) {\n const warning = error instanceof Error ? error.message : String(error);\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: [],\n warning,\n });\n }\n };\n const feature = createEmbeddedWorkflowFeature();\n const statuses = feature.createListStatusesTool({\n recordFilter: (record) => {\n const sessionId = host.context.sessionId;\n return record.env?.PI_SESSION_ID === undefined || record.env.PI_SESSION_ID === sessionId;\n },\n });\n let control: ReturnType<typeof feature.createRunControl> | undefined;\n let modeOwner: MinorModeOwner | undefined;\n const modeSelected = (): boolean => (host.context.selection.state?.['minor-mode'] ?? []).includes(WORKFLOW_MODE_ID);\n const modeState = (): MinorModeState => {\n const active = modeSelected();\n return {\n activation: active ? 'active' : 'inactive',\n condition: 'ready',\n ...(active ? { detail: 'workflow tools available' } : {}),\n actions: [\n { id: 'activate', enabled: !active, ...(!active ? {} : { disabledReason: 'Workflow mode is active.' }) },\n { id: 'deactivate', enabled: active, ...(active ? {} : { disabledReason: 'Workflow mode is inactive.' }) },\n ],\n };\n };\n const selectMode = async (enabled: boolean): Promise<void> => {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== WORKFLOW_MODE_ID);\n await host.changeSelection({\n axis: 'state',\n key: 'minor-mode',\n values: enabled ? [...modes, WORKFLOW_MODE_ID] : modes,\n });\n modeOwner?.publish();\n };\n modeOwner = defineMinorMode({\n descriptor: {\n source: SOURCE,\n id: WORKFLOW_MODE_ID,\n label: 'Workflow',\n description: 'Workflow discovery, launch, inspection, control, and recovery tools.',\n order: 20,\n actions: [\n {\n id: 'activate',\n label: 'Activate',\n description: 'Enable workflow tools for this session.',\n contexts: ['headless'],\n parameters: [],\n },\n {\n id: 'deactivate',\n label: 'Deactivate',\n description: 'Disable workflow tools without stopping active runs.',\n contexts: ['headless'],\n parameters: [],\n },\n ],\n },\n state: modeState,\n async handleAction(_runtime, actionId, _argumentsValue, execution) {\n execution.signal.throwIfAborted();\n if (actionId === 'activate') {\n await selectMode(true);\n return { message: 'Workflow mode activated.' };\n }\n if (actionId === 'deactivate') {\n await selectMode(false);\n return { message: 'Workflow mode deactivated.' };\n }\n throw new Error(`Unknown workflow mode action: ${actionId}`);\n },\n }).createOwner(undefined);\n return {\n services: [serverMinorModes([modeOwner])],\n toolRestrictions: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID } },\n allowedTools: [LIST_TOOL, LAUNCH_TOOL, RUN_TOOL],\n },\n ],\n hooks: [\n {\n event: 'tool_execution_end',\n handle: async (_event, executionContext) => {\n await publishLifecycle(executionContext);\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n event: 'session_shutdown',\n handle: () => {\n control?.dispose();\n control = undefined;\n },\n },\n ],\n resources: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-author-workflow',\n kind: 'skill',\n read: () => skill('doompi-author-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-use-workflow',\n kind: 'skill',\n read: () => skill('doompi-use-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-recovery',\n kind: 'skill',\n read: () => skill('workflow-recovery'),\n },\n ],\n activities: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: SOURCE,\n async start(executionContext) {\n control = feature.createRunControl({});\n await control.start();\n await publishLifecycle(executionContext);\n return () => {\n control?.dispose();\n control = undefined;\n };\n },\n },\n ],\n tools: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LIST_TOOL,\n label: 'List Workflows',\n description: 'List workflow definitions available in this repository.',\n parameters: z.toJSONSchema(feature.listWorkflowsTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n return callResult(\n await feature.listWorkflowsTool.execute(\n parameters as Parameters<typeof feature.listWorkflowsTool.execute>[0],\n ),\n );\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LAUNCH_TOOL,\n label: 'Launch Workflow',\n description: 'Start a workflow run and return its recorded launch result.',\n parameters: z.toJSONSchema(feature.runTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n return callResult(await feature.runTool.execute(parameters as Parameters<typeof feature.runTool.execute>[0]));\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: RUN_TOOL,\n label: 'Workflow Run',\n description: 'Inspect the status of a workflow run or request cooperative control.',\n parameters: {\n type: 'object',\n properties: {\n action: { type: 'string', enum: ['status', 'pause', 'resume', 'stop'] },\n runKey: { type: 'string', minLength: 1 },\n workspace: { type: 'string' },\n reason: { type: 'string' },\n expectedRunId: { type: 'string' },\n },\n required: ['action', 'runKey'],\n additionalProperties: false,\n },\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n const input = parameters as unknown as {\n action: 'status' | 'pause' | 'resume' | 'stop';\n runKey: string;\n workspace?: string;\n reason?: string;\n expectedRunId?: string;\n };\n if (input.action === 'status')\n return callResult(await statuses.execute({ workspace: input.workspace, pageSize: 100 }));\n if (!control) return callResult({ error: 'Workflow activity is not active.' });\n if (typeof input.expectedRunId !== 'string' || input.expectedRunId.length === 0) {\n return callResult({ error: 'expectedRunId is required for workflow control.' });\n }\n const request =\n input.action === 'pause'\n ? await control.pause(input.runKey, input.expectedRunId, input.workspace, input.reason)\n : input.action === 'resume'\n ? await control.resume(input.runKey, input.expectedRunId, input.workspace)\n : await control.stop(input.runKey, input.expectedRunId, input.workspace, input.reason);\n return callResult(request);\n },\n },\n ],\n commands: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-launch',\n description: 'Launch a workflow from a slash command.',\n async execute(args: string, execution: DoomHeadlessExecutionContext) {\n const parsed = parseWorkflowLaunchCommand(args);\n if ('error' in parsed) {\n await execution.client.notify({ body: parsed.error, level: 'error' });\n return;\n }\n const result = await feature.runTool.execute({\n workflowPath: parsed.workflow,\n ...(parsed.runner === undefined ? {} : { runner: parsed.runner }),\n ...(Object.keys(parsed.inputs).length === 0 ? {} : { inputs: parsed.inputs }),\n ...(parsed.prompt === undefined ? {} : { prompt: parsed.prompt }),\n });\n const rendered = callResult(result).content.find((entry) => entry.type === 'text');\n await execution.client.notify({\n body: rendered?.type === 'text' ? rendered.text : 'Workflow launch requested.',\n level: 'info',\n });\n },\n },\n ],\n onDispose() {\n control?.dispose();\n control = undefined;\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{parseWorkflowLaunchCommand as e}from"../services/workflowLaunchCommand/index.mjs";import{readWorkflowSkill as t}from"../services/workflowResource/index.mjs";import{createWorkflowCatalogReader as n,presentWorkflowCatalog as r}from"../services/webWorkflowCatalog/index.mjs";import{defaultCatalogDeps as i}from"../services/workflowCatalogDeps/index.mjs";import{presentWorkflowRuns as a,runBelongsToSession as o}from"../services/workflowRuns/index.mjs";import{readWorkflowRuns as s}from"../services/workflowWatcher/index.mjs";import{WORKFLOW_CATALOG_TYPE as c,WORKFLOW_RUNS_TYPE as l}from"../types/webWorkflows.mjs";import{createEmbeddedWorkflowFeature as u}from"@agimon-ai/workflow-mcp";import{z as d}from"zod";import{defineMinorMode as f,serverMinorModes as p}from"@agimon-ai/doompi-minor-mode";const m=`@agimon-ai/doompi-workflow`,h=`workflow`,g=`list_workflows`,_=`launch_workflow`,v=`workflow_run`;function y(e){let t=[];if(typeof e==`object`&&e&&`content`in e&&Array.isArray(e.content))for(let n of e.content){if(typeof n!=`object`||!n||!(`type`in n))continue;let e=n;e.type===`text`&&typeof e.text==`string`?t.push({type:`text`,text:e.text}):e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`&&t.push({type:`image`,data:e.data,mimeType:e.mimeType})}return t.length===0&&t.push({type:`text`,text:JSON.stringify(e,null,2)}),{content:t,details:e}}function b(b,x){if(x.context.directEvents===void 0)throw Error(`Workflow headless facet requires the session direct event bus.`);let S=x.context.directEvents,C=n(i()),w=async e=>{let t=a(s({environment:e.environment}).filter(t=>o(t,e.sessionId)).map(e=>e.view),Date.now());S.publish(l,e.sessionId,{runs:t});try{S.publish(c,e.sessionId,{cwd:e.cwd,workflows:r(await C.read(e.cwd))})}catch(t){let n=t instanceof Error?t.message:String(t);S.publish(c,e.sessionId,{cwd:e.cwd,workflows:[],warning:n})}},T=u(),E=T.createListStatusesTool({recordFilter:e=>{let t=b.context.sessionId;return e.env?.PI_SESSION_ID===void 0||e.env.PI_SESSION_ID===t}}),D,O,k=()=>(b.context.selection.state?.[`minor-mode`]??[]).includes(h),A=()=>{let e=k();return{activation:e?`active`:`inactive`,condition:`ready`,...e?{detail:`workflow tools available`}:{},actions:[{id:`activate`,enabled:!e,...e?{disabledReason:`Workflow mode is active.`}:{}},{id:`deactivate`,enabled:e,...e?{}:{disabledReason:`Workflow mode is inactive.`}}]}},j=async e=>{let t=(b.context.selection.state?.[`minor-mode`]??[]).filter(e=>e!==h);await b.changeSelection({axis:`state`,key:`minor-mode`,values:e?[...t,h]:t}),O?.publish()};return O=f({descriptor:{source:m,id:h,label:`Workflow`,description:`Workflow discovery, launch, inspection, control, and recovery tools.`,order:20,actions:[{id:`activate`,label:`Activate`,description:`Enable workflow tools for this session.`,contexts:[`headless`],parameters:[]},{id:`deactivate`,label:`Deactivate`,description:`Disable workflow tools without stopping active runs.`,contexts:[`headless`],parameters:[]}]},state:A,async handleAction(e,t,n,r){if(r.signal.throwIfAborted(),t===`activate`)return await j(!0),{message:`Workflow mode activated.`};if(t===`deactivate`)return await j(!1),{message:`Workflow mode deactivated.`};throw Error(`Unknown workflow mode action: ${t}`)}}).createOwner(void 0),{services:[p([O])],toolRestrictions:[{when:{state:{"minor-mode":h}},allowedTools:[g,_,v]}],hooks:[{event:`tool_execution_end`,handle:async(e,t)=>{await w(t)}},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},event:`session_shutdown`,handle:()=>{D?.dispose(),D=void 0}}],resources:[{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:`doompi-author-workflow`,kind:`skill`,read:()=>t(`doompi-author-workflow`)},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:`doompi-use-workflow`,kind:`skill`,read:()=>t(`doompi-use-workflow`)},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:`workflow-recovery`,kind:`skill`,read:()=>t(`workflow-recovery`)}],activities:[{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:m,async start(e){return D=T.createRunControl({}),await D.start(),await w(e),()=>{D?.dispose(),D=void 0}}}],tools:[{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:g,label:`List Workflows`,description:`List workflow definitions available in this repository.`,parameters:d.toJSONSchema(T.listWorkflowsTool.getInputSchema()),executionMode:`serial`,async execute(e,t,n){return n?.throwIfAborted(),y(await T.listWorkflowsTool.execute(t))}},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:_,label:`Launch Workflow`,description:`Start a workflow run and return its recorded launch result.`,parameters:d.toJSONSchema(T.runTool.getInputSchema()),executionMode:`serial`,async execute(e,t,n){return n?.throwIfAborted(),y(await T.runTool.execute(t))}},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:v,label:`Workflow Run`,description:`Inspect the status of a workflow run or request cooperative control.`,parameters:{type:`object`,properties:{action:{type:`string`,enum:[`status`,`pause`,`resume`,`stop`]},runKey:{type:`string`,minLength:1},workspace:{type:`string`},reason:{type:`string`},expectedRunId:{type:`string`}},required:[`action`,`runKey`],additionalProperties:!1},executionMode:`serial`,async execute(e,t,n){n?.throwIfAborted();let r=t;return r.action===`status`?y(await E.execute({workspace:r.workspace,pageSize:100})):D?typeof r.expectedRunId!=`string`||r.expectedRunId.length===0?y({error:`expectedRunId is required for workflow control.`}):y(r.action===`pause`?await D.pause(r.runKey,r.expectedRunId,r.workspace,r.reason):r.action===`resume`?await D.resume(r.runKey,r.expectedRunId,r.workspace):await D.stop(r.runKey,r.expectedRunId,r.workspace,r.reason)):y({error:`Workflow activity is not active.`})}}],commands:[{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:`workflow-launch`,description:`Launch a workflow from a slash command.`,async execute(t,n){let r=e(t);if(`error`in r){await n.client.notify({body:r.error,level:`error`});return}let i=y(await T.runTool.execute({workflowPath:r.workflow,...r.runner===void 0?{}:{runner:r.runner},...Object.keys(r.inputs).length===0?{}:{inputs:r.inputs},...r.prompt===void 0?{}:{prompt:r.prompt}})).content.find(e=>e.type===`text`);await n.client.notify({body:i?.type===`text`?i.text:`Workflow launch requested.`,level:`info`})}}],onDispose(){D?.dispose(),D=void 0}}}export{b as createWorkflowServerRuntime};
|
|
2
|
+
//# sourceMappingURL=serverRuntime.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serverRuntime.mjs","names":["skill"],"sources":["../../../src/controllers/serverRuntime.ts"],"sourcesContent":["import {\n type DoomHeadlessExecutionContext,\n type DoomHeadlessContent,\n type DoomHeadlessToolResult,\n} from '@agimon-ai/doompi-core/headless';\nimport { serverMinorModes } from '@agimon-ai/doompi-minor-mode';\nimport { defineMinorMode, type MinorModeOwner, type MinorModeState } from '@agimon-ai/doompi-minor-mode';\nimport { createEmbeddedWorkflowFeature } from '@agimon-ai/workflow-mcp';\nimport { z } from 'zod';\n\nimport { createWorkflowCatalogReader, presentWorkflowCatalog } from '../services/webWorkflowCatalog';\nimport { defaultCatalogDeps } from '../services/workflowCatalogDeps';\nimport { parseWorkflowLaunchCommand } from '../services/workflowLaunchCommand';\nimport { readWorkflowSkill as skill } from '../services/workflowResource';\nimport { presentWorkflowRuns, runBelongsToSession } from '../services/workflowRuns';\nimport { readWorkflowRuns } from '../services/workflowWatcher';\nimport { WORKFLOW_CATALOG_TYPE, WORKFLOW_RUNS_TYPE } from '../types/webWorkflows';\n\nconst SOURCE = '@agimon-ai/doompi-workflow';\nconst WORKFLOW_MODE_ID = 'workflow';\nconst LIST_TOOL = 'list_workflows';\nconst LAUNCH_TOOL = 'launch_workflow';\nconst RUN_TOOL = 'workflow_run';\n\nfunction callResult(value: unknown): DoomHeadlessToolResult {\n const content: DoomHeadlessContent[] = [];\n if (typeof value === 'object' && value !== null && 'content' in value && Array.isArray(value.content)) {\n for (const item of value.content) {\n if (typeof item !== 'object' || item === null || !('type' in item)) continue;\n const record = item as Record<string, unknown>;\n if (record.type === 'text' && typeof record.text === 'string') content.push({ type: 'text', text: record.text });\n else if (record.type === 'image' && typeof record.data === 'string' && typeof record.mimeType === 'string') {\n content.push({ type: 'image', data: record.data, mimeType: record.mimeType });\n }\n }\n }\n if (content.length === 0) content.push({ type: 'text', text: JSON.stringify(value, null, 2) });\n return { content, details: value };\n}\n\nimport { type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport { type DoomServerHostService, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\nexport function createWorkflowServerRuntime(\n host: DoomHeadlessHostService,\n serverHost: DoomServerHostService,\n): DoomServerSessionPlugin {\n if (serverHost.context.directEvents === undefined)\n throw new Error('Workflow headless facet requires the session direct event bus.');\n const directEvents = serverHost.context.directEvents;\n const catalogReader = createWorkflowCatalogReader(defaultCatalogDeps());\n const publishLifecycle = async (executionContext: typeof host.context): Promise<void> => {\n const runs = presentWorkflowRuns(\n readWorkflowRuns({ environment: executionContext.environment })\n .filter((run) => runBelongsToSession(run, executionContext.sessionId))\n .map((run) => run.view),\n Date.now(),\n );\n directEvents.publish(WORKFLOW_RUNS_TYPE, executionContext.sessionId, { runs });\n try {\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: presentWorkflowCatalog(await catalogReader.read(executionContext.cwd)),\n });\n } catch (error) {\n const warning = error instanceof Error ? error.message : String(error);\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: [],\n warning,\n });\n }\n };\n const feature = createEmbeddedWorkflowFeature();\n const statuses = feature.createListStatusesTool({\n recordFilter: (record) => {\n const sessionId = host.context.sessionId;\n return record.env?.PI_SESSION_ID === undefined || record.env.PI_SESSION_ID === sessionId;\n },\n });\n let control: ReturnType<typeof feature.createRunControl> | undefined;\n let modeOwner: MinorModeOwner | undefined;\n const modeSelected = (): boolean => (host.context.selection.state?.['minor-mode'] ?? []).includes(WORKFLOW_MODE_ID);\n const modeState = (): MinorModeState => {\n const active = modeSelected();\n return {\n activation: active ? 'active' : 'inactive',\n condition: 'ready',\n ...(active ? { detail: 'workflow tools available' } : {}),\n actions: [\n { id: 'activate', enabled: !active, ...(!active ? {} : { disabledReason: 'Workflow mode is active.' }) },\n { id: 'deactivate', enabled: active, ...(active ? {} : { disabledReason: 'Workflow mode is inactive.' }) },\n ],\n };\n };\n const selectMode = async (enabled: boolean): Promise<void> => {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== WORKFLOW_MODE_ID);\n await host.changeSelection({\n axis: 'state',\n key: 'minor-mode',\n values: enabled ? [...modes, WORKFLOW_MODE_ID] : modes,\n });\n modeOwner?.publish();\n };\n modeOwner = defineMinorMode({\n descriptor: {\n source: SOURCE,\n id: WORKFLOW_MODE_ID,\n label: 'Workflow',\n description: 'Workflow discovery, launch, inspection, control, and recovery tools.',\n order: 20,\n actions: [\n {\n id: 'activate',\n label: 'Activate',\n description: 'Enable workflow tools for this session.',\n contexts: ['headless'],\n parameters: [],\n },\n {\n id: 'deactivate',\n label: 'Deactivate',\n description: 'Disable workflow tools without stopping active runs.',\n contexts: ['headless'],\n parameters: [],\n },\n ],\n },\n state: modeState,\n async handleAction(_runtime, actionId, _argumentsValue, execution) {\n execution.signal.throwIfAborted();\n if (actionId === 'activate') {\n await selectMode(true);\n return { message: 'Workflow mode activated.' };\n }\n if (actionId === 'deactivate') {\n await selectMode(false);\n return { message: 'Workflow mode deactivated.' };\n }\n throw new Error(`Unknown workflow mode action: ${actionId}`);\n },\n }).createOwner(undefined);\n return {\n services: [serverMinorModes([modeOwner])],\n toolRestrictions: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID } },\n allowedTools: [LIST_TOOL, LAUNCH_TOOL, RUN_TOOL],\n },\n ],\n hooks: [\n {\n event: 'tool_execution_end',\n handle: async (_event, executionContext) => {\n await publishLifecycle(executionContext);\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n event: 'session_shutdown',\n handle: () => {\n control?.dispose();\n control = undefined;\n },\n },\n ],\n resources: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-author-workflow',\n kind: 'skill',\n read: () => skill('doompi-author-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-use-workflow',\n kind: 'skill',\n read: () => skill('doompi-use-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-recovery',\n kind: 'skill',\n read: () => skill('workflow-recovery'),\n },\n ],\n activities: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: SOURCE,\n async start(executionContext) {\n control = feature.createRunControl({});\n await control.start();\n await publishLifecycle(executionContext);\n return () => {\n control?.dispose();\n control = undefined;\n };\n },\n },\n ],\n tools: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LIST_TOOL,\n label: 'List Workflows',\n description: 'List workflow definitions available in this repository.',\n parameters: z.toJSONSchema(feature.listWorkflowsTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n return callResult(\n await feature.listWorkflowsTool.execute(\n parameters as Parameters<typeof feature.listWorkflowsTool.execute>[0],\n ),\n );\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LAUNCH_TOOL,\n label: 'Launch Workflow',\n description: 'Start a workflow run and return its recorded launch result.',\n parameters: z.toJSONSchema(feature.runTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n return callResult(await feature.runTool.execute(parameters as Parameters<typeof feature.runTool.execute>[0]));\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: RUN_TOOL,\n label: 'Workflow Run',\n description: 'Inspect the status of a workflow run or request cooperative control.',\n parameters: {\n type: 'object',\n properties: {\n action: { type: 'string', enum: ['status', 'pause', 'resume', 'stop'] },\n runKey: { type: 'string', minLength: 1 },\n workspace: { type: 'string' },\n reason: { type: 'string' },\n expectedRunId: { type: 'string' },\n },\n required: ['action', 'runKey'],\n additionalProperties: false,\n },\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n const input = parameters as unknown as {\n action: 'status' | 'pause' | 'resume' | 'stop';\n runKey: string;\n workspace?: string;\n reason?: string;\n expectedRunId?: string;\n };\n if (input.action === 'status')\n return callResult(await statuses.execute({ workspace: input.workspace, pageSize: 100 }));\n if (!control) return callResult({ error: 'Workflow activity is not active.' });\n if (typeof input.expectedRunId !== 'string' || input.expectedRunId.length === 0) {\n return callResult({ error: 'expectedRunId is required for workflow control.' });\n }\n const request =\n input.action === 'pause'\n ? await control.pause(input.runKey, input.expectedRunId, input.workspace, input.reason)\n : input.action === 'resume'\n ? await control.resume(input.runKey, input.expectedRunId, input.workspace)\n : await control.stop(input.runKey, input.expectedRunId, input.workspace, input.reason);\n return callResult(request);\n },\n },\n ],\n commands: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-launch',\n description: 'Launch a workflow from a slash command.',\n async execute(args: string, execution: DoomHeadlessExecutionContext) {\n const parsed = parseWorkflowLaunchCommand(args);\n if ('error' in parsed) {\n await execution.client.notify({ body: parsed.error, level: 'error' });\n return;\n }\n const result = await feature.runTool.execute({\n workflowPath: parsed.workflow,\n ...(parsed.runner === undefined ? {} : { runner: parsed.runner }),\n ...(Object.keys(parsed.inputs).length === 0 ? {} : { inputs: parsed.inputs }),\n ...(parsed.prompt === undefined ? {} : { prompt: parsed.prompt }),\n });\n const rendered = callResult(result).content.find((entry) => entry.type === 'text');\n await execution.client.notify({\n body: rendered?.type === 'text' ? rendered.text : 'Workflow launch requested.',\n level: 'info',\n });\n },\n },\n ],\n onDispose() {\n control?.dispose();\n control = undefined;\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../services/webWorkflowCatalog/index.cjs"),t=require("../services/workflowCatalogDeps/index.cjs"),n=require("../types/webWorkflows.cjs");function r(r={}){let a=e.createWorkflowCatalogReader(r.deps??t.defaultCatalogDeps());return{frameType:n.WORKFLOW_CATALOG_TYPE,start(t){let r=new Map,o=new Map,s=new Map,c=(e,n)=>{o.set(e.sessionId,n),t.publish(e.sessionId,n)},l=async n=>{let i;try{i={cwd:n.cwd,workflows:e.presentWorkflowCatalog(await a.read(n.cwd))}}catch(e){let r=e instanceof Error?e.message:String(e);i={cwd:n.cwd,workflows:[],warning:r},t.onNotice(`workflow catalog for ${n.cwd} is unavailable (${r})`)}r.get(n.sessionId)===n&&c(n,i)};return{payloadFor(e){return r.has(e.sessionId)?o.get(e.sessionId):void 0},sessionAdded(e){r.set(e.sessionId,e),s.get(e.sessionId)?.();let a=t.directEvents.subscribe(n.WORKFLOW_CATALOG_TYPE,e.sessionId,t=>{i(t)&&c(e,t)},{replayLatest:!0});s.set(e.sessionId,a),l(e)},sessionRemoved(e){s.get(e)?.(),s.delete(e),r.delete(e),o.delete(e)},close(){for(let e of s.values())e();s.clear(),r.clear(),o.clear()}}}}}function i(e){return typeof e==`object`&&!!e&&typeof e.cwd==`string`&&Array.isArray(e.workflows)}exports.createWorkflowCatalogChannel=r;
|
|
2
|
+
//# sourceMappingURL=workflowCatalogChannel.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflowCatalogChannel.cjs","names":["createWorkflowCatalogReader","defaultCatalogDeps","WORKFLOW_CATALOG_TYPE","presentWorkflowCatalog"],"sources":["../../../src/controllers/workflowCatalogChannel.ts"],"sourcesContent":["import type { DoomHubChannelSource, DoomHubSessionScope, DoomHubChannel } from '@agimon-ai/doompi-core/hub-channel';\n\nimport {\n createWorkflowCatalogReader,\n presentWorkflowCatalog,\n type WorkflowCatalogReaderDeps,\n} from '../services/webWorkflowCatalog';\nimport { defaultCatalogDeps } from '../services/workflowCatalogDeps';\nimport { WORKFLOW_CATALOG_TYPE, type WorkflowCatalogPayload } from '../types/webWorkflows';\n\nexport interface WorkflowCatalogChannelOptions {\n deps?: WorkflowCatalogReaderDeps;\n}\n\n/**\n * The workflow catalog channel. Durable state seeds a session once, then\n * session lifecycle events deliver updates over the direct event bus.\n */\nexport function createWorkflowCatalogChannel(options: WorkflowCatalogChannelOptions = {}): DoomHubChannel {\n const reader = createWorkflowCatalogReader(options.deps ?? defaultCatalogDeps());\n return {\n frameType: WORKFLOW_CATALOG_TYPE,\n start(host) {\n const scopes = new Map<string, DoomHubSessionScope>();\n const latest = new Map<string, WorkflowCatalogPayload>();\n const subscriptions = new Map<string, () => void>();\n const publish = (scope: DoomHubSessionScope, payload: WorkflowCatalogPayload): void => {\n latest.set(scope.sessionId, payload);\n host.publish(scope.sessionId, payload);\n };\n const readInitial = async (scope: DoomHubSessionScope): Promise<void> => {\n let payload: WorkflowCatalogPayload;\n try {\n payload = {\n cwd: scope.cwd,\n workflows: presentWorkflowCatalog(await reader.read(scope.cwd)),\n };\n } catch (error) {\n const warning = error instanceof Error ? error.message : String(error);\n payload = { cwd: scope.cwd, workflows: [], warning };\n host.onNotice(`workflow catalog for ${scope.cwd} is unavailable (${warning})`);\n }\n if (scopes.get(scope.sessionId) === scope) publish(scope, payload);\n };\n const source: DoomHubChannelSource = {\n payloadFor(scope) {\n return scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : undefined;\n },\n sessionAdded(scope) {\n scopes.set(scope.sessionId, scope);\n subscriptions.get(scope.sessionId)?.();\n const unsubscribe = host.directEvents.subscribe(\n WORKFLOW_CATALOG_TYPE,\n scope.sessionId,\n (value) => {\n if (isWorkflowCatalogPayload(value)) publish(scope, value);\n },\n { replayLatest: true },\n );\n subscriptions.set(scope.sessionId, unsubscribe);\n void readInitial(scope);\n },\n sessionRemoved(sessionId) {\n subscriptions.get(sessionId)?.();\n subscriptions.delete(sessionId);\n scopes.delete(sessionId);\n latest.delete(sessionId);\n },\n close() {\n for (const unsubscribe of subscriptions.values()) unsubscribe();\n subscriptions.clear();\n scopes.clear();\n latest.clear();\n },\n };\n return source;\n },\n };\n}\n\nfunction isWorkflowCatalogPayload(value: unknown): value is WorkflowCatalogPayload {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { cwd?: unknown }).cwd === 'string' &&\n Array.isArray((value as { workflows?: unknown }).workflows)\n );\n}\n"],"mappings":"0JAkBA,SAAgB,EAA6B,EAAyC,CAAC,EAAmB,CACxG,IAAM,EAASA,EAAAA,4BAA4B,EAAQ,MAAQC,EAAAA,mBAAmB,CAAC,EAC/E,MAAO,CACL,UAAWC,EAAAA,sBACX,MAAM,EAAM,CACV,IAAM,EAAS,IAAI,IACb,EAAS,IAAI,IACb,EAAgB,IAAI,IACpB,GAAW,EAA4B,IAA0C,CACrF,EAAO,IAAI,EAAM,UAAW,CAAO,EACnC,EAAK,QAAQ,EAAM,UAAW,CAAO,CACvC,EACM,EAAc,KAAO,IAA8C,CACvE,IAAI,EACJ,GAAI,CACF,EAAU,CACR,IAAK,EAAM,IACX,UAAWC,EAAAA,uBAAuB,MAAM,EAAO,KAAK,EAAM,GAAG,CAAC,CAChE,CACF,OAAS,EAAO,CACd,IAAM,EAAU,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACrE,EAAU,CAAE,IAAK,EAAM,IAAK,UAAW,CAAC,EAAG,SAAQ,EACnD,EAAK,SAAS,wBAAwB,EAAM,IAAI,mBAAmB,EAAQ,EAAE,CAC/E,CACI,EAAO,IAAI,EAAM,SAAS,IAAM,GAAO,EAAQ,EAAO,CAAO,CACnE,EAgCA,MAAO,CA9BL,WAAW,EAAO,CAChB,OAAO,EAAO,IAAI,EAAM,SAAS,EAAI,EAAO,IAAI,EAAM,SAAS,EAAI,IAAA,EACrE,EACA,aAAa,EAAO,CAClB,EAAO,IAAI,EAAM,UAAW,CAAK,EACjC,EAAc,IAAI,EAAM,SAAS,CAAC,GAAG,EACrC,IAAM,EAAc,EAAK,aAAa,UACpCD,EAAAA,sBACA,EAAM,UACL,GAAU,CACL,EAAyB,CAAK,GAAG,EAAQ,EAAO,CAAK,CAC3D,EACA,CAAE,aAAc,EAAK,CACvB,EACA,EAAc,IAAI,EAAM,UAAW,CAAW,EAC9C,EAAiB,CAAK,CACxB,EACA,eAAe,EAAW,CACxB,EAAc,IAAI,CAAS,CAAC,GAAG,EAC/B,EAAc,OAAO,CAAS,EAC9B,EAAO,OAAO,CAAS,EACvB,EAAO,OAAO,CAAS,CACzB,EACA,OAAQ,CACN,IAAK,IAAM,KAAe,EAAc,OAAO,EAAG,EAAY,EAC9D,EAAc,MAAM,EACpB,EAAO,MAAM,EACb,EAAO,MAAM,CACf,CAEU,CACd,CACF,CACF,CAEA,SAAS,EAAyB,EAAiD,CACjF,OACE,OAAO,GAAU,YACjB,GACA,OAAQ,EAA4B,KAAQ,UAC5C,MAAM,QAAS,EAAkC,SAAS,CAE9D"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createWorkflowCatalogReader as e,presentWorkflowCatalog as t}from"../services/webWorkflowCatalog/index.mjs";import{defaultCatalogDeps as n}from"../services/workflowCatalogDeps/index.mjs";import{WORKFLOW_CATALOG_TYPE as r}from"../types/webWorkflows.mjs";function i(i={}){let o=e(i.deps??n());return{frameType:r,start(e){let n=new Map,i=new Map,s=new Map,c=(t,n)=>{i.set(t.sessionId,n),e.publish(t.sessionId,n)},l=async r=>{let i;try{i={cwd:r.cwd,workflows:t(await o.read(r.cwd))}}catch(t){let n=t instanceof Error?t.message:String(t);i={cwd:r.cwd,workflows:[],warning:n},e.onNotice(`workflow catalog for ${r.cwd} is unavailable (${n})`)}n.get(r.sessionId)===r&&c(r,i)};return{payloadFor(e){return n.has(e.sessionId)?i.get(e.sessionId):void 0},sessionAdded(t){n.set(t.sessionId,t),s.get(t.sessionId)?.();let i=e.directEvents.subscribe(r,t.sessionId,e=>{a(e)&&c(t,e)},{replayLatest:!0});s.set(t.sessionId,i),l(t)},sessionRemoved(e){s.get(e)?.(),s.delete(e),n.delete(e),i.delete(e)},close(){for(let e of s.values())e();s.clear(),n.clear(),i.clear()}}}}}function a(e){return typeof e==`object`&&!!e&&typeof e.cwd==`string`&&Array.isArray(e.workflows)}export{i as createWorkflowCatalogChannel};
|
|
2
|
+
//# sourceMappingURL=workflowCatalogChannel.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflowCatalogChannel.mjs","names":[],"sources":["../../../src/controllers/workflowCatalogChannel.ts"],"sourcesContent":["import type { DoomHubChannelSource, DoomHubSessionScope, DoomHubChannel } from '@agimon-ai/doompi-core/hub-channel';\n\nimport {\n createWorkflowCatalogReader,\n presentWorkflowCatalog,\n type WorkflowCatalogReaderDeps,\n} from '../services/webWorkflowCatalog';\nimport { defaultCatalogDeps } from '../services/workflowCatalogDeps';\nimport { WORKFLOW_CATALOG_TYPE, type WorkflowCatalogPayload } from '../types/webWorkflows';\n\nexport interface WorkflowCatalogChannelOptions {\n deps?: WorkflowCatalogReaderDeps;\n}\n\n/**\n * The workflow catalog channel. Durable state seeds a session once, then\n * session lifecycle events deliver updates over the direct event bus.\n */\nexport function createWorkflowCatalogChannel(options: WorkflowCatalogChannelOptions = {}): DoomHubChannel {\n const reader = createWorkflowCatalogReader(options.deps ?? defaultCatalogDeps());\n return {\n frameType: WORKFLOW_CATALOG_TYPE,\n start(host) {\n const scopes = new Map<string, DoomHubSessionScope>();\n const latest = new Map<string, WorkflowCatalogPayload>();\n const subscriptions = new Map<string, () => void>();\n const publish = (scope: DoomHubSessionScope, payload: WorkflowCatalogPayload): void => {\n latest.set(scope.sessionId, payload);\n host.publish(scope.sessionId, payload);\n };\n const readInitial = async (scope: DoomHubSessionScope): Promise<void> => {\n let payload: WorkflowCatalogPayload;\n try {\n payload = {\n cwd: scope.cwd,\n workflows: presentWorkflowCatalog(await reader.read(scope.cwd)),\n };\n } catch (error) {\n const warning = error instanceof Error ? error.message : String(error);\n payload = { cwd: scope.cwd, workflows: [], warning };\n host.onNotice(`workflow catalog for ${scope.cwd} is unavailable (${warning})`);\n }\n if (scopes.get(scope.sessionId) === scope) publish(scope, payload);\n };\n const source: DoomHubChannelSource = {\n payloadFor(scope) {\n return scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : undefined;\n },\n sessionAdded(scope) {\n scopes.set(scope.sessionId, scope);\n subscriptions.get(scope.sessionId)?.();\n const unsubscribe = host.directEvents.subscribe(\n WORKFLOW_CATALOG_TYPE,\n scope.sessionId,\n (value) => {\n if (isWorkflowCatalogPayload(value)) publish(scope, value);\n },\n { replayLatest: true },\n );\n subscriptions.set(scope.sessionId, unsubscribe);\n void readInitial(scope);\n },\n sessionRemoved(sessionId) {\n subscriptions.get(sessionId)?.();\n subscriptions.delete(sessionId);\n scopes.delete(sessionId);\n latest.delete(sessionId);\n },\n close() {\n for (const unsubscribe of subscriptions.values()) unsubscribe();\n subscriptions.clear();\n scopes.clear();\n latest.clear();\n },\n };\n return source;\n },\n };\n}\n\nfunction isWorkflowCatalogPayload(value: unknown): value is WorkflowCatalogPayload {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { cwd?: unknown }).cwd === 'string' &&\n Array.isArray((value as { workflows?: unknown }).workflows)\n );\n}\n"],"mappings":"oQAkBA,SAAgB,EAA6B,EAAyC,CAAC,EAAmB,CACxG,IAAM,EAAS,EAA4B,EAAQ,MAAQ,EAAmB,CAAC,EAC/E,MAAO,CACL,UAAW,EACX,MAAM,EAAM,CACV,IAAM,EAAS,IAAI,IACb,EAAS,IAAI,IACb,EAAgB,IAAI,IACpB,GAAW,EAA4B,IAA0C,CACrF,EAAO,IAAI,EAAM,UAAW,CAAO,EACnC,EAAK,QAAQ,EAAM,UAAW,CAAO,CACvC,EACM,EAAc,KAAO,IAA8C,CACvE,IAAI,EACJ,GAAI,CACF,EAAU,CACR,IAAK,EAAM,IACX,UAAW,EAAuB,MAAM,EAAO,KAAK,EAAM,GAAG,CAAC,CAChE,CACF,OAAS,EAAO,CACd,IAAM,EAAU,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACrE,EAAU,CAAE,IAAK,EAAM,IAAK,UAAW,CAAC,EAAG,SAAQ,EACnD,EAAK,SAAS,wBAAwB,EAAM,IAAI,mBAAmB,EAAQ,EAAE,CAC/E,CACI,EAAO,IAAI,EAAM,SAAS,IAAM,GAAO,EAAQ,EAAO,CAAO,CACnE,EAgCA,MAAO,CA9BL,WAAW,EAAO,CAChB,OAAO,EAAO,IAAI,EAAM,SAAS,EAAI,EAAO,IAAI,EAAM,SAAS,EAAI,IAAA,EACrE,EACA,aAAa,EAAO,CAClB,EAAO,IAAI,EAAM,UAAW,CAAK,EACjC,EAAc,IAAI,EAAM,SAAS,CAAC,GAAG,EACrC,IAAM,EAAc,EAAK,aAAa,UACpC,EACA,EAAM,UACL,GAAU,CACL,EAAyB,CAAK,GAAG,EAAQ,EAAO,CAAK,CAC3D,EACA,CAAE,aAAc,EAAK,CACvB,EACA,EAAc,IAAI,EAAM,UAAW,CAAW,EAC9C,EAAiB,CAAK,CACxB,EACA,eAAe,EAAW,CACxB,EAAc,IAAI,CAAS,CAAC,GAAG,EAC/B,EAAc,OAAO,CAAS,EAC9B,EAAO,OAAO,CAAS,EACvB,EAAO,OAAO,CAAS,CACzB,EACA,OAAQ,CACN,IAAK,IAAM,KAAe,EAAc,OAAO,EAAG,EAAY,EAC9D,EAAc,MAAM,EACpB,EAAO,MAAM,EACb,EAAO,MAAM,CACf,CAEU,CACd,CACF,CACF,CAEA,SAAS,EAAyB,EAAiD,CACjF,OACE,OAAO,GAAU,YACjB,GACA,OAAQ,EAA4B,KAAQ,UAC5C,MAAM,QAAS,EAAkC,SAAS,CAE9D"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../services/workflowTerminal/index.cjs"),n=require("../types/webWorkflowTerminal.cjs");let r=require("node:fs");r=e.__toESM(r,1);let i=require("node:path");i=e.__toESM(i,1);let a=require("@agimon-ai/workflow-mcp"),o=require("node:crypto"),s=require("node:stream"),c=require("hono"),l=require("hono/streaming");const u=[`running`,`error`,`completed`],d=524288,f=/^[\w.@-]+$/,p={".aac":`audio/aac`,".bmp":`image/bmp`,".css":`text/css`,".csv":`text/csv`,".gif":`image/gif`,".htm":`text/html`,".html":`text/html`,".ico":`image/x-icon`,".jpeg":`image/jpeg`,".jpg":`image/jpeg`,".js":`text/javascript`,".json":`application/json`,".jsx":`text/jsx`,".m4a":`audio/mp4`,".markdown":`text/markdown`,".md":`text/markdown`,".mov":`video/quicktime`,".mp3":`audio/mpeg`,".mp4":`video/mp4`,".oga":`audio/ogg`,".ogg":`audio/ogg`,".ogv":`video/ogg`,".pdf":`application/pdf`,".png":`image/png`,".sh":`text/x-shellscript`,".svg":`image/svg+xml`,".toml":`text/toml`,".ts":`text/typescript`,".tsv":`text/tab-separated-values`,".tsx":`text/tsx`,".txt":`text/plain`,".wav":`audio/wav`,".webm":`video/webm`,".webp":`image/webp`,".xml":`application/xml`,".yaml":`text/yaml`,".yml":`text/yaml`};async function m(e){let t=await e.req.json().catch(()=>void 0);return typeof t==`object`&&t&&!Array.isArray(t)?t:{}}function h(e){return e!==``&&e!==`../adapters`&&e!==`..`&&f.test(e)}function g(e,t){return`${e}/${t}`}function _(e={}){let i=e.registry??new a.WorkflowRegistryService,s=e.terminal??new a.WorkflowTerminalService,d=t.createWorkflowTerminalService({terminal:s,now:e.now??(()=>Date.now())}),f=new c.Hono,p=async(e,t)=>{if(h(e)&&h(t))for(let n of u)try{return await i.readRunByKey(e,n,t)}catch{}},_=(e,t)=>({error:`No workflow run '${t}' in workspace '${e}'.`});return f.get(`/runs/:workspace/:runKey/screen/stream`,async e=>{let t=e.req.param(`workspace`),r=e.req.param(`runKey`),i=await p(t,r);if(i===void 0)return e.json(_(t,r),404);let a=g(t,r);return(0,l.streamSSE)(e,async e=>{let o=0,s=!0;for(e.onAbort(()=>{s=!1});s;){let s=await p(t,r)??i,c=d.capabilities(s),l=c.readable?await d.screen(a,s,48):[],u=s.stage!==`running`;u&&(o+=1);let f=u&&o>=4,m={lines:l,capabilities:c,...f?{ended:!0}:{}};if(await e.writeSSE({event:n.WORKFLOW_SCREEN_EVENT,data:JSON.stringify(m)}),f)break;await e.sleep(500)}d.forget(new Set)})}),f.post(`/runs/:workspace/:runKey/control`,async e=>{let t=e.req.param(`workspace`),n=e.req.param(`runKey`),r=await p(t,n);if(r===void 0)return e.json(_(t,n),404);let i=g(t,n),a=await m(e),s=d.capabilities(r);if(a.release===!0)return typeof a.token==`string`&&d.releaseControl(i,a.token),e.json({held:!1});if(!s.writable){let t={held:!1,reason:s.reason};return e.json(t,409)}let c=typeof a.token==`string`&&a.token!==``?a.token:(0,o.randomUUID)();if(!d.takeControl(i,c))return e.json({held:!1,reason:`Another reader holds the keyboard.`},409);let l={held:!0,token:c};return e.json(l)}),f.post(`/runs/:workspace/:runKey/keys`,async e=>{let t=e.req.param(`workspace`),n=e.req.param(`runKey`),r=await p(t,n);if(r===void 0)return e.json(_(t,n),404);let i=await m(e);if(typeof i.token!=`string`||typeof i.data!=`string`)return e.json({error:`A keystroke needs a control token and its data.`},400);try{await d.write(g(t,n),r,i.token,i.data)}catch(t){return e.json({error:t instanceof Error?t.message:String(t)},409)}return e.body(null,204)}),f.post(`/runs/:workspace/:runKey/resize`,async e=>{let t=e.req.param(`workspace`),n=e.req.param(`runKey`),r=await p(t,n);if(r===void 0)return e.json(_(t,n),404);let{token:i,columns:a,rows:o}=await m(e);if(typeof i!=`string`||typeof a!=`number`||typeof o!=`number`)return e.json({error:`A resize needs a control token, columns and rows.`},400);try{let s=await d.resize(g(t,n),r,i,a,o);return e.json({resized:s})}catch(t){return e.json({error:t instanceof Error?t.message:String(t)},409)}}),f.delete(`/runs/:workspace/:runKey`,async e=>{let t=e.req.param(`workspace`),n=e.req.param(`runKey`),a=await p(t,n);if(a===void 0)return e.json(_(t,n),404);if(a.stage===`running`)return e.json({error:`A running workflow must be stopped before it can be deleted.`},409);try{r.default.rmSync(i.runDirectoryFor(a),{recursive:!0,force:!0})}catch(t){return e.json({error:t instanceof Error?t.message:String(t)},409)}return e.json({deleted:!0})}),f.get(`/runs/:workspace/:runKey/artifacts`,async e=>{let t=e.req.param(`workspace`),n=e.req.param(`runKey`),r=await p(t,n);if(r===void 0)return e.json(_(t,n),404);let a=i.runDirectoryFor(r),o={runDir:a,description:r.runDirectory?.description??``,artifacts:S(a,r)};return e.json(o)}),f.get(`/runs/:workspace/:runKey/artifacts/:name{.+}`,async e=>{let t=e.req.param(`workspace`),n=e.req.param(`runKey`),r=await p(t,n);if(r===void 0)return e.json(_(t,n),404);let a=i.runDirectoryFor(r),o=e.req.param(`name`),s=v(a,o);if(s===void 0)return e.json({error:`'${o}' is not inside this run.`},400);if(e.req.query(`raw`)===`1`)return E(s,o,e.req.header(`range`),e.req.query(`download`)===`1`)??e.json({error:`'${o}' has not been written.`},404);let c=T(s,o);return c===void 0?e.json({error:`'${o}' has not been written.`},404):e.json(c)}),f}function v(e,t){let n=i.default.resolve(e,t),r=i.default.resolve(e);if(n===r||n.startsWith(`${r}${i.default.sep}`))return n}function y(e){try{return r.default.statSync(e)}catch{return}}function b(e){return e===void 0?`pending`:e.isDirectory()?`written`:e.size===0?`empty`:`written`}function x(e,t){let n=y(i.default.join(e,t.path));return{...t,state:b(n),...n===void 0?{}:{size:n.size,modifiedAt:n.mtime.toISOString()}}}function S(e,t){let n=(t.runDirectory?.entries??[]).map(t=>x(e,{path:t.path,kind:t.kind,description:t.description,producedBy:t[`produced-by`]??[],declared:!0})),i=new Set(n.map(e=>e.path)),a;try{a=r.default.readdirSync(e,{withFileTypes:!0})}catch{return n}let o=a.filter(e=>!i.has(e.name)).map(t=>x(e,{path:t.name,kind:t.isDirectory()?`directory`:`file`,description:``,producedBy:[],declared:!1})).sort((e,t)=>e.path.localeCompare(t.path));return[...n,...o]}function C(e){return p[i.default.extname(e).toLowerCase()]??`application/octet-stream`}function w(e){return e.startsWith(`text/`)||e===`application/json`||e===`application/xml`}function T(e,t){let n=y(e);if(n===void 0||n.isDirectory())return;let i=C(t),a;if(w(i))try{let t=r.default.openSync(e,`r`);try{let e=Buffer.alloc(Math.min(n.size,d));r.default.readSync(t,e,0,e.length,0),a=e.toString(`utf8`)}finally{r.default.closeSync(t)}}catch{return}return{path:t,size:n.size,modifiedAt:n.mtime.toISOString(),mimeType:i,...a===void 0?{}:{text:a},truncated:a!==void 0&&n.size>d}}function E(e,t,n,a){let o=y(e);if(o===void 0||o.isDirectory())return;let c=C(t),l=0,u=Math.max(0,o.size-1),d=!1,f=n?.match(/^bytes=(\d*)-(\d*)$/);if(f!=null&&o.size>0){let e=f[1]===``?void 0:Number(f[1]),t=f[2]===``?void 0:Number(f[2]);if(e===void 0&&t!==void 0?l=Math.max(0,o.size-t):e!==void 0&&(l=e,u=t===void 0?u:Math.min(t,u)),l>=o.size||l>u)return new Response(null,{status:416,headers:{"content-range":`bytes */${String(o.size)}`}});d=!0}let p=i.default.basename(t).replace(/["\\\r\n]/g,`_`),m=new Headers({"accept-ranges":`bytes`,"content-disposition":`${a||c===`text/html`?`attachment`:`inline`}; filename="${p}"`,"content-length":String(o.size===0?0:u-l+1),"content-type":c,"x-content-type-options":`nosniff`});if(d&&m.set(`content-range`,`bytes ${String(l)}-${String(u)}/${String(o.size)}`),o.size===0)return new Response(null,{status:200,headers:m});let h=s.Readable.toWeb(r.default.createReadStream(e,{start:l,end:u}));return new Response(h,{status:d?206:200,headers:m})}const D={basePath:n.WORKFLOW_API_BASE_PATH,start(e){let t=_();return{fetch:e=>t.fetch(e),close:()=>void 0}}};exports.api=D,exports.createWorkflowHubApi=_;
|
|
2
|
+
//# sourceMappingURL=workflowHubApi.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflowHubApi.cjs","names":["WorkflowRegistryService","WorkflowTerminalFacade","createWorkflowTerminalService","Hono","streamSSE","WORKFLOW_SCREEN_EVENT","randomUUID","path","fs","Readable","WORKFLOW_API_BASE_PATH"],"sources":["../../../src/controllers/workflowHubApi.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { Readable } from 'node:stream';\n\nimport type { DoomApi, DoomApiContext, DoomApiHandler } from '@agimon-ai/doompi-core/package-api';\nimport {\n WorkflowRegistryService,\n WorkflowTerminalService as WorkflowTerminalFacade,\n type WorkflowRunRecord,\n type WorkflowStage,\n} from '@agimon-ai/workflow-mcp';\nimport { type Context, Hono } from 'hono';\nimport { streamSSE } from 'hono/streaming';\n\nimport { createWorkflowTerminalService } from '../services/workflowTerminal';\nimport {\n WORKFLOW_API_BASE_PATH,\n WORKFLOW_SCREEN_EVENT,\n type WorkflowArtifactContentResponse,\n type WorkflowArtifactsResponse,\n type WorkflowArtifactView,\n type WorkflowControlResponse,\n type WorkflowDeleteResponse,\n type WorkflowScreenEvent,\n} from '../types/webWorkflowTerminal';\n\n/** Stages a run can be recorded under, newest first: a live run is the common case. */\nconst STAGES: readonly WorkflowStage[] = ['running', 'error', 'completed'];\n/** Lines of screen the stream sends, which is a terminal's visible height plus room. */\nconst SCREEN_LINES = 48;\n/** How often the stream re-reads; the service coalesces, so this is an upper bound. */\nconst STREAM_TICK_MS = 500;\n/** How often a settled run is re-checked before the stream closes itself. */\nconst SETTLED_POLL_TICKS = 4;\n/** Bytes of one textual artifact returned as JSON; binary previews use a stream. */\nconst MAX_ARTIFACT_BYTES = 512 * 1024;\n/** Path segments a client supplies are names, never paths. */\nconst SAFE_SEGMENT = /^[\\w.@-]+$/;\nconst ARTIFACT_MIME_TYPES: Readonly<Record<string, string>> = {\n '.aac': 'audio/aac',\n '.bmp': 'image/bmp',\n '.css': 'text/css',\n '.csv': 'text/csv',\n '.gif': 'image/gif',\n '.htm': 'text/html',\n '.html': 'text/html',\n '.ico': 'image/x-icon',\n '.jpeg': 'image/jpeg',\n '.jpg': 'image/jpeg',\n '.js': 'text/javascript',\n '.json': 'application/json',\n '.jsx': 'text/jsx',\n '.m4a': 'audio/mp4',\n '.markdown': 'text/markdown',\n '.md': 'text/markdown',\n '.mov': 'video/quicktime',\n '.mp3': 'audio/mpeg',\n '.mp4': 'video/mp4',\n '.oga': 'audio/ogg',\n '.ogg': 'audio/ogg',\n '.ogv': 'video/ogg',\n '.pdf': 'application/pdf',\n '.png': 'image/png',\n '.sh': 'text/x-shellscript',\n '.svg': 'image/svg+xml',\n '.toml': 'text/toml',\n '.ts': 'text/typescript',\n '.tsv': 'text/tab-separated-values',\n '.tsx': 'text/tsx',\n '.txt': 'text/plain',\n '.wav': 'audio/wav',\n '.webm': 'video/webm',\n '.webp': 'image/webp',\n '.xml': 'application/xml',\n '.yaml': 'text/yaml',\n '.yml': 'text/yaml',\n};\n\n/**\n * One request's JSON body as a plain record.\n *\n * A body that is absent, malformed, or not an object reads as empty rather\n * than failing the route: every field is checked by the route anyway, and a\n * 400 naming the missing field beats a parse error naming nothing.\n */\nasync function jsonBody(context: Context): Promise<Record<string, unknown>> {\n const parsed: unknown = await context.req.json().catch(() => undefined);\n return parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n}\n\n/** Rejects anything that could climb out of the registry before a path is built. */\nfunction isSafeSegment(value: string): boolean {\n return value !== '' && value !== '../adapters' && value !== '..' && SAFE_SEGMENT.test(value);\n}\n\n/** One run's identity for caches and leases, stable across stage moves. */\nfunction runIdentityOf(workspace: string, runKey: string): string {\n return `${workspace}/${runKey}`;\n}\n\nexport interface WorkflowHubApiOptions {\n registry?: WorkflowRegistryService;\n terminal?: WorkflowTerminalFacade;\n now?: () => number;\n}\n\n/**\n * This package's HTTP surface: one workflow run's terminal, and the files its\n * run directory holds.\n *\n * Mounted in the hub rather than in a session's server, because a run's\n * terminal belongs to its multiplexer rather than to the session that launched\n * it: any process can read a tmux pane, and the session's own server cannot\n * reach anything more. The routes therefore name a run, never a session.\n */\nexport function createWorkflowHubApi(options: WorkflowHubApiOptions = {}): Hono {\n const registry = options.registry ?? new WorkflowRegistryService();\n const facade = options.terminal ?? new WorkflowTerminalFacade();\n const terminal = createWorkflowTerminalService<WorkflowRunRecord>({\n terminal: facade,\n now: options.now ?? (() => Date.now()),\n });\n const app = new Hono();\n\n /** The record behind a request, whichever stage it now sits in. */\n const runOf = async (workspace: string, runKey: string): Promise<WorkflowRunRecord | undefined> => {\n if (!isSafeSegment(workspace) || !isSafeSegment(runKey)) return undefined;\n for (const stage of STAGES) {\n try {\n return await registry.readRunByKey(workspace, stage, runKey);\n } catch {\n // Not in this stage. A run moves between them as it settles, so a miss\n // here is ordinary; only a miss in every stage means no such run.\n }\n }\n return undefined;\n };\n\n const missing = (workspace: string, runKey: string): { error: string } => ({\n error: `No workflow run '${runKey}' in workspace '${workspace}'.`,\n });\n\n app.get('/runs/:workspace/:runKey/screen/stream', async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const identity = runIdentityOf(workspace, runKey);\n\n return streamSSE(context, async (stream) => {\n let settledTicks = 0;\n let running = true;\n stream.onAbort(() => {\n running = false;\n });\n while (running) {\n const current = (await runOf(workspace, runKey)) ?? record;\n const capabilities = terminal.capabilities(current);\n const lines = capabilities.readable ? await terminal.screen(identity, current, SCREEN_LINES) : [];\n // A settled run is read a few more times before the stream closes: the\n // last thing a failing step printed is what the reader came for, and it\n // lands after the record has already moved to its final stage.\n const settled = current.stage !== 'running';\n if (settled) settledTicks += 1;\n const ended = settled && settledTicks >= SETTLED_POLL_TICKS;\n const event: WorkflowScreenEvent = { lines, capabilities, ...(ended ? { ended: true } : {}) };\n await stream.writeSSE({ event: WORKFLOW_SCREEN_EVENT, data: JSON.stringify(event) });\n if (ended) break;\n await stream.sleep(STREAM_TICK_MS);\n }\n terminal.forget(new Set());\n });\n });\n\n app.post('/runs/:workspace/:runKey/control', async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const identity = runIdentityOf(workspace, runKey);\n const body = await jsonBody(context);\n const capabilities = terminal.capabilities(record);\n\n if (body.release === true) {\n if (typeof body.token === 'string') terminal.releaseControl(identity, body.token);\n const released: WorkflowControlResponse = { held: false };\n return context.json(released);\n }\n if (!capabilities.writable) {\n const refused: WorkflowControlResponse = { held: false, reason: capabilities.reason };\n return context.json(refused, 409);\n }\n const token = typeof body.token === 'string' && body.token !== '' ? body.token : randomUUID();\n if (!terminal.takeControl(identity, token)) {\n const taken: WorkflowControlResponse = { held: false, reason: 'Another reader holds the keyboard.' };\n return context.json(taken, 409);\n }\n const held: WorkflowControlResponse = { held: true, token };\n return context.json(held);\n });\n\n app.post('/runs/:workspace/:runKey/keys', async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const body = await jsonBody(context);\n if (typeof body.token !== 'string' || typeof body.data !== 'string') {\n return context.json({ error: 'A keystroke needs a control token and its data.' }, 400);\n }\n try {\n await terminal.write(runIdentityOf(workspace, runKey), record, body.token, body.data);\n } catch (error) {\n return context.json({ error: error instanceof Error ? error.message : String(error) }, 409);\n }\n return context.body(null, 204);\n });\n\n app.post('/runs/:workspace/:runKey/resize', async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const body = await jsonBody(context);\n const { token, columns, rows } = body;\n if (typeof token !== 'string' || typeof columns !== 'number' || typeof rows !== 'number') {\n return context.json({ error: 'A resize needs a control token, columns and rows.' }, 400);\n }\n try {\n const resized = await terminal.resize(runIdentityOf(workspace, runKey), record, token, columns, rows);\n return context.json({ resized });\n } catch (error) {\n return context.json({ error: error instanceof Error ? error.message : String(error) }, 409);\n }\n });\n\n app.delete('/runs/:workspace/:runKey', async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n if (record.stage === 'running') {\n return context.json({ error: 'A running workflow must be stopped before it can be deleted.' }, 409);\n }\n try {\n fs.rmSync(registry.runDirectoryFor(record), { recursive: true, force: true });\n } catch (error) {\n return context.json({ error: error instanceof Error ? error.message : String(error) }, 409);\n }\n const response: WorkflowDeleteResponse = { deleted: true };\n return context.json(response);\n });\n\n app.get('/runs/:workspace/:runKey/artifacts', async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const runDir = registry.runDirectoryFor(record);\n const body: WorkflowArtifactsResponse = {\n runDir,\n description: record.runDirectory?.description ?? '',\n artifacts: readArtifacts(runDir, record),\n };\n return context.json(body);\n });\n\n app.get('/runs/:workspace/:runKey/artifacts/:name{.+}', async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const runDir = registry.runDirectoryFor(record);\n const requested = context.req.param('name');\n const resolved = resolveInside(runDir, requested);\n if (resolved === undefined) return context.json({ error: `'${requested}' is not inside this run.` }, 400);\n if (context.req.query('raw') === '1') {\n const response = streamArtifact(\n resolved,\n requested,\n context.req.header('range'),\n context.req.query('download') === '1',\n );\n return response ?? context.json({ error: `'${requested}' has not been written.` }, 404);\n }\n const body = readArtifact(resolved, requested);\n if (body === undefined) return context.json({ error: `'${requested}' has not been written.` }, 404);\n return context.json(body);\n });\n\n return app;\n}\n\n/**\n * A path inside the run directory, or undefined when it points anywhere else.\n *\n * The client supplies this one verbatim, unlike the run key, so it is resolved\n * and then checked rather than trusted: without the check the route would read\n * any file the hub can reach.\n */\nfunction resolveInside(runDir: string, requested: string): string | undefined {\n const resolved = path.resolve(runDir, requested);\n const root = path.resolve(runDir);\n if (resolved !== root && !resolved.startsWith(`${root}${path.sep}`)) return undefined;\n return resolved;\n}\n\n/** Size and modification time of one path, or undefined when it is not there. */\nfunction statOf(target: string): fs.Stats | undefined {\n try {\n return fs.statSync(target);\n } catch {\n return undefined; // Not written yet, which is an ordinary state for an artifact.\n }\n}\n\nfunction stateOf(stats: fs.Stats | undefined): WorkflowArtifactView['state'] {\n if (stats === undefined) return 'pending';\n if (stats.isDirectory()) return 'written';\n return stats.size === 0 ? 'empty' : 'written';\n}\n\nfunction viewOf(\n runDir: string,\n entry: Omit<WorkflowArtifactView, 'state' | 'size' | 'modifiedAt'>,\n): WorkflowArtifactView {\n const stats = statOf(path.join(runDir, entry.path));\n return {\n ...entry,\n state: stateOf(stats),\n ...(stats === undefined ? {} : { size: stats.size, modifiedAt: stats.mtime.toISOString() }),\n };\n}\n\n/**\n * What the run directory holds: the workflow's own declaration first, then the\n * files nobody declared.\n *\n * The declaration is the point of the folder, so it leads and keeps its order\n * even for entries no job has written yet. The rest follows rather than being\n * hidden: the engine's own context.md and progress log are often exactly what a\n * reader is looking for.\n */\nfunction readArtifacts(runDir: string, record: WorkflowRunRecord): WorkflowArtifactView[] {\n const declared = (record.runDirectory?.entries ?? []).map((entry) =>\n viewOf(runDir, {\n path: entry.path,\n kind: entry.kind,\n description: entry.description,\n producedBy: entry['produced-by'] ?? [],\n declared: true,\n }),\n );\n const claimed = new Set(declared.map((entry) => entry.path));\n let names: fs.Dirent[];\n try {\n names = fs.readdirSync(runDir, { withFileTypes: true });\n } catch {\n return declared; // The directory is gone; the declaration is still worth showing.\n }\n const found = names\n .filter((entry) => !claimed.has(entry.name))\n .map((entry) =>\n viewOf(runDir, {\n path: entry.name,\n kind: entry.isDirectory() ? 'directory' : 'file',\n description: '',\n producedBy: [],\n declared: false,\n }),\n )\n .sort((left, right) => left.path.localeCompare(right.path));\n return [...declared, ...found];\n}\n\n/** Browser content type inferred from a filename without trusting client input. */\nfunction artifactMimeType(requested: string): string {\n return ARTIFACT_MIME_TYPES[path.extname(requested).toLowerCase()] ?? 'application/octet-stream';\n}\n\nfunction isTextArtifact(mimeType: string): boolean {\n return mimeType.startsWith('text/') || mimeType === 'application/json' || mimeType === 'application/xml';\n}\n\n/** One artifact's metadata and bounded text, or undefined when it is not readable. */\nfunction readArtifact(resolved: string, requested: string): WorkflowArtifactContentResponse | undefined {\n const stats = statOf(resolved);\n if (stats === undefined || stats.isDirectory()) return undefined;\n const mimeType = artifactMimeType(requested);\n let text: string | undefined;\n if (isTextArtifact(mimeType)) {\n try {\n const handle = fs.openSync(resolved, 'r');\n try {\n const buffer = Buffer.alloc(Math.min(stats.size, MAX_ARTIFACT_BYTES));\n fs.readSync(handle, buffer, 0, buffer.length, 0);\n text = buffer.toString('utf8');\n } finally {\n fs.closeSync(handle);\n }\n } catch {\n return undefined;\n }\n }\n return {\n path: requested,\n size: stats.size,\n modifiedAt: stats.mtime.toISOString(),\n mimeType,\n ...(text === undefined ? {} : { text }),\n truncated: text !== undefined && stats.size > MAX_ARTIFACT_BYTES,\n };\n}\n\n/** Streams media with byte-range support so browser audio, video, and PDF controls can seek. */\nfunction streamArtifact(\n resolved: string,\n requested: string,\n rangeHeader: string | undefined,\n download: boolean,\n): Response | undefined {\n const stats = statOf(resolved);\n if (stats === undefined || stats.isDirectory()) return undefined;\n const mimeType = artifactMimeType(requested);\n let start = 0;\n let end = Math.max(0, stats.size - 1);\n let partial = false;\n const match = rangeHeader?.match(/^bytes=(\\d*)-(\\d*)$/);\n if (match !== null && match !== undefined && stats.size > 0) {\n const requestedStart = match[1] === '' ? undefined : Number(match[1]);\n const requestedEnd = match[2] === '' ? undefined : Number(match[2]);\n if (requestedStart === undefined && requestedEnd !== undefined) {\n start = Math.max(0, stats.size - requestedEnd);\n } else if (requestedStart !== undefined) {\n start = requestedStart;\n end = requestedEnd === undefined ? end : Math.min(requestedEnd, end);\n }\n if (start >= stats.size || start > end) {\n return new Response(null, { status: 416, headers: { 'content-range': `bytes */${String(stats.size)}` } });\n }\n partial = true;\n }\n const filename = path.basename(requested).replace(/[\"\\\\\\r\\n]/g, '_');\n const forceDownload = download || mimeType === 'text/html';\n const headers = new Headers({\n 'accept-ranges': 'bytes',\n 'content-disposition': `${forceDownload ? 'attachment' : 'inline'}; filename=\"${filename}\"`,\n 'content-length': String(stats.size === 0 ? 0 : end - start + 1),\n 'content-type': mimeType,\n 'x-content-type-options': 'nosniff',\n });\n if (partial) headers.set('content-range', `bytes ${String(start)}-${String(end)}/${String(stats.size)}`);\n if (stats.size === 0) return new Response(null, { status: 200, headers });\n const body = Readable.toWeb(fs.createReadStream(resolved, { start, end }));\n return new Response(body, { status: partial ? 206 : 200, headers });\n}\n\n/** The named export a host imports from this package's built hub entry. */\nexport const api: DoomApi = {\n basePath: WORKFLOW_API_BASE_PATH,\n start(_context: DoomApiContext): DoomApiHandler {\n // Hub-scoped: the host hands no session, and these routes want none. A run\n // is addressed by its registry identity, which is machine-wide.\n const app = createWorkflowHubApi();\n return {\n fetch: (request) => app.fetch(request),\n // Nothing outlives a request: a stream's loop ends when its own socket\n // aborts, and the caches it touched are per run rather than per client.\n close: () => undefined,\n };\n },\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createWorkflowTerminalService as e}from"../services/workflowTerminal/index.mjs";import{WORKFLOW_API_BASE_PATH as t,WORKFLOW_SCREEN_EVENT as n}from"../types/webWorkflowTerminal.mjs";import r from"node:fs";import i from"node:path";import{WorkflowRegistryService as a,WorkflowTerminalService as o}from"@agimon-ai/workflow-mcp";import{randomUUID as s}from"node:crypto";import{Readable as c}from"node:stream";import{Hono as l}from"hono";import{streamSSE as u}from"hono/streaming";const d=[`running`,`error`,`completed`],f=524288,p=/^[\w.@-]+$/,m={".aac":`audio/aac`,".bmp":`image/bmp`,".css":`text/css`,".csv":`text/csv`,".gif":`image/gif`,".htm":`text/html`,".html":`text/html`,".ico":`image/x-icon`,".jpeg":`image/jpeg`,".jpg":`image/jpeg`,".js":`text/javascript`,".json":`application/json`,".jsx":`text/jsx`,".m4a":`audio/mp4`,".markdown":`text/markdown`,".md":`text/markdown`,".mov":`video/quicktime`,".mp3":`audio/mpeg`,".mp4":`video/mp4`,".oga":`audio/ogg`,".ogg":`audio/ogg`,".ogv":`video/ogg`,".pdf":`application/pdf`,".png":`image/png`,".sh":`text/x-shellscript`,".svg":`image/svg+xml`,".toml":`text/toml`,".ts":`text/typescript`,".tsv":`text/tab-separated-values`,".tsx":`text/tsx`,".txt":`text/plain`,".wav":`audio/wav`,".webm":`video/webm`,".webp":`image/webp`,".xml":`application/xml`,".yaml":`text/yaml`,".yml":`text/yaml`};async function h(e){let t=await e.req.json().catch(()=>void 0);return typeof t==`object`&&t&&!Array.isArray(t)?t:{}}function g(e){return e!==``&&e!==`../adapters`&&e!==`..`&&p.test(e)}function _(e,t){return`${e}/${t}`}function v(t={}){let i=t.registry??new a,c=t.terminal??new o,f=e({terminal:c,now:t.now??(()=>Date.now())}),p=new l,m=async(e,t)=>{if(g(e)&&g(t))for(let n of d)try{return await i.readRunByKey(e,n,t)}catch{}},v=(e,t)=>({error:`No workflow run '${t}' in workspace '${e}'.`});return p.get(`/runs/:workspace/:runKey/screen/stream`,async e=>{let t=e.req.param(`workspace`),r=e.req.param(`runKey`),i=await m(t,r);if(i===void 0)return e.json(v(t,r),404);let a=_(t,r);return u(e,async e=>{let o=0,s=!0;for(e.onAbort(()=>{s=!1});s;){let s=await m(t,r)??i,c=f.capabilities(s),l=c.readable?await f.screen(a,s,48):[],u=s.stage!==`running`;u&&(o+=1);let d=u&&o>=4,p={lines:l,capabilities:c,...d?{ended:!0}:{}};if(await e.writeSSE({event:n,data:JSON.stringify(p)}),d)break;await e.sleep(500)}f.forget(new Set)})}),p.post(`/runs/:workspace/:runKey/control`,async e=>{let t=e.req.param(`workspace`),n=e.req.param(`runKey`),r=await m(t,n);if(r===void 0)return e.json(v(t,n),404);let i=_(t,n),a=await h(e),o=f.capabilities(r);if(a.release===!0)return typeof a.token==`string`&&f.releaseControl(i,a.token),e.json({held:!1});if(!o.writable){let t={held:!1,reason:o.reason};return e.json(t,409)}let c=typeof a.token==`string`&&a.token!==``?a.token:s();if(!f.takeControl(i,c))return e.json({held:!1,reason:`Another reader holds the keyboard.`},409);let l={held:!0,token:c};return e.json(l)}),p.post(`/runs/:workspace/:runKey/keys`,async e=>{let t=e.req.param(`workspace`),n=e.req.param(`runKey`),r=await m(t,n);if(r===void 0)return e.json(v(t,n),404);let i=await h(e);if(typeof i.token!=`string`||typeof i.data!=`string`)return e.json({error:`A keystroke needs a control token and its data.`},400);try{await f.write(_(t,n),r,i.token,i.data)}catch(t){return e.json({error:t instanceof Error?t.message:String(t)},409)}return e.body(null,204)}),p.post(`/runs/:workspace/:runKey/resize`,async e=>{let t=e.req.param(`workspace`),n=e.req.param(`runKey`),r=await m(t,n);if(r===void 0)return e.json(v(t,n),404);let{token:i,columns:a,rows:o}=await h(e);if(typeof i!=`string`||typeof a!=`number`||typeof o!=`number`)return e.json({error:`A resize needs a control token, columns and rows.`},400);try{let s=await f.resize(_(t,n),r,i,a,o);return e.json({resized:s})}catch(t){return e.json({error:t instanceof Error?t.message:String(t)},409)}}),p.delete(`/runs/:workspace/:runKey`,async e=>{let t=e.req.param(`workspace`),n=e.req.param(`runKey`),a=await m(t,n);if(a===void 0)return e.json(v(t,n),404);if(a.stage===`running`)return e.json({error:`A running workflow must be stopped before it can be deleted.`},409);try{r.rmSync(i.runDirectoryFor(a),{recursive:!0,force:!0})}catch(t){return e.json({error:t instanceof Error?t.message:String(t)},409)}return e.json({deleted:!0})}),p.get(`/runs/:workspace/:runKey/artifacts`,async e=>{let t=e.req.param(`workspace`),n=e.req.param(`runKey`),r=await m(t,n);if(r===void 0)return e.json(v(t,n),404);let a=i.runDirectoryFor(r),o={runDir:a,description:r.runDirectory?.description??``,artifacts:C(a,r)};return e.json(o)}),p.get(`/runs/:workspace/:runKey/artifacts/:name{.+}`,async e=>{let t=e.req.param(`workspace`),n=e.req.param(`runKey`),r=await m(t,n);if(r===void 0)return e.json(v(t,n),404);let a=i.runDirectoryFor(r),o=e.req.param(`name`),s=y(a,o);if(s===void 0)return e.json({error:`'${o}' is not inside this run.`},400);if(e.req.query(`raw`)===`1`)return D(s,o,e.req.header(`range`),e.req.query(`download`)===`1`)??e.json({error:`'${o}' has not been written.`},404);let c=E(s,o);return c===void 0?e.json({error:`'${o}' has not been written.`},404):e.json(c)}),p}function y(e,t){let n=i.resolve(e,t),r=i.resolve(e);if(n===r||n.startsWith(`${r}${i.sep}`))return n}function b(e){try{return r.statSync(e)}catch{return}}function x(e){return e===void 0?`pending`:e.isDirectory()?`written`:e.size===0?`empty`:`written`}function S(e,t){let n=b(i.join(e,t.path));return{...t,state:x(n),...n===void 0?{}:{size:n.size,modifiedAt:n.mtime.toISOString()}}}function C(e,t){let n=(t.runDirectory?.entries??[]).map(t=>S(e,{path:t.path,kind:t.kind,description:t.description,producedBy:t[`produced-by`]??[],declared:!0})),i=new Set(n.map(e=>e.path)),a;try{a=r.readdirSync(e,{withFileTypes:!0})}catch{return n}let o=a.filter(e=>!i.has(e.name)).map(t=>S(e,{path:t.name,kind:t.isDirectory()?`directory`:`file`,description:``,producedBy:[],declared:!1})).sort((e,t)=>e.path.localeCompare(t.path));return[...n,...o]}function w(e){return m[i.extname(e).toLowerCase()]??`application/octet-stream`}function T(e){return e.startsWith(`text/`)||e===`application/json`||e===`application/xml`}function E(e,t){let n=b(e);if(n===void 0||n.isDirectory())return;let i=w(t),a;if(T(i))try{let t=r.openSync(e,`r`);try{let e=Buffer.alloc(Math.min(n.size,f));r.readSync(t,e,0,e.length,0),a=e.toString(`utf8`)}finally{r.closeSync(t)}}catch{return}return{path:t,size:n.size,modifiedAt:n.mtime.toISOString(),mimeType:i,...a===void 0?{}:{text:a},truncated:a!==void 0&&n.size>f}}function D(e,t,n,a){let o=b(e);if(o===void 0||o.isDirectory())return;let s=w(t),l=0,u=Math.max(0,o.size-1),d=!1,f=n?.match(/^bytes=(\d*)-(\d*)$/);if(f!=null&&o.size>0){let e=f[1]===``?void 0:Number(f[1]),t=f[2]===``?void 0:Number(f[2]);if(e===void 0&&t!==void 0?l=Math.max(0,o.size-t):e!==void 0&&(l=e,u=t===void 0?u:Math.min(t,u)),l>=o.size||l>u)return new Response(null,{status:416,headers:{"content-range":`bytes */${String(o.size)}`}});d=!0}let p=i.basename(t).replace(/["\\\r\n]/g,`_`),m=new Headers({"accept-ranges":`bytes`,"content-disposition":`${a||s===`text/html`?`attachment`:`inline`}; filename="${p}"`,"content-length":String(o.size===0?0:u-l+1),"content-type":s,"x-content-type-options":`nosniff`});if(d&&m.set(`content-range`,`bytes ${String(l)}-${String(u)}/${String(o.size)}`),o.size===0)return new Response(null,{status:200,headers:m});let h=c.toWeb(r.createReadStream(e,{start:l,end:u}));return new Response(h,{status:d?206:200,headers:m})}const O={basePath:t,start(e){let t=v();return{fetch:e=>t.fetch(e),close:()=>void 0}}};export{O as api,v as createWorkflowHubApi};
|
|
2
|
+
//# sourceMappingURL=workflowHubApi.mjs.map
|