@agimon-ai/doompi-workflow 0.0.1-alpha.76 → 0.0.1-alpha.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (332) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +23 -0
  2. package/dist/api-contracts.cjs +7 -0
  3. package/dist/api-contracts.d.cts +2 -0
  4. package/dist/api-contracts.d.mts +2 -0
  5. package/dist/api-contracts.mjs +2 -0
  6. package/dist/extensions/pi.cjs +63 -0
  7. package/dist/extensions/pi.cjs.map +1 -0
  8. package/dist/extensions/pi.d.cts +6 -0
  9. package/dist/extensions/pi.d.cts.map +1 -0
  10. package/dist/extensions/pi.d.mts +6 -0
  11. package/dist/extensions/pi.d.mts.map +1 -0
  12. package/dist/extensions/pi.mjs +58 -0
  13. package/dist/extensions/pi.mjs.map +1 -0
  14. package/dist/extensions/server.cjs +96 -0
  15. package/dist/extensions/server.cjs.map +1 -0
  16. package/dist/extensions/server.d.cts +5 -0
  17. package/dist/extensions/server.d.cts.map +1 -0
  18. package/dist/extensions/server.d.mts +5 -0
  19. package/dist/extensions/server.d.mts.map +1 -0
  20. package/dist/extensions/server.mjs +91 -0
  21. package/dist/extensions/server.mjs.map +1 -0
  22. package/dist/extensions/web.mjs +3219 -0
  23. package/dist/extensions/web.mjs.map +1 -0
  24. package/dist/index.cjs +4 -0
  25. package/dist/index.d.cts +2 -0
  26. package/dist/index.d.mts +2 -0
  27. package/dist/index.mjs +2 -0
  28. package/dist/src/constants/workflow.cjs +32 -0
  29. package/dist/src/constants/workflow.cjs.map +1 -0
  30. package/dist/src/constants/workflow.mjs +21 -0
  31. package/dist/src/constants/workflow.mjs.map +1 -0
  32. package/dist/src/extensions/(backend)/_lib/index.server.cjs +12 -0
  33. package/dist/src/extensions/(backend)/_lib/index.server.cjs.map +1 -0
  34. package/dist/src/extensions/(backend)/_lib/index.server.mjs +12 -0
  35. package/dist/src/extensions/(backend)/_lib/index.server.mjs.map +1 -0
  36. package/dist/src/extensions/(backend)/api/workflow/route.server.cjs +7 -0
  37. package/dist/src/extensions/(backend)/api/workflow/route.server.cjs.map +1 -0
  38. package/dist/src/extensions/(backend)/api/workflow/route.server.mjs +8 -0
  39. package/dist/src/extensions/(backend)/api/workflow/route.server.mjs.map +1 -0
  40. package/dist/src/extensions/(backend)/channel/workflow-catalog.server.cjs +7 -0
  41. package/dist/src/extensions/(backend)/channel/workflow-catalog.server.cjs.map +1 -0
  42. package/dist/src/extensions/(backend)/channel/workflow-catalog.server.mjs +8 -0
  43. package/dist/src/extensions/(backend)/channel/workflow-catalog.server.mjs.map +1 -0
  44. package/dist/src/extensions/(backend)/channel/workflows.server.cjs +7 -0
  45. package/dist/src/extensions/(backend)/channel/workflows.server.cjs.map +1 -0
  46. package/dist/src/extensions/(backend)/channel/workflows.server.mjs +8 -0
  47. package/dist/src/extensions/(backend)/channel/workflows.server.mjs.map +1 -0
  48. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.cjs +100 -0
  49. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.cjs.map +1 -0
  50. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.mjs +100 -0
  51. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.mjs.map +1 -0
  52. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.cjs +11 -0
  53. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.cjs.map +1 -0
  54. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.mjs +11 -0
  55. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.mjs.map +1 -0
  56. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.cjs +12 -0
  57. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.cjs.map +1 -0
  58. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.mjs +12 -0
  59. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.mjs.map +1 -0
  60. package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.cjs +6 -0
  61. package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.cjs.map +1 -0
  62. package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.mjs +7 -0
  63. package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.mjs.map +1 -0
  64. package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.cjs +6 -0
  65. package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.cjs.map +1 -0
  66. package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.mjs +7 -0
  67. package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.mjs.map +1 -0
  68. package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.cjs +6 -0
  69. package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.cjs.map +1 -0
  70. package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.mjs +7 -0
  71. package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.mjs.map +1 -0
  72. package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.cjs +6 -0
  73. package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.cjs.map +1 -0
  74. package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.mjs +7 -0
  75. package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.mjs.map +1 -0
  76. package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.cjs +6 -0
  77. package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.cjs.map +1 -0
  78. package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.mjs +7 -0
  79. package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.mjs.map +1 -0
  80. package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.cjs +6 -0
  81. package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.cjs.map +1 -0
  82. package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.mjs +7 -0
  83. package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.mjs.map +1 -0
  84. package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.cjs +6 -0
  85. package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.cjs.map +1 -0
  86. package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.mjs +7 -0
  87. package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.mjs.map +1 -0
  88. package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.cjs +6 -0
  89. package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.cjs.map +1 -0
  90. package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.mjs +7 -0
  91. package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.mjs.map +1 -0
  92. package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.cjs +6 -0
  93. package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.cjs.map +1 -0
  94. package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.mjs +7 -0
  95. package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.mjs.map +1 -0
  96. package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.cjs +6 -0
  97. package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.cjs.map +1 -0
  98. package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.mjs +7 -0
  99. package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.mjs.map +1 -0
  100. package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.cjs +7 -0
  101. package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.cjs.map +1 -0
  102. package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.mjs +8 -0
  103. package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.mjs.map +1 -0
  104. package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs +15 -0
  105. package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs.map +1 -0
  106. package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs +16 -0
  107. package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs.map +1 -0
  108. package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs +17 -0
  109. package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs.map +1 -0
  110. package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs +18 -0
  111. package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs.map +1 -0
  112. package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.cjs +6 -0
  113. package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.cjs.map +1 -0
  114. package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.mjs +7 -0
  115. package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.mjs.map +1 -0
  116. package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.cjs +6 -0
  117. package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.cjs.map +1 -0
  118. package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.mjs +7 -0
  119. package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.mjs.map +1 -0
  120. package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.cjs +6 -0
  121. package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.cjs.map +1 -0
  122. package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.mjs +7 -0
  123. package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.mjs.map +1 -0
  124. package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.cjs +6 -0
  125. package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.cjs.map +1 -0
  126. package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.mjs +7 -0
  127. package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.mjs.map +1 -0
  128. package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.cjs +6 -0
  129. package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.cjs.map +1 -0
  130. package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.mjs +7 -0
  131. package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.mjs.map +1 -0
  132. package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.cjs +6 -0
  133. package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.cjs.map +1 -0
  134. package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.mjs +7 -0
  135. package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.mjs.map +1 -0
  136. package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.cjs +6 -0
  137. package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.cjs.map +1 -0
  138. package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.mjs +7 -0
  139. package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.mjs.map +1 -0
  140. package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.cjs +6 -0
  141. package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.cjs.map +1 -0
  142. package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.mjs +7 -0
  143. package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.mjs.map +1 -0
  144. package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.cjs +50 -0
  145. package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.cjs.map +1 -0
  146. package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.mjs +47 -0
  147. package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.mjs.map +1 -0
  148. package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.cjs +36 -0
  149. package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.cjs.map +1 -0
  150. package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.mjs +35 -0
  151. package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.mjs.map +1 -0
  152. package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.cjs +7 -0
  153. package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.cjs.map +1 -0
  154. package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.mjs +8 -0
  155. package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.mjs.map +1 -0
  156. package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.cjs +7 -0
  157. package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.cjs.map +1 -0
  158. package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.mjs +8 -0
  159. package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.mjs.map +1 -0
  160. package/dist/src/schemas/apiContracts.cjs +330 -0
  161. package/dist/src/schemas/apiContracts.cjs.map +1 -0
  162. package/dist/src/schemas/apiContracts.d.cts +53 -0
  163. package/dist/src/schemas/apiContracts.d.cts.map +1 -0
  164. package/dist/src/schemas/apiContracts.d.mts +53 -0
  165. package/dist/src/schemas/apiContracts.d.mts.map +1 -0
  166. package/dist/src/schemas/apiContracts.mjs +327 -0
  167. package/dist/src/schemas/apiContracts.mjs.map +1 -0
  168. package/dist/src/schemas/workflowPi.cjs +77 -0
  169. package/dist/src/schemas/workflowPi.cjs.map +1 -0
  170. package/dist/src/schemas/workflowPi.d.cts +1 -0
  171. package/dist/src/schemas/workflowPi.d.mts +1 -0
  172. package/dist/src/schemas/workflowPi.mjs +74 -0
  173. package/dist/src/schemas/workflowPi.mjs.map +1 -0
  174. package/dist/src/services/backgroundWork/index.cjs +61 -0
  175. package/dist/src/services/backgroundWork/index.cjs.map +1 -0
  176. package/dist/src/services/backgroundWork/index.mjs +61 -0
  177. package/dist/src/services/backgroundWork/index.mjs.map +1 -0
  178. package/dist/src/services/piToolBridge/index.cjs +205 -0
  179. package/dist/src/services/piToolBridge/index.cjs.map +1 -0
  180. package/dist/src/services/piToolBridge/index.mjs +195 -0
  181. package/dist/src/services/piToolBridge/index.mjs.map +1 -0
  182. package/dist/src/services/serverRuntime/index.cjs +387 -0
  183. package/dist/src/services/serverRuntime/index.cjs.map +1 -0
  184. package/dist/src/services/serverRuntime/index.mjs +387 -0
  185. package/dist/src/services/serverRuntime/index.mjs.map +1 -0
  186. package/dist/src/services/webWorkflowCatalog/index.cjs +53 -0
  187. package/dist/src/services/webWorkflowCatalog/index.cjs.map +1 -0
  188. package/dist/src/services/webWorkflowCatalog/index.mjs +52 -0
  189. package/dist/src/services/webWorkflowCatalog/index.mjs.map +1 -0
  190. package/dist/src/services/workflowCatalogChannel/index.cjs +74 -0
  191. package/dist/src/services/workflowCatalogChannel/index.cjs.map +1 -0
  192. package/dist/src/services/workflowCatalogChannel/index.mjs +74 -0
  193. package/dist/src/services/workflowCatalogChannel/index.mjs.map +1 -0
  194. package/dist/src/services/workflowCatalogDeps/index.cjs +25 -0
  195. package/dist/src/services/workflowCatalogDeps/index.cjs.map +1 -0
  196. package/dist/src/services/workflowCatalogDeps/index.mjs +25 -0
  197. package/dist/src/services/workflowCatalogDeps/index.mjs.map +1 -0
  198. package/dist/src/services/workflowExecution/index.cjs +205 -0
  199. package/dist/src/services/workflowExecution/index.cjs.map +1 -0
  200. package/dist/src/services/workflowExecution/index.d.cts +6 -0
  201. package/dist/src/services/workflowExecution/index.d.mts +6 -0
  202. package/dist/src/services/workflowExecution/index.mjs +200 -0
  203. package/dist/src/services/workflowExecution/index.mjs.map +1 -0
  204. package/dist/src/services/workflowFence/index.cjs +170 -0
  205. package/dist/src/services/workflowFence/index.cjs.map +1 -0
  206. package/dist/src/services/workflowFence/index.mjs +166 -0
  207. package/dist/src/services/workflowFence/index.mjs.map +1 -0
  208. package/dist/src/services/workflowHubApi/index.cjs +415 -0
  209. package/dist/src/services/workflowHubApi/index.cjs.map +1 -0
  210. package/dist/src/services/workflowHubApi/index.mjs +411 -0
  211. package/dist/src/services/workflowHubApi/index.mjs.map +1 -0
  212. package/dist/src/services/workflowLaunchCommand/index.cjs +121 -0
  213. package/dist/src/services/workflowLaunchCommand/index.cjs.map +1 -0
  214. package/dist/src/services/workflowLaunchCommand/index.d.cts +52 -0
  215. package/dist/src/services/workflowLaunchCommand/index.d.cts.map +1 -0
  216. package/dist/src/services/workflowLaunchCommand/index.d.mts +52 -0
  217. package/dist/src/services/workflowLaunchCommand/index.d.mts.map +1 -0
  218. package/dist/src/services/workflowLaunchCommand/index.mjs +118 -0
  219. package/dist/src/services/workflowLaunchCommand/index.mjs.map +1 -0
  220. package/dist/src/services/workflowLauncher/index.cjs +181 -0
  221. package/dist/src/services/workflowLauncher/index.cjs.map +1 -0
  222. package/dist/src/services/workflowLauncher/index.mjs +177 -0
  223. package/dist/src/services/workflowLauncher/index.mjs.map +1 -0
  224. package/dist/src/services/workflowNarration/index.cjs +19 -0
  225. package/dist/src/services/workflowNarration/index.cjs.map +1 -0
  226. package/dist/src/services/workflowNarration/index.mjs +19 -0
  227. package/dist/src/services/workflowNarration/index.mjs.map +1 -0
  228. package/dist/src/services/workflowResource/index.cjs +27 -0
  229. package/dist/src/services/workflowResource/index.cjs.map +1 -0
  230. package/dist/src/services/workflowResource/index.mjs +24 -0
  231. package/dist/src/services/workflowResource/index.mjs.map +1 -0
  232. package/dist/src/services/workflowRuns/index.cjs +333 -0
  233. package/dist/src/services/workflowRuns/index.cjs.map +1 -0
  234. package/dist/src/services/workflowRuns/index.mjs +319 -0
  235. package/dist/src/services/workflowRuns/index.mjs.map +1 -0
  236. package/dist/src/services/workflowTerminal/index.cjs +69 -0
  237. package/dist/src/services/workflowTerminal/index.cjs.map +1 -0
  238. package/dist/src/services/workflowTerminal/index.mjs +69 -0
  239. package/dist/src/services/workflowTerminal/index.mjs.map +1 -0
  240. package/dist/src/services/workflowTools/index.cjs +221 -0
  241. package/dist/src/services/workflowTools/index.cjs.map +1 -0
  242. package/dist/src/services/workflowTools/index.mjs +221 -0
  243. package/dist/src/services/workflowTools/index.mjs.map +1 -0
  244. package/dist/src/services/workflowWatcher/index.cjs +78 -0
  245. package/dist/src/services/workflowWatcher/index.cjs.map +1 -0
  246. package/dist/src/services/workflowWatcher/index.mjs +74 -0
  247. package/dist/src/services/workflowWatcher/index.mjs.map +1 -0
  248. package/dist/src/services/workflowsHubChannel/index.cjs +58 -0
  249. package/dist/src/services/workflowsHubChannel/index.cjs.map +1 -0
  250. package/dist/src/services/workflowsHubChannel/index.mjs +58 -0
  251. package/dist/src/services/workflowsHubChannel/index.mjs.map +1 -0
  252. package/dist/src/tui/leader.cjs +84 -0
  253. package/dist/src/tui/leader.cjs.map +1 -0
  254. package/dist/src/tui/leader.mjs +83 -0
  255. package/dist/src/tui/leader.mjs.map +1 -0
  256. package/dist/src/tui/workflow/doomOverlay.cjs +159 -0
  257. package/dist/src/tui/workflow/doomOverlay.cjs.map +1 -0
  258. package/dist/src/tui/workflow/doomOverlay.mjs +157 -0
  259. package/dist/src/tui/workflow/doomOverlay.mjs.map +1 -0
  260. package/dist/src/tui/workflow/overlayText.cjs +83 -0
  261. package/dist/src/tui/workflow/overlayText.cjs.map +1 -0
  262. package/dist/src/tui/workflow/overlayText.mjs +78 -0
  263. package/dist/src/tui/workflow/overlayText.mjs.map +1 -0
  264. package/dist/src/tui/workflow/rendering.cjs +22 -0
  265. package/dist/src/tui/workflow/rendering.cjs.map +1 -0
  266. package/dist/src/tui/workflow/rendering.mjs +20 -0
  267. package/dist/src/tui/workflow/rendering.mjs.map +1 -0
  268. package/dist/src/tui/workflow/workflowCatalog.cjs +336 -0
  269. package/dist/src/tui/workflow/workflowCatalog.cjs.map +1 -0
  270. package/dist/src/tui/workflow/workflowCatalog.mjs +333 -0
  271. package/dist/src/tui/workflow/workflowCatalog.mjs.map +1 -0
  272. package/dist/src/tui/workflow/workflowFinishedMessage.cjs +50 -0
  273. package/dist/src/tui/workflow/workflowFinishedMessage.cjs.map +1 -0
  274. package/dist/src/tui/workflow/workflowFinishedMessage.mjs +47 -0
  275. package/dist/src/tui/workflow/workflowFinishedMessage.mjs.map +1 -0
  276. package/dist/src/tui/workflow/workflowInspector.cjs +276 -0
  277. package/dist/src/tui/workflow/workflowInspector.cjs.map +1 -0
  278. package/dist/src/tui/workflow/workflowInspector.mjs +276 -0
  279. package/dist/src/tui/workflow/workflowInspector.mjs.map +1 -0
  280. package/dist/src/tui/workflow/workflowOverlay.cjs +126 -0
  281. package/dist/src/tui/workflow/workflowOverlay.cjs.map +1 -0
  282. package/dist/src/tui/workflow/workflowOverlay.mjs +125 -0
  283. package/dist/src/tui/workflow/workflowOverlay.mjs.map +1 -0
  284. package/dist/src/tui/workflow/workflowPicker.cjs +138 -0
  285. package/dist/src/tui/workflow/workflowPicker.cjs.map +1 -0
  286. package/dist/src/tui/workflow/workflowPicker.mjs +136 -0
  287. package/dist/src/tui/workflow/workflowPicker.mjs.map +1 -0
  288. package/dist/src/tui/workflow/workflowProgressOverlay.cjs +197 -0
  289. package/dist/src/tui/workflow/workflowProgressOverlay.cjs.map +1 -0
  290. package/dist/src/tui/workflow/workflowProgressOverlay.mjs +192 -0
  291. package/dist/src/tui/workflow/workflowProgressOverlay.mjs.map +1 -0
  292. package/dist/src/tui/workflow/workflowPrompt.cjs +142 -0
  293. package/dist/src/tui/workflow/workflowPrompt.cjs.map +1 -0
  294. package/dist/src/tui/workflow/workflowPrompt.mjs +139 -0
  295. package/dist/src/tui/workflow/workflowPrompt.mjs.map +1 -0
  296. package/dist/src/tui/workflow/workflowRunPanel.cjs +95 -0
  297. package/dist/src/tui/workflow/workflowRunPanel.cjs.map +1 -0
  298. package/dist/src/tui/workflow/workflowRunPanel.mjs +94 -0
  299. package/dist/src/tui/workflow/workflowRunPanel.mjs.map +1 -0
  300. package/dist/src/tui/workflow/workflowStatusRow.cjs +20 -0
  301. package/dist/src/tui/workflow/workflowStatusRow.cjs.map +1 -0
  302. package/dist/src/tui/workflow/workflowStatusRow.mjs +20 -0
  303. package/dist/src/tui/workflow/workflowStatusRow.mjs.map +1 -0
  304. package/dist/src/tui/workflow/workflowStepMessage.cjs +32 -0
  305. package/dist/src/tui/workflow/workflowStepMessage.cjs.map +1 -0
  306. package/dist/src/tui/workflow/workflowStepMessage.mjs +31 -0
  307. package/dist/src/tui/workflow/workflowStepMessage.mjs.map +1 -0
  308. package/dist/src/tui/workflow/workflowToolRender.cjs +491 -0
  309. package/dist/src/tui/workflow/workflowToolRender.cjs.map +1 -0
  310. package/dist/src/tui/workflow/workflowToolRender.mjs +490 -0
  311. package/dist/src/tui/workflow/workflowToolRender.mjs.map +1 -0
  312. package/dist/src/tui/workflowRuntime.cjs +1934 -0
  313. package/dist/src/tui/workflowRuntime.cjs.map +1 -0
  314. package/dist/src/tui/workflowRuntime.d.cts +33 -0
  315. package/dist/src/tui/workflowRuntime.d.cts.map +1 -0
  316. package/dist/src/tui/workflowRuntime.d.mts +33 -0
  317. package/dist/src/tui/workflowRuntime.d.mts.map +1 -0
  318. package/dist/src/tui/workflowRuntime.mjs +1930 -0
  319. package/dist/src/tui/workflowRuntime.mjs.map +1 -0
  320. package/dist/src/types/apiRoutes.cjs +82 -0
  321. package/dist/src/types/apiRoutes.cjs.map +1 -0
  322. package/dist/src/types/apiRoutes.mjs +80 -0
  323. package/dist/src/types/apiRoutes.mjs.map +1 -0
  324. package/dist/src/types/webWorkflowTerminal.cjs +23 -0
  325. package/dist/src/types/webWorkflowTerminal.cjs.map +1 -0
  326. package/dist/src/types/webWorkflowTerminal.mjs +22 -0
  327. package/dist/src/types/webWorkflowTerminal.mjs.map +1 -0
  328. package/dist/src/types/webWorkflows.cjs +8 -0
  329. package/dist/src/types/webWorkflows.cjs.map +1 -0
  330. package/dist/src/types/webWorkflows.mjs +7 -0
  331. package/dist/src/types/webWorkflows.mjs.map +1 -0
  332. package/package.json +8 -8
@@ -0,0 +1,61 @@
1
+ import { DOOM_BACKGROUND_WORK_SERVICE, readDoomBackgroundWorkService } from "@agimon-ai/doompi-core/background-work";
2
+ //#region src/services/backgroundWork/index.ts
3
+ /**
4
+ * Background-work registration for workflow runs.
5
+ *
6
+ * DESIGN PATTERNS:
7
+ * - Hard dependency binding through Cordis injection
8
+ * - Snapshot pattern: the extension pushes the current run set, the provider
9
+ * only reads it
10
+ *
11
+ * CODING STANDARDS:
12
+ * - Named exports only
13
+ * - Explicit return types on exported functions
14
+ *
15
+ * AVOID:
16
+ * - Process-global symbols or dynamic imports for extension communication
17
+ * - Reporting runs owned by another Pi session
18
+ */
19
+ const PROVIDER_NAME = "workflow-mcp";
20
+ /**
21
+ * Register a background-work provider for this session's workflow runs.
22
+ *
23
+ * The runtime pins all announcements to the active Pi session and validates
24
+ * each snapshot before it reaches another extension.
25
+ */
26
+ function registerRunProvider(ctx) {
27
+ let items = [];
28
+ let provider;
29
+ let disposed = false;
30
+ ctx.inject([DOOM_BACKGROUND_WORK_SERVICE], (serviceContext) => {
31
+ if (disposed) return void 0;
32
+ const service = readDoomBackgroundWorkService(serviceContext);
33
+ if (!service) return void 0;
34
+ const registration = service.register({
35
+ provider: PROVIDER_NAME,
36
+ listActiveWork: () => items
37
+ });
38
+ provider = registration;
39
+ return () => {
40
+ registration.dispose();
41
+ if (provider === registration) provider = void 0;
42
+ };
43
+ });
44
+ return {
45
+ update(next) {
46
+ items = next;
47
+ provider?.update();
48
+ },
49
+ dispose() {
50
+ if (disposed) return;
51
+ disposed = true;
52
+ items = [];
53
+ provider?.dispose();
54
+ provider = void 0;
55
+ }
56
+ };
57
+ }
58
+ //#endregion
59
+ export { registerRunProvider };
60
+
61
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/services/backgroundWork/index.ts"],"sourcesContent":["/**\n * Background-work registration for workflow runs.\n *\n * DESIGN PATTERNS:\n * - Hard dependency binding through Cordis injection\n * - Snapshot pattern: the extension pushes the current run set, the provider\n * only reads it\n *\n * CODING STANDARDS:\n * - Named exports only\n * - Explicit return types on exported functions\n *\n * AVOID:\n * - Process-global symbols or dynamic imports for extension communication\n * - Reporting runs owned by another Pi session\n */\n\nimport {\n DOOM_BACKGROUND_WORK_SERVICE,\n type BackgroundWorkProviderHandle,\n readDoomBackgroundWorkService,\n} from '@agimon-ai/doompi-core/background-work';\nimport type { Context } from '@deepseek-ai/cordis';\n\nexport interface RunProviderItem {\n id: string;\n sessionId: string;\n}\n\nexport interface RunProviderHandle {\n /** Replace the reported run set. */\n update(items: RunProviderItem[]): void;\n /** Remove the registration. Safe to call when registration never happened. */\n dispose(): void;\n}\n\nconst PROVIDER_NAME = 'workflow-mcp';\n\n/**\n * Register a background-work provider for this session's workflow runs.\n *\n * The runtime pins all announcements to the active Pi session and validates\n * each snapshot before it reaches another extension.\n */\nexport function registerRunProvider(ctx: Context): RunProviderHandle {\n let items: RunProviderItem[] = [];\n let provider: BackgroundWorkProviderHandle | undefined;\n let disposed = false;\n ctx.inject([DOOM_BACKGROUND_WORK_SERVICE], (serviceContext) => {\n if (disposed) return undefined;\n const service = readDoomBackgroundWorkService(serviceContext);\n if (!service) return undefined;\n const registration = service.register({ provider: PROVIDER_NAME, listActiveWork: () => items });\n provider = registration;\n return () => {\n registration.dispose();\n if (provider === registration) provider = undefined;\n };\n });\n const handle: RunProviderHandle = {\n update(next) {\n items = next;\n provider?.update();\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n items = [];\n provider?.dispose();\n provider = undefined;\n },\n };\n return handle;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoCA,MAAM,gBAAgB;;;;;;;AAQtB,SAAgB,oBAAoB,KAAiC;CACnE,IAAI,QAA2B,CAAC;CAChC,IAAI;CACJ,IAAI,WAAW;CACf,IAAI,OAAO,CAAC,4BAA4B,IAAI,mBAAmB;EAC7D,IAAI,UAAU,OAAO,KAAA;EACrB,MAAM,UAAU,8BAA8B,cAAc;EAC5D,IAAI,CAAC,SAAS,OAAO,KAAA;EACrB,MAAM,eAAe,QAAQ,SAAS;GAAE,UAAU;GAAe,sBAAsB;EAAM,CAAC;EAC9F,WAAW;EACX,aAAa;GACX,aAAa,QAAQ;GACrB,IAAI,aAAa,cAAc,WAAW,KAAA;EAC5C;CACF,CAAC;CAcD,OAAO;EAZL,OAAO,MAAM;GACX,QAAQ;GACR,UAAU,OAAO;EACnB;EACA,UAAU;GACR,IAAI,UAAU;GACd,WAAW;GACX,QAAQ,CAAC;GACT,UAAU,QAAQ;GAClB,WAAW,KAAA;EACb;CAEU;AACd"}
@@ -0,0 +1,205 @@
1
+ //#region src/services/piToolBridge/index.ts
2
+ /**
3
+ * Environment variable stamped onto every run launched from a Pi session.
4
+ *
5
+ * `RunWorkflowService` forwards `env` to the inner CLI invocation across the
6
+ * `launch-command` delegation boundary and persists it on the run record, so
7
+ * this survives backgrounding and identifies the launching session afterwards.
8
+ */
9
+ const PI_SESSION_ENV = "PI_SESSION_ID";
10
+ /** Operator override for the per-session launch ceiling. */
11
+ const MAX_CONCURRENT_ENV = "WORKFLOW_MCP_MAX_CONCURRENT";
12
+ const DEFAULT_MAX_CONCURRENT = 5;
13
+ /** Resolve the per-session launch ceiling from the environment. */
14
+ function resolveMaxConcurrent(env = process.env) {
15
+ const parsed = Number(env[MAX_CONCURRENT_ENV]);
16
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : DEFAULT_MAX_CONCURRENT;
17
+ }
18
+ /**
19
+ * True when this session launched the run.
20
+ *
21
+ * Fails closed on a missing session id: an unstamped record (a CLI launch) and
22
+ * a call arriving before the session id is known both match nothing, so no run
23
+ * ever leaks across sessions through an undefined-equals-undefined comparison.
24
+ */
25
+ function isSessionRun(record, sessionId) {
26
+ return sessionId !== void 0 && record.env?.["PI_SESSION_ID"] === sessionId;
27
+ }
28
+ /** Runs launched by one Pi session that are still running. */
29
+ function runsForSession(records, sessionId) {
30
+ return records.filter((record) => isSessionRun(record, sessionId) && record.stage === "running");
31
+ }
32
+ /**
33
+ * What the caller is told when the registry, not the launcher, acknowledged a
34
+ * launch.
35
+ *
36
+ * Leads with the run key because it is the handle every other workflow action
37
+ * takes, and it is no longer available any other way: the launcher's own output
38
+ * is not waited for, so nothing else in this result carries it.
39
+ */
40
+ function launchedRunSummary(record) {
41
+ return [
42
+ `Started ${record.displayName} in workspace ${record.workspace}.`,
43
+ `Run key: ${record.runKey}`,
44
+ "The run is registered and going. This call returned at that point rather than waiting for the launcher process to exit."
45
+ ].join("\n");
46
+ }
47
+ /**
48
+ * What the caller is told when the launch was handed off but no run has
49
+ * registered inside the acknowledgement budget.
50
+ *
51
+ * Deliberately not an error: the launcher is slow rather than broken often
52
+ * enough that failing here would strand runs that go on to start normally.
53
+ * There is no run key to offer yet, so it points at the surfaces that do not
54
+ * need one.
55
+ */
56
+ function launchHandoffSummary(workflowPath) {
57
+ return [
58
+ `Launch handed off for ${workflowPath}, but no run has registered yet.`,
59
+ "Nothing was cancelled: the launcher is still starting, and a run that registers later still reports back here when it finishes.",
60
+ "Do not launch it again. Ask the user to check the active workflow list if they need to see it sooner."
61
+ ].join("\n");
62
+ }
63
+ /**
64
+ * Escape sequences a terminal consumes rather than prints.
65
+ *
66
+ * Built from a string with the rule silenced, the way `doom-runner`'s own
67
+ * scrubber does it, because matching the escape byte is the entire job. Not
68
+ * imported from there: that package's published build is a stale artifact
69
+ * missing the export, and a launch notice should not need another package's
70
+ * build to be current.
71
+ */
72
+ const ESCAPE_SEQUENCE = new RegExp([
73
+ "\\u001B\\[[0-9;?]*[ -/]*[@-~]",
74
+ "\\u001B\\][^\\u0007\\u001B]*(?:\\u0007|\\u001B\\\\)",
75
+ "\\u001B[@-Z\\\\-_]"
76
+ ].join("|"), "g");
77
+ /** Rows made only of box-drawing: separators that carry nothing once trimmed. */
78
+ const RULE_ROW = /^[\s─-╿]*$/u;
79
+ const NOTICE_LINE_LIMIT = 3;
80
+ /**
81
+ * Widest a notice row may be before it is clipped.
82
+ *
83
+ * A three-line cap does not bound a toast on its own: the engine announces its
84
+ * delegation by echoing the whole shell command, temp script path included, and
85
+ * one line of that wraps across three rows of a narrow terminal and shoves the
86
+ * transcript around. Clipped at a width every terminal can hold instead.
87
+ */
88
+ const NOTICE_WIDTH_LIMIT = 100;
89
+ /**
90
+ * Cut a tool result down to something a toast can hold.
91
+ *
92
+ * The launch result used to reach `ui.notify` whole, and for a workflow that
93
+ * executes in this process that result is the engine's entire console log:
94
+ * banner, run directory, job tree, rules, colour. Pi rendered every line of it
95
+ * over the transcript, which reads as a broken screen rather than as output.
96
+ * Escape sequences go first: the log carries colour the notification would
97
+ * render as literal text, and a stray clear or cursor-move would do to the
98
+ * screen exactly what this function exists to prevent.
99
+ */
100
+ function launchNotice(text, limit = NOTICE_LINE_LIMIT) {
101
+ const lines = text.replace(ESCAPE_SEQUENCE, "").split("\n").map((line) => line.trimEnd()).filter((line) => line.trim().length > 0 && !RULE_ROW.test(line)).map((line) => line.length > NOTICE_WIDTH_LIMIT ? `${line.slice(0, 99)}…` : line);
102
+ if (lines.length === 0) return "Workflow started.";
103
+ if (lines.length <= limit) return lines.join("\n");
104
+ return [...lines.slice(0, limit), `… ${lines.length - limit} more lines, in the run's own output.`].join("\n");
105
+ }
106
+ /** Flatten MCP tool content to text for Pi. */
107
+ function toolResultText(result) {
108
+ return result.content.map((part) => part.type === "text" ? part.text : "").filter(Boolean).join("\n").trim();
109
+ }
110
+ /**
111
+ * Convert an MCP tool result into a Pi tool result.
112
+ *
113
+ * Pi signals tool failure by throwing: the agent loop catches it and builds the
114
+ * error result. So an `isError` MCP result becomes a thrown error rather than a
115
+ * successful result carrying a flag Pi would ignore.
116
+ */
117
+ function toAgentToolResult(tool, result, errorOptions = []) {
118
+ const text = toolResultText(result) || "No output.";
119
+ if (result.isError) throw new Error(withOptions(text, errorOptions));
120
+ return {
121
+ content: [{
122
+ type: "text",
123
+ text
124
+ }],
125
+ details: { tool }
126
+ };
127
+ }
128
+ /**
129
+ * Attach a short menu of next steps to a problem.
130
+ *
131
+ * An error with no route forward is where an agent invents one: retrying a
132
+ * capacity limit, relaunching a run that should be recovered, or silently
133
+ * giving up on work the user is waiting for. Naming two or three real options
134
+ * turns an error into a decision, and the decision belongs to the user.
135
+ */
136
+ function withOptions(problem, options) {
137
+ if (options.length === 0) return problem;
138
+ return [
139
+ problem,
140
+ "",
141
+ "Options, put these to the user rather than picking one yourself:",
142
+ ...options.map(bullet)
143
+ ].join("\n");
144
+ }
145
+ function bullet(option) {
146
+ return `- ${option}`;
147
+ }
148
+ /** The job and step a run died on, preferring the progress log to the record. */
149
+ function failurePosition(record, jobs) {
150
+ const failedJob = jobs.find((job) => job.status === "failed");
151
+ const failedStep = failedJob?.steps.find((step) => step.status === "failed");
152
+ return {
153
+ job: failedJob?.name ?? record.failedJob,
154
+ step: failedStep?.name,
155
+ reason: failedStep?.reason ?? failedJob?.reason
156
+ };
157
+ }
158
+ /**
159
+ * Describe a finished run for the agent that launched it.
160
+ *
161
+ * Carries the job identifiers back so a dispatching agent can match the run to
162
+ * the work item it launched it for without another lookup. When the run failed,
163
+ * carries the failing step and a set of options too: the agent is being told
164
+ * about this out of band, with no user question in flight, so without them it
165
+ * has to guess whether to recover, relaunch, or report.
166
+ */
167
+ function finishedRunSummary(record, jobs = []) {
168
+ const outcome = record.stage === "completed" ? "completed" : `ended in ${record.stage}`;
169
+ const failure = failurePosition(record, jobs);
170
+ const lines = [
171
+ `Workflow run ${record.runKey} in workspace ${record.workspace} ${outcome}.`,
172
+ record.workflowId ? `Workflow: ${record.workflowId}` : void 0,
173
+ failure.job ? `Failed job: ${failure.job}${failure.step ? ` (step: ${failure.step})` : ""}` : void 0,
174
+ record.errorMessage ? `Error: ${record.errorMessage}` : void 0,
175
+ failure.reason && failure.reason !== record.errorMessage ? `Step reported: ${failure.reason}` : void 0
176
+ ];
177
+ const jobId = record.env?.AGIFLOW_JOB_ID;
178
+ if (jobId) lines.push(`Agiflow job: ${record.env?.AGIFLOW_JOB_KIND ?? "unknown"} ${jobId}`);
179
+ const summary = lines.filter((line) => Boolean(line)).join("\n");
180
+ if (record.stage === "completed") return summary;
181
+ if (record.outcome === "interrupted") return withOptions(summary, [`workflow_run {"action":"recover","runKey":${JSON.stringify(record.runKey)}}: pick it up where it stopped.`, "Leave it stopped and move on."]);
182
+ const diagnosticText = [record.errorMessage, failure.reason].filter(Boolean).join("\n");
183
+ if (diagnosticText.includes("JOB_ALREADY_CLAIMED")) return withOptions(summary, ["Report contention: another worker owns this job. Do not unlock, release, or retry the claim automatically."]);
184
+ if (diagnosticText.includes("WORKFLOW_NOT_OWNED") || /release failed/i.test(diagnosticText)) return withOptions(summary, ["Inspect the current workflow ownership and ask the user before any release or unlock. Never force another worker’s lock."]);
185
+ if (/running workflow not found/i.test(diagnosticText)) return withOptions(summary, [`workflow_run {"action":"status","runKey":${JSON.stringify(record.runKey)}}: re-check current state before retrying.`, "Report the recorded terminal state when no running owner remains."]);
186
+ return withOptions(summary, [
187
+ `workflow_run {"action":"tail","runKey":${JSON.stringify(record.runKey)}}: read the run's own output first, when the error above does not explain the failure.`,
188
+ `workflow_run {"action":"recover","runKey":${JSON.stringify(record.runKey)}}: resume from the failed job, keeping the work already done. Fits a transient or external cause.`,
189
+ "Report the failure and stop, when it needs a code change or a decision you cannot make."
190
+ ]);
191
+ }
192
+ //#endregion
193
+ exports.PI_SESSION_ENV = PI_SESSION_ENV;
194
+ exports.finishedRunSummary = finishedRunSummary;
195
+ exports.isSessionRun = isSessionRun;
196
+ exports.launchHandoffSummary = launchHandoffSummary;
197
+ exports.launchNotice = launchNotice;
198
+ exports.launchedRunSummary = launchedRunSummary;
199
+ exports.resolveMaxConcurrent = resolveMaxConcurrent;
200
+ exports.runsForSession = runsForSession;
201
+ exports.toAgentToolResult = toAgentToolResult;
202
+ exports.toolResultText = toolResultText;
203
+ exports.withOptions = withOptions;
204
+
205
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../../../src/services/piToolBridge/index.ts"],"sourcesContent":["/**\n * Pure bridging logic between MCP tool results and the Pi tool surface.\n *\n * DESIGN PATTERNS:\n * - Adapter pattern: MCP `CallToolResult` is converted to Pi's result shape\n * - Pure module: no service or tool-class imports, so this is unit-testable\n * without constructing the workflow execution stack\n *\n * CODING STANDARDS:\n * - Named exports only\n * - Explicit return types on exported functions\n *\n * AVOID:\n * - Importing tool classes or services here (that belongs in `piTools.ts`)\n * - Returning an error flag Pi does not read; Pi tools signal failure by throwing\n */\n\nimport type { WorkflowProgressJob, WorkflowRunRecord } from '@agimon-ai/workflow-mcp';\nimport type { AgentToolResult } from '@earendil-works/pi-coding-agent';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\n\n/**\n * Environment variable stamped onto every run launched from a Pi session.\n *\n * `RunWorkflowService` forwards `env` to the inner CLI invocation across the\n * `launch-command` delegation boundary and persists it on the run record, so\n * this survives backgrounding and identifies the launching session afterwards.\n */\nexport const PI_SESSION_ENV = 'PI_SESSION_ID';\n\n/** Operator override for the per-session launch ceiling. */\nconst MAX_CONCURRENT_ENV = 'WORKFLOW_MCP_MAX_CONCURRENT';\nconst DEFAULT_MAX_CONCURRENT = 5;\n\nexport interface WorkflowToolDetails {\n tool: string;\n}\n\n/** Resolve the per-session launch ceiling from the environment. */\nexport function resolveMaxConcurrent(env: NodeJS.ProcessEnv = process.env): number {\n const parsed = Number(env[MAX_CONCURRENT_ENV]);\n return Number.isInteger(parsed) && parsed > 0 ? parsed : DEFAULT_MAX_CONCURRENT;\n}\n\n/**\n * True when this session launched the run.\n *\n * Fails closed on a missing session id: an unstamped record (a CLI launch) and\n * a call arriving before the session id is known both match nothing, so no run\n * ever leaks across sessions through an undefined-equals-undefined comparison.\n */\nexport function isSessionRun(record: WorkflowRunRecord, sessionId: string | undefined): boolean {\n return sessionId !== undefined && record.env?.[PI_SESSION_ENV] === sessionId;\n}\n\n/** Runs launched by one Pi session that are still running. */\nexport function runsForSession(records: WorkflowRunRecord[], sessionId: string): WorkflowRunRecord[] {\n return records.filter((record) => isSessionRun(record, sessionId) && record.stage === 'running');\n}\n\n/**\n * What the caller is told when the registry, not the launcher, acknowledged a\n * launch.\n *\n * Leads with the run key because it is the handle every other workflow action\n * takes, and it is no longer available any other way: the launcher's own output\n * is not waited for, so nothing else in this result carries it.\n */\nexport function launchedRunSummary(record: WorkflowRunRecord): string {\n return [\n `Started ${record.displayName} in workspace ${record.workspace}.`,\n `Run key: ${record.runKey}`,\n 'The run is registered and going. This call returned at that point rather than waiting for the launcher process to exit.',\n ].join('\\n');\n}\n\n/**\n * What the caller is told when the launch was handed off but no run has\n * registered inside the acknowledgement budget.\n *\n * Deliberately not an error: the launcher is slow rather than broken often\n * enough that failing here would strand runs that go on to start normally.\n * There is no run key to offer yet, so it points at the surfaces that do not\n * need one.\n */\nexport function launchHandoffSummary(workflowPath: string): string {\n return [\n `Launch handed off for ${workflowPath}, but no run has registered yet.`,\n 'Nothing was cancelled: the launcher is still starting, and a run that registers later still reports back here when it finishes.',\n 'Do not launch it again. Ask the user to check the active workflow list if they need to see it sooner.',\n ].join('\\n');\n}\n\n/**\n * Escape sequences a terminal consumes rather than prints.\n *\n * Built from a string with the rule silenced, the way `doom-runner`'s own\n * scrubber does it, because matching the escape byte is the entire job. Not\n * imported from there: that package's published build is a stale artifact\n * missing the export, and a launch notice should not need another package's\n * build to be current.\n */\n// oxlint-disable-next-line no-control-regex -- matching terminal control bytes is the point\nconst ESCAPE_SEQUENCE = new RegExp(\n ['\\\\u001B\\\\[[0-9;?]*[ -/]*[@-~]', '\\\\u001B\\\\][^\\\\u0007\\\\u001B]*(?:\\\\u0007|\\\\u001B\\\\\\\\)', '\\\\u001B[@-Z\\\\\\\\-_]'].join(\n '|',\n ),\n 'g',\n);\n\n/** Rows made only of box-drawing: separators that carry nothing once trimmed. */\nconst RULE_ROW = /^[\\s─-╿]*$/u;\nconst NOTICE_LINE_LIMIT = 3;\n/**\n * Widest a notice row may be before it is clipped.\n *\n * A three-line cap does not bound a toast on its own: the engine announces its\n * delegation by echoing the whole shell command, temp script path included, and\n * one line of that wraps across three rows of a narrow terminal and shoves the\n * transcript around. Clipped at a width every terminal can hold instead.\n */\nconst NOTICE_WIDTH_LIMIT = 100;\n\n/**\n * Cut a tool result down to something a toast can hold.\n *\n * The launch result used to reach `ui.notify` whole, and for a workflow that\n * executes in this process that result is the engine's entire console log:\n * banner, run directory, job tree, rules, colour. Pi rendered every line of it\n * over the transcript, which reads as a broken screen rather than as output.\n * Escape sequences go first: the log carries colour the notification would\n * render as literal text, and a stray clear or cursor-move would do to the\n * screen exactly what this function exists to prevent.\n */\nexport function launchNotice(text: string, limit: number = NOTICE_LINE_LIMIT): string {\n const lines = text\n .replace(ESCAPE_SEQUENCE, '')\n .split('\\n')\n .map((line) => line.trimEnd())\n .filter((line) => line.trim().length > 0 && !RULE_ROW.test(line))\n .map((line) => (line.length > NOTICE_WIDTH_LIMIT ? `${line.slice(0, NOTICE_WIDTH_LIMIT - 1)}…` : line));\n if (lines.length === 0) return 'Workflow started.';\n if (lines.length <= limit) return lines.join('\\n');\n return [...lines.slice(0, limit), `… ${lines.length - limit} more lines, in the run's own output.`].join('\\n');\n}\n\n/** Flatten MCP tool content to text for Pi. */\nexport function toolResultText(result: CallToolResult): string {\n return result.content\n .map((part) => (part.type === 'text' ? part.text : ''))\n .filter(Boolean)\n .join('\\n')\n .trim();\n}\n\n/**\n * Convert an MCP tool result into a Pi tool result.\n *\n * Pi signals tool failure by throwing: the agent loop catches it and builds the\n * error result. So an `isError` MCP result becomes a thrown error rather than a\n * successful result carrying a flag Pi would ignore.\n */\nexport function toAgentToolResult(\n tool: string,\n result: CallToolResult,\n errorOptions: string[] = [],\n): AgentToolResult<WorkflowToolDetails> {\n const text = toolResultText(result) || 'No output.';\n if (result.isError) throw new Error(withOptions(text, errorOptions));\n return { content: [{ type: 'text', text }], details: { tool } };\n}\n\n/**\n * Attach a short menu of next steps to a problem.\n *\n * An error with no route forward is where an agent invents one: retrying a\n * capacity limit, relaunching a run that should be recovered, or silently\n * giving up on work the user is waiting for. Naming two or three real options\n * turns an error into a decision, and the decision belongs to the user.\n */\nexport function withOptions(problem: string, options: string[]): string {\n if (options.length === 0) return problem;\n return [problem, '', 'Options, put these to the user rather than picking one yourself:', ...options.map(bullet)].join(\n '\\n',\n );\n}\n\nfunction bullet(option: string): string {\n return `- ${option}`;\n}\n\n/** The job and step a run died on, preferring the progress log to the record. */\nfunction failurePosition(\n record: WorkflowRunRecord,\n jobs: WorkflowProgressJob[],\n): { job?: string; step?: string; reason?: string } {\n // The progress log knows which step was in flight; the record only names the\n // job. Falling back keeps this working for runs that predate the log.\n const failedJob = jobs.find((job) => job.status === 'failed');\n const failedStep = failedJob?.steps.find((step) => step.status === 'failed');\n return {\n job: failedJob?.name ?? record.failedJob,\n step: failedStep?.name,\n reason: failedStep?.reason ?? failedJob?.reason,\n };\n}\n\n/**\n * Describe a finished run for the agent that launched it.\n *\n * Carries the job identifiers back so a dispatching agent can match the run to\n * the work item it launched it for without another lookup. When the run failed,\n * carries the failing step and a set of options too: the agent is being told\n * about this out of band, with no user question in flight, so without them it\n * has to guess whether to recover, relaunch, or report.\n */\nexport function finishedRunSummary(record: WorkflowRunRecord, jobs: WorkflowProgressJob[] = []): string {\n const outcome = record.stage === 'completed' ? 'completed' : `ended in ${record.stage}`;\n const failure = failurePosition(record, jobs);\n const lines: Array<string | undefined> = [\n `Workflow run ${record.runKey} in workspace ${record.workspace} ${outcome}.`,\n record.workflowId ? `Workflow: ${record.workflowId}` : undefined,\n failure.job ? `Failed job: ${failure.job}${failure.step ? ` (step: ${failure.step})` : ''}` : undefined,\n record.errorMessage ? `Error: ${record.errorMessage}` : undefined,\n failure.reason && failure.reason !== record.errorMessage ? `Step reported: ${failure.reason}` : undefined,\n ];\n const jobId = record.env?.AGIFLOW_JOB_ID;\n if (jobId) lines.push(`Agiflow job: ${record.env?.AGIFLOW_JOB_KIND ?? 'unknown'} ${jobId}`);\n\n const summary = lines.filter((line): line is string => Boolean(line)).join('\\n');\n if (record.stage === 'completed') return summary;\n\n // A run the user stopped is not a defect, so it gets no diagnosis step: the\n // question is only whether to pick it back up.\n const stopped = record.outcome === 'interrupted';\n if (stopped) {\n return withOptions(summary, [\n `workflow_run {\"action\":\"recover\",\"runKey\":${JSON.stringify(record.runKey)}}: pick it up where it stopped.`,\n 'Leave it stopped and move on.',\n ]);\n }\n\n const diagnosticText = [record.errorMessage, failure.reason].filter(Boolean).join('\\n');\n if (diagnosticText.includes('JOB_ALREADY_CLAIMED')) {\n return withOptions(summary, [\n 'Report contention: another worker owns this job. Do not unlock, release, or retry the claim automatically.',\n ]);\n }\n if (diagnosticText.includes('WORKFLOW_NOT_OWNED') || /release failed/i.test(diagnosticText)) {\n return withOptions(summary, [\n 'Inspect the current workflow ownership and ask the user before any release or unlock. Never force another worker’s lock.',\n ]);\n }\n if (/running workflow not found/i.test(diagnosticText)) {\n return withOptions(summary, [\n `workflow_run {\"action\":\"status\",\"runKey\":${JSON.stringify(record.runKey)}}: re-check current state before retrying.`,\n 'Report the recorded terminal state when no running owner remains.',\n ]);\n }\n\n return withOptions(summary, [\n `workflow_run {\"action\":\"tail\",\"runKey\":${JSON.stringify(record.runKey)}}: read the run's own output first, when the error above does not explain the failure.`,\n `workflow_run {\"action\":\"recover\",\"runKey\":${JSON.stringify(record.runKey)}}: resume from the failed job, keeping the work already done. Fits a transient or external cause.`,\n 'Report the failure and stop, when it needs a code change or a decision you cannot make.',\n ]);\n}\n"],"mappings":"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"}
@@ -0,0 +1,195 @@
1
+ //#region src/services/piToolBridge/index.ts
2
+ /**
3
+ * Environment variable stamped onto every run launched from a Pi session.
4
+ *
5
+ * `RunWorkflowService` forwards `env` to the inner CLI invocation across the
6
+ * `launch-command` delegation boundary and persists it on the run record, so
7
+ * this survives backgrounding and identifies the launching session afterwards.
8
+ */
9
+ const PI_SESSION_ENV = "PI_SESSION_ID";
10
+ /** Operator override for the per-session launch ceiling. */
11
+ const MAX_CONCURRENT_ENV = "WORKFLOW_MCP_MAX_CONCURRENT";
12
+ const DEFAULT_MAX_CONCURRENT = 5;
13
+ /** Resolve the per-session launch ceiling from the environment. */
14
+ function resolveMaxConcurrent(env = process.env) {
15
+ const parsed = Number(env[MAX_CONCURRENT_ENV]);
16
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : DEFAULT_MAX_CONCURRENT;
17
+ }
18
+ /**
19
+ * True when this session launched the run.
20
+ *
21
+ * Fails closed on a missing session id: an unstamped record (a CLI launch) and
22
+ * a call arriving before the session id is known both match nothing, so no run
23
+ * ever leaks across sessions through an undefined-equals-undefined comparison.
24
+ */
25
+ function isSessionRun(record, sessionId) {
26
+ return sessionId !== void 0 && record.env?.["PI_SESSION_ID"] === sessionId;
27
+ }
28
+ /** Runs launched by one Pi session that are still running. */
29
+ function runsForSession(records, sessionId) {
30
+ return records.filter((record) => isSessionRun(record, sessionId) && record.stage === "running");
31
+ }
32
+ /**
33
+ * What the caller is told when the registry, not the launcher, acknowledged a
34
+ * launch.
35
+ *
36
+ * Leads with the run key because it is the handle every other workflow action
37
+ * takes, and it is no longer available any other way: the launcher's own output
38
+ * is not waited for, so nothing else in this result carries it.
39
+ */
40
+ function launchedRunSummary(record) {
41
+ return [
42
+ `Started ${record.displayName} in workspace ${record.workspace}.`,
43
+ `Run key: ${record.runKey}`,
44
+ "The run is registered and going. This call returned at that point rather than waiting for the launcher process to exit."
45
+ ].join("\n");
46
+ }
47
+ /**
48
+ * What the caller is told when the launch was handed off but no run has
49
+ * registered inside the acknowledgement budget.
50
+ *
51
+ * Deliberately not an error: the launcher is slow rather than broken often
52
+ * enough that failing here would strand runs that go on to start normally.
53
+ * There is no run key to offer yet, so it points at the surfaces that do not
54
+ * need one.
55
+ */
56
+ function launchHandoffSummary(workflowPath) {
57
+ return [
58
+ `Launch handed off for ${workflowPath}, but no run has registered yet.`,
59
+ "Nothing was cancelled: the launcher is still starting, and a run that registers later still reports back here when it finishes.",
60
+ "Do not launch it again. Ask the user to check the active workflow list if they need to see it sooner."
61
+ ].join("\n");
62
+ }
63
+ /**
64
+ * Escape sequences a terminal consumes rather than prints.
65
+ *
66
+ * Built from a string with the rule silenced, the way `doom-runner`'s own
67
+ * scrubber does it, because matching the escape byte is the entire job. Not
68
+ * imported from there: that package's published build is a stale artifact
69
+ * missing the export, and a launch notice should not need another package's
70
+ * build to be current.
71
+ */
72
+ const ESCAPE_SEQUENCE = new RegExp([
73
+ "\\u001B\\[[0-9;?]*[ -/]*[@-~]",
74
+ "\\u001B\\][^\\u0007\\u001B]*(?:\\u0007|\\u001B\\\\)",
75
+ "\\u001B[@-Z\\\\-_]"
76
+ ].join("|"), "g");
77
+ /** Rows made only of box-drawing: separators that carry nothing once trimmed. */
78
+ const RULE_ROW = /^[\s─-╿]*$/u;
79
+ const NOTICE_LINE_LIMIT = 3;
80
+ /**
81
+ * Widest a notice row may be before it is clipped.
82
+ *
83
+ * A three-line cap does not bound a toast on its own: the engine announces its
84
+ * delegation by echoing the whole shell command, temp script path included, and
85
+ * one line of that wraps across three rows of a narrow terminal and shoves the
86
+ * transcript around. Clipped at a width every terminal can hold instead.
87
+ */
88
+ const NOTICE_WIDTH_LIMIT = 100;
89
+ /**
90
+ * Cut a tool result down to something a toast can hold.
91
+ *
92
+ * The launch result used to reach `ui.notify` whole, and for a workflow that
93
+ * executes in this process that result is the engine's entire console log:
94
+ * banner, run directory, job tree, rules, colour. Pi rendered every line of it
95
+ * over the transcript, which reads as a broken screen rather than as output.
96
+ * Escape sequences go first: the log carries colour the notification would
97
+ * render as literal text, and a stray clear or cursor-move would do to the
98
+ * screen exactly what this function exists to prevent.
99
+ */
100
+ function launchNotice(text, limit = NOTICE_LINE_LIMIT) {
101
+ const lines = text.replace(ESCAPE_SEQUENCE, "").split("\n").map((line) => line.trimEnd()).filter((line) => line.trim().length > 0 && !RULE_ROW.test(line)).map((line) => line.length > NOTICE_WIDTH_LIMIT ? `${line.slice(0, 99)}…` : line);
102
+ if (lines.length === 0) return "Workflow started.";
103
+ if (lines.length <= limit) return lines.join("\n");
104
+ return [...lines.slice(0, limit), `… ${lines.length - limit} more lines, in the run's own output.`].join("\n");
105
+ }
106
+ /** Flatten MCP tool content to text for Pi. */
107
+ function toolResultText(result) {
108
+ return result.content.map((part) => part.type === "text" ? part.text : "").filter(Boolean).join("\n").trim();
109
+ }
110
+ /**
111
+ * Convert an MCP tool result into a Pi tool result.
112
+ *
113
+ * Pi signals tool failure by throwing: the agent loop catches it and builds the
114
+ * error result. So an `isError` MCP result becomes a thrown error rather than a
115
+ * successful result carrying a flag Pi would ignore.
116
+ */
117
+ function toAgentToolResult(tool, result, errorOptions = []) {
118
+ const text = toolResultText(result) || "No output.";
119
+ if (result.isError) throw new Error(withOptions(text, errorOptions));
120
+ return {
121
+ content: [{
122
+ type: "text",
123
+ text
124
+ }],
125
+ details: { tool }
126
+ };
127
+ }
128
+ /**
129
+ * Attach a short menu of next steps to a problem.
130
+ *
131
+ * An error with no route forward is where an agent invents one: retrying a
132
+ * capacity limit, relaunching a run that should be recovered, or silently
133
+ * giving up on work the user is waiting for. Naming two or three real options
134
+ * turns an error into a decision, and the decision belongs to the user.
135
+ */
136
+ function withOptions(problem, options) {
137
+ if (options.length === 0) return problem;
138
+ return [
139
+ problem,
140
+ "",
141
+ "Options, put these to the user rather than picking one yourself:",
142
+ ...options.map(bullet)
143
+ ].join("\n");
144
+ }
145
+ function bullet(option) {
146
+ return `- ${option}`;
147
+ }
148
+ /** The job and step a run died on, preferring the progress log to the record. */
149
+ function failurePosition(record, jobs) {
150
+ const failedJob = jobs.find((job) => job.status === "failed");
151
+ const failedStep = failedJob?.steps.find((step) => step.status === "failed");
152
+ return {
153
+ job: failedJob?.name ?? record.failedJob,
154
+ step: failedStep?.name,
155
+ reason: failedStep?.reason ?? failedJob?.reason
156
+ };
157
+ }
158
+ /**
159
+ * Describe a finished run for the agent that launched it.
160
+ *
161
+ * Carries the job identifiers back so a dispatching agent can match the run to
162
+ * the work item it launched it for without another lookup. When the run failed,
163
+ * carries the failing step and a set of options too: the agent is being told
164
+ * about this out of band, with no user question in flight, so without them it
165
+ * has to guess whether to recover, relaunch, or report.
166
+ */
167
+ function finishedRunSummary(record, jobs = []) {
168
+ const outcome = record.stage === "completed" ? "completed" : `ended in ${record.stage}`;
169
+ const failure = failurePosition(record, jobs);
170
+ const lines = [
171
+ `Workflow run ${record.runKey} in workspace ${record.workspace} ${outcome}.`,
172
+ record.workflowId ? `Workflow: ${record.workflowId}` : void 0,
173
+ failure.job ? `Failed job: ${failure.job}${failure.step ? ` (step: ${failure.step})` : ""}` : void 0,
174
+ record.errorMessage ? `Error: ${record.errorMessage}` : void 0,
175
+ failure.reason && failure.reason !== record.errorMessage ? `Step reported: ${failure.reason}` : void 0
176
+ ];
177
+ const jobId = record.env?.AGIFLOW_JOB_ID;
178
+ if (jobId) lines.push(`Agiflow job: ${record.env?.AGIFLOW_JOB_KIND ?? "unknown"} ${jobId}`);
179
+ const summary = lines.filter((line) => Boolean(line)).join("\n");
180
+ if (record.stage === "completed") return summary;
181
+ if (record.outcome === "interrupted") return withOptions(summary, [`workflow_run {"action":"recover","runKey":${JSON.stringify(record.runKey)}}: pick it up where it stopped.`, "Leave it stopped and move on."]);
182
+ const diagnosticText = [record.errorMessage, failure.reason].filter(Boolean).join("\n");
183
+ if (diagnosticText.includes("JOB_ALREADY_CLAIMED")) return withOptions(summary, ["Report contention: another worker owns this job. Do not unlock, release, or retry the claim automatically."]);
184
+ if (diagnosticText.includes("WORKFLOW_NOT_OWNED") || /release failed/i.test(diagnosticText)) return withOptions(summary, ["Inspect the current workflow ownership and ask the user before any release or unlock. Never force another worker’s lock."]);
185
+ if (/running workflow not found/i.test(diagnosticText)) return withOptions(summary, [`workflow_run {"action":"status","runKey":${JSON.stringify(record.runKey)}}: re-check current state before retrying.`, "Report the recorded terminal state when no running owner remains."]);
186
+ return withOptions(summary, [
187
+ `workflow_run {"action":"tail","runKey":${JSON.stringify(record.runKey)}}: read the run's own output first, when the error above does not explain the failure.`,
188
+ `workflow_run {"action":"recover","runKey":${JSON.stringify(record.runKey)}}: resume from the failed job, keeping the work already done. Fits a transient or external cause.`,
189
+ "Report the failure and stop, when it needs a code change or a decision you cannot make."
190
+ ]);
191
+ }
192
+ //#endregion
193
+ export { PI_SESSION_ENV, finishedRunSummary, isSessionRun, launchHandoffSummary, launchNotice, launchedRunSummary, resolveMaxConcurrent, runsForSession, toAgentToolResult, toolResultText, withOptions };
194
+
195
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/services/piToolBridge/index.ts"],"sourcesContent":["/**\n * Pure bridging logic between MCP tool results and the Pi tool surface.\n *\n * DESIGN PATTERNS:\n * - Adapter pattern: MCP `CallToolResult` is converted to Pi's result shape\n * - Pure module: no service or tool-class imports, so this is unit-testable\n * without constructing the workflow execution stack\n *\n * CODING STANDARDS:\n * - Named exports only\n * - Explicit return types on exported functions\n *\n * AVOID:\n * - Importing tool classes or services here (that belongs in `piTools.ts`)\n * - Returning an error flag Pi does not read; Pi tools signal failure by throwing\n */\n\nimport type { WorkflowProgressJob, WorkflowRunRecord } from '@agimon-ai/workflow-mcp';\nimport type { AgentToolResult } from '@earendil-works/pi-coding-agent';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\n\n/**\n * Environment variable stamped onto every run launched from a Pi session.\n *\n * `RunWorkflowService` forwards `env` to the inner CLI invocation across the\n * `launch-command` delegation boundary and persists it on the run record, so\n * this survives backgrounding and identifies the launching session afterwards.\n */\nexport const PI_SESSION_ENV = 'PI_SESSION_ID';\n\n/** Operator override for the per-session launch ceiling. */\nconst MAX_CONCURRENT_ENV = 'WORKFLOW_MCP_MAX_CONCURRENT';\nconst DEFAULT_MAX_CONCURRENT = 5;\n\nexport interface WorkflowToolDetails {\n tool: string;\n}\n\n/** Resolve the per-session launch ceiling from the environment. */\nexport function resolveMaxConcurrent(env: NodeJS.ProcessEnv = process.env): number {\n const parsed = Number(env[MAX_CONCURRENT_ENV]);\n return Number.isInteger(parsed) && parsed > 0 ? parsed : DEFAULT_MAX_CONCURRENT;\n}\n\n/**\n * True when this session launched the run.\n *\n * Fails closed on a missing session id: an unstamped record (a CLI launch) and\n * a call arriving before the session id is known both match nothing, so no run\n * ever leaks across sessions through an undefined-equals-undefined comparison.\n */\nexport function isSessionRun(record: WorkflowRunRecord, sessionId: string | undefined): boolean {\n return sessionId !== undefined && record.env?.[PI_SESSION_ENV] === sessionId;\n}\n\n/** Runs launched by one Pi session that are still running. */\nexport function runsForSession(records: WorkflowRunRecord[], sessionId: string): WorkflowRunRecord[] {\n return records.filter((record) => isSessionRun(record, sessionId) && record.stage === 'running');\n}\n\n/**\n * What the caller is told when the registry, not the launcher, acknowledged a\n * launch.\n *\n * Leads with the run key because it is the handle every other workflow action\n * takes, and it is no longer available any other way: the launcher's own output\n * is not waited for, so nothing else in this result carries it.\n */\nexport function launchedRunSummary(record: WorkflowRunRecord): string {\n return [\n `Started ${record.displayName} in workspace ${record.workspace}.`,\n `Run key: ${record.runKey}`,\n 'The run is registered and going. This call returned at that point rather than waiting for the launcher process to exit.',\n ].join('\\n');\n}\n\n/**\n * What the caller is told when the launch was handed off but no run has\n * registered inside the acknowledgement budget.\n *\n * Deliberately not an error: the launcher is slow rather than broken often\n * enough that failing here would strand runs that go on to start normally.\n * There is no run key to offer yet, so it points at the surfaces that do not\n * need one.\n */\nexport function launchHandoffSummary(workflowPath: string): string {\n return [\n `Launch handed off for ${workflowPath}, but no run has registered yet.`,\n 'Nothing was cancelled: the launcher is still starting, and a run that registers later still reports back here when it finishes.',\n 'Do not launch it again. Ask the user to check the active workflow list if they need to see it sooner.',\n ].join('\\n');\n}\n\n/**\n * Escape sequences a terminal consumes rather than prints.\n *\n * Built from a string with the rule silenced, the way `doom-runner`'s own\n * scrubber does it, because matching the escape byte is the entire job. Not\n * imported from there: that package's published build is a stale artifact\n * missing the export, and a launch notice should not need another package's\n * build to be current.\n */\n// oxlint-disable-next-line no-control-regex -- matching terminal control bytes is the point\nconst ESCAPE_SEQUENCE = new RegExp(\n ['\\\\u001B\\\\[[0-9;?]*[ -/]*[@-~]', '\\\\u001B\\\\][^\\\\u0007\\\\u001B]*(?:\\\\u0007|\\\\u001B\\\\\\\\)', '\\\\u001B[@-Z\\\\\\\\-_]'].join(\n '|',\n ),\n 'g',\n);\n\n/** Rows made only of box-drawing: separators that carry nothing once trimmed. */\nconst RULE_ROW = /^[\\s─-╿]*$/u;\nconst NOTICE_LINE_LIMIT = 3;\n/**\n * Widest a notice row may be before it is clipped.\n *\n * A three-line cap does not bound a toast on its own: the engine announces its\n * delegation by echoing the whole shell command, temp script path included, and\n * one line of that wraps across three rows of a narrow terminal and shoves the\n * transcript around. Clipped at a width every terminal can hold instead.\n */\nconst NOTICE_WIDTH_LIMIT = 100;\n\n/**\n * Cut a tool result down to something a toast can hold.\n *\n * The launch result used to reach `ui.notify` whole, and for a workflow that\n * executes in this process that result is the engine's entire console log:\n * banner, run directory, job tree, rules, colour. Pi rendered every line of it\n * over the transcript, which reads as a broken screen rather than as output.\n * Escape sequences go first: the log carries colour the notification would\n * render as literal text, and a stray clear or cursor-move would do to the\n * screen exactly what this function exists to prevent.\n */\nexport function launchNotice(text: string, limit: number = NOTICE_LINE_LIMIT): string {\n const lines = text\n .replace(ESCAPE_SEQUENCE, '')\n .split('\\n')\n .map((line) => line.trimEnd())\n .filter((line) => line.trim().length > 0 && !RULE_ROW.test(line))\n .map((line) => (line.length > NOTICE_WIDTH_LIMIT ? `${line.slice(0, NOTICE_WIDTH_LIMIT - 1)}…` : line));\n if (lines.length === 0) return 'Workflow started.';\n if (lines.length <= limit) return lines.join('\\n');\n return [...lines.slice(0, limit), `… ${lines.length - limit} more lines, in the run's own output.`].join('\\n');\n}\n\n/** Flatten MCP tool content to text for Pi. */\nexport function toolResultText(result: CallToolResult): string {\n return result.content\n .map((part) => (part.type === 'text' ? part.text : ''))\n .filter(Boolean)\n .join('\\n')\n .trim();\n}\n\n/**\n * Convert an MCP tool result into a Pi tool result.\n *\n * Pi signals tool failure by throwing: the agent loop catches it and builds the\n * error result. So an `isError` MCP result becomes a thrown error rather than a\n * successful result carrying a flag Pi would ignore.\n */\nexport function toAgentToolResult(\n tool: string,\n result: CallToolResult,\n errorOptions: string[] = [],\n): AgentToolResult<WorkflowToolDetails> {\n const text = toolResultText(result) || 'No output.';\n if (result.isError) throw new Error(withOptions(text, errorOptions));\n return { content: [{ type: 'text', text }], details: { tool } };\n}\n\n/**\n * Attach a short menu of next steps to a problem.\n *\n * An error with no route forward is where an agent invents one: retrying a\n * capacity limit, relaunching a run that should be recovered, or silently\n * giving up on work the user is waiting for. Naming two or three real options\n * turns an error into a decision, and the decision belongs to the user.\n */\nexport function withOptions(problem: string, options: string[]): string {\n if (options.length === 0) return problem;\n return [problem, '', 'Options, put these to the user rather than picking one yourself:', ...options.map(bullet)].join(\n '\\n',\n );\n}\n\nfunction bullet(option: string): string {\n return `- ${option}`;\n}\n\n/** The job and step a run died on, preferring the progress log to the record. */\nfunction failurePosition(\n record: WorkflowRunRecord,\n jobs: WorkflowProgressJob[],\n): { job?: string; step?: string; reason?: string } {\n // The progress log knows which step was in flight; the record only names the\n // job. Falling back keeps this working for runs that predate the log.\n const failedJob = jobs.find((job) => job.status === 'failed');\n const failedStep = failedJob?.steps.find((step) => step.status === 'failed');\n return {\n job: failedJob?.name ?? record.failedJob,\n step: failedStep?.name,\n reason: failedStep?.reason ?? failedJob?.reason,\n };\n}\n\n/**\n * Describe a finished run for the agent that launched it.\n *\n * Carries the job identifiers back so a dispatching agent can match the run to\n * the work item it launched it for without another lookup. When the run failed,\n * carries the failing step and a set of options too: the agent is being told\n * about this out of band, with no user question in flight, so without them it\n * has to guess whether to recover, relaunch, or report.\n */\nexport function finishedRunSummary(record: WorkflowRunRecord, jobs: WorkflowProgressJob[] = []): string {\n const outcome = record.stage === 'completed' ? 'completed' : `ended in ${record.stage}`;\n const failure = failurePosition(record, jobs);\n const lines: Array<string | undefined> = [\n `Workflow run ${record.runKey} in workspace ${record.workspace} ${outcome}.`,\n record.workflowId ? `Workflow: ${record.workflowId}` : undefined,\n failure.job ? `Failed job: ${failure.job}${failure.step ? ` (step: ${failure.step})` : ''}` : undefined,\n record.errorMessage ? `Error: ${record.errorMessage}` : undefined,\n failure.reason && failure.reason !== record.errorMessage ? `Step reported: ${failure.reason}` : undefined,\n ];\n const jobId = record.env?.AGIFLOW_JOB_ID;\n if (jobId) lines.push(`Agiflow job: ${record.env?.AGIFLOW_JOB_KIND ?? 'unknown'} ${jobId}`);\n\n const summary = lines.filter((line): line is string => Boolean(line)).join('\\n');\n if (record.stage === 'completed') return summary;\n\n // A run the user stopped is not a defect, so it gets no diagnosis step: the\n // question is only whether to pick it back up.\n const stopped = record.outcome === 'interrupted';\n if (stopped) {\n return withOptions(summary, [\n `workflow_run {\"action\":\"recover\",\"runKey\":${JSON.stringify(record.runKey)}}: pick it up where it stopped.`,\n 'Leave it stopped and move on.',\n ]);\n }\n\n const diagnosticText = [record.errorMessage, failure.reason].filter(Boolean).join('\\n');\n if (diagnosticText.includes('JOB_ALREADY_CLAIMED')) {\n return withOptions(summary, [\n 'Report contention: another worker owns this job. Do not unlock, release, or retry the claim automatically.',\n ]);\n }\n if (diagnosticText.includes('WORKFLOW_NOT_OWNED') || /release failed/i.test(diagnosticText)) {\n return withOptions(summary, [\n 'Inspect the current workflow ownership and ask the user before any release or unlock. Never force another worker’s lock.',\n ]);\n }\n if (/running workflow not found/i.test(diagnosticText)) {\n return withOptions(summary, [\n `workflow_run {\"action\":\"status\",\"runKey\":${JSON.stringify(record.runKey)}}: re-check current state before retrying.`,\n 'Report the recorded terminal state when no running owner remains.',\n ]);\n }\n\n return withOptions(summary, [\n `workflow_run {\"action\":\"tail\",\"runKey\":${JSON.stringify(record.runKey)}}: read the run's own output first, when the error above does not explain the failure.`,\n `workflow_run {\"action\":\"recover\",\"runKey\":${JSON.stringify(record.runKey)}}: resume from the failed job, keeping the work already done. Fits a transient or external cause.`,\n 'Report the failure and stop, when it needs a code change or a decision you cannot make.',\n ]);\n}\n"],"mappings":"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"}