@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,333 @@
1
+ import { DOOM_FULLSCREEN_UI_OPTIONS, DOOM_OVERLAY_ACCENT, DoomOverlay } from "./doomOverlay.mjs";
2
+ import { fit, isControlInput, matchesQuery, pathTail, rightAligned } from "./overlayText.mjs";
3
+ import { Key, matchesKey, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
4
+ DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions;
5
+ const TITLE = "WORKFLOWS";
6
+ const BREADCRUMB = "SPC › w / workflows › l / list";
7
+ const DIVIDER = "│";
8
+ const DEFAULT_PAGE_SIZE = 1;
9
+ const ROWS_PER_ENTRY = 2;
10
+ /** Indent under `${SELECTION_MARKER} `, so the path line hangs under the name. */
11
+ const META_INDENT = " ";
12
+ const EMPTY_NAME = "(unnamed)";
13
+ const LAUNCH_KEY = "r";
14
+ const FILTER_KEY = "/";
15
+ const KEY_CLEAR = "";
16
+ const FILTER_LABEL = "FILTER";
17
+ const EMPTY_MESSAGE = "No workflow definitions were found in this repository.";
18
+ const TAB_ORDER = [
19
+ "triggers",
20
+ "inputs",
21
+ "steps"
22
+ ];
23
+ const TAB_KEYS = {
24
+ t: "triggers",
25
+ i: "inputs",
26
+ s: "steps"
27
+ };
28
+ const FOOTER = "↑↓ cursor · JK scroll · tab detail · / filter · r launch · esc close";
29
+ const FOOTER_HINTS = [
30
+ ["↑↓", "move"],
31
+ ["JK", "scroll"],
32
+ ["tab", "cycle"],
33
+ ["/", "filter"],
34
+ ["r", "launch"]
35
+ ];
36
+ const FILTER_FOOTER = "enter keep · esc clear · ctrl+u wipe";
37
+ const FILTER_FOOTER_HINTS = [
38
+ ["enter", "keep"],
39
+ ["esc", "clear"],
40
+ ["ctrl+u", "wipe"]
41
+ ];
42
+ function splitLayout(width) {
43
+ const paneBudget = Math.max(2, width - visibleWidth(DIVIDER));
44
+ const leftPaneWidth = Math.max(1, Math.floor(paneBudget / 3));
45
+ const rightPaneWidth = Math.max(1, paneBudget - leftPaneWidth);
46
+ const gutterWidth = leftPaneWidth >= 3 && rightPaneWidth >= 3 ? 1 : 0;
47
+ return {
48
+ leftContentWidth: Math.max(1, leftPaneWidth - gutterWidth),
49
+ rightContentWidth: Math.max(1, rightPaneWidth - gutterWidth),
50
+ gutterWidth
51
+ };
52
+ }
53
+ function appendWrapped(lines, text, width, colour, theme) {
54
+ for (const line of wrapTextWithAnsi(text, Math.max(1, width))) lines.push(theme.fg(colour, line));
55
+ }
56
+ function appendSection(lines, heading, items, width, theme) {
57
+ lines.push(theme.bold(theme.fg("accent", heading)));
58
+ if (items.length === 0) lines.push(theme.fg("dim", " none"));
59
+ else for (const item of items) appendWrapped(lines, ` • ${item}`, width, "text", theme);
60
+ lines.push("");
61
+ }
62
+ function inputLabel(input) {
63
+ const qualifiers = [
64
+ input.required ? "required" : "optional",
65
+ input.default === void 0 ? void 0 : `default ${input.default}`,
66
+ input.options && input.options.length > 0 ? `one of ${input.options.join(", ")}` : void 0
67
+ ].filter((part) => Boolean(part));
68
+ const description = input.description ? `${input.description} · ` : "";
69
+ return `${input.name} — ${description}${qualifiers.join(" · ")}`;
70
+ }
71
+ function workflowDetailLines(detail, tab, width, theme) {
72
+ const lines = [];
73
+ if (detail.error) {
74
+ lines.push(theme.bold(theme.fg("error", "WORKFLOW ERROR")));
75
+ appendWrapped(lines, detail.error, width, "error", theme);
76
+ lines.push("");
77
+ return lines;
78
+ }
79
+ if (tab === "triggers") {
80
+ appendSection(lines, "TRIGGERS", detail.triggers, width, theme);
81
+ appendSection(lines, "RUNNERS", detail.runners ?? ["any available runner"], width, theme);
82
+ return lines;
83
+ }
84
+ if (tab === "inputs") {
85
+ appendSection(lines, "DISPATCH INPUTS", detail.inputs.map(inputLabel), width, theme);
86
+ return lines;
87
+ }
88
+ for (const job of detail.jobs) {
89
+ lines.push(theme.bold(theme.fg("accent", job.name)));
90
+ if (job.steps.length === 0) lines.push(theme.fg("dim", " no steps"));
91
+ else for (const step of job.steps) appendWrapped(lines, ` • ${step}`, width, "text", theme);
92
+ lines.push("");
93
+ }
94
+ if (detail.jobs.length === 0) appendSection(lines, "JOBS", [], width, theme);
95
+ return lines;
96
+ }
97
+ function tabStrip(tab, width, theme) {
98
+ const labels = TAB_ORDER.map((candidate) => {
99
+ const label = candidate.toUpperCase();
100
+ return candidate === tab ? theme.inverse(theme.bold(` ${label} `)) : theme.fg("dim", ` ${label} `);
101
+ }).join(" ");
102
+ return truncateToWidth(labels, Math.max(0, width), "…");
103
+ }
104
+ function filterWorkflowRows(rows, query) {
105
+ if (!query.trim()) return rows;
106
+ return rows.filter((row) => matchesQuery([
107
+ row.name,
108
+ row.relativePath,
109
+ row.description,
110
+ row.tags.join(" ")
111
+ ].join(" "), query));
112
+ }
113
+ var WorkflowCatalogComponent = class extends DoomOverlay {
114
+ done;
115
+ options;
116
+ rows;
117
+ detailCache = /* @__PURE__ */ new Map();
118
+ cursorIndex = 0;
119
+ tab = "triggers";
120
+ query = "";
121
+ filtering = false;
122
+ notice;
123
+ listPageSize = DEFAULT_PAGE_SIZE;
124
+ detailPageSize = DEFAULT_PAGE_SIZE;
125
+ detailOffset = 0;
126
+ detailTotal = 0;
127
+ constructor(tui, theme, rows, done, options) {
128
+ super(tui, theme);
129
+ this.done = done;
130
+ this.options = options;
131
+ this.rows = [...rows].sort((left, right) => left.name.localeCompare(right.name));
132
+ }
133
+ matches() {
134
+ return filterWorkflowRows(this.rows, this.query);
135
+ }
136
+ cursorRow() {
137
+ const matches = this.matches();
138
+ return matches[Math.min(this.cursorIndex, Math.max(0, matches.length - 1))];
139
+ }
140
+ /** Parsed once per workflow, then reused for every repaint of that row. */
141
+ detailFor(row) {
142
+ const cached = this.detailCache.get(row.key);
143
+ if (cached) return cached;
144
+ const detail = this.options.loadDetail(row);
145
+ this.detailCache.set(row.key, detail);
146
+ return detail;
147
+ }
148
+ moveCursor(delta) {
149
+ const count = this.matches().length;
150
+ if (count === 0) return;
151
+ const next = Math.max(0, Math.min(count - 1, this.cursorIndex + delta));
152
+ if (next === this.cursorIndex) return;
153
+ this.cursorIndex = next;
154
+ this.detailOffset = 0;
155
+ this.invalidate();
156
+ }
157
+ switchTab(tab) {
158
+ if (this.tab === tab) return;
159
+ this.tab = tab;
160
+ this.detailOffset = 0;
161
+ this.invalidate();
162
+ }
163
+ cycleTab() {
164
+ const current = TAB_ORDER.indexOf(this.tab);
165
+ this.switchTab(TAB_ORDER[(current + 1) % TAB_ORDER.length] ?? "triggers");
166
+ }
167
+ scrollDetail(delta) {
168
+ if (!this.cursorRow()) return;
169
+ const maximum = Math.max(0, this.detailTotal - this.detailPageSize);
170
+ const next = Math.max(0, Math.min(maximum, this.detailOffset + delta));
171
+ if (next === this.detailOffset) return;
172
+ this.detailOffset = next;
173
+ this.invalidate();
174
+ }
175
+ setNotice(notice) {
176
+ this.notice = notice;
177
+ this.invalidate();
178
+ }
179
+ setQuery(query) {
180
+ if (query === this.query) return;
181
+ this.query = query;
182
+ this.cursorIndex = 0;
183
+ this.detailOffset = 0;
184
+ this.invalidate();
185
+ }
186
+ launchCursor() {
187
+ const row = this.cursorRow();
188
+ if (!row) {
189
+ this.setNotice("launch unavailable · no workflow is selected");
190
+ return;
191
+ }
192
+ const launchWorkflow = this.options.launchWorkflow;
193
+ if (!launchWorkflow) {
194
+ this.setNotice("launch unavailable · no workflow launcher is attached");
195
+ return;
196
+ }
197
+ const detail = this.detailFor(row);
198
+ if (detail.error) {
199
+ this.setNotice(`launch unavailable · ${detail.error}`);
200
+ return;
201
+ }
202
+ this.done(void 0);
203
+ launchWorkflow(row);
204
+ }
205
+ handleFilterInput(data) {
206
+ if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c")) {
207
+ this.filtering = false;
208
+ this.setQuery("");
209
+ this.invalidate();
210
+ return;
211
+ }
212
+ if (matchesKey(data, "enter")) {
213
+ this.filtering = false;
214
+ this.invalidate();
215
+ return;
216
+ }
217
+ if (matchesKey(data, "backspace")) {
218
+ this.setQuery(this.query.slice(0, -1));
219
+ return;
220
+ }
221
+ if (data === KEY_CLEAR) {
222
+ this.setQuery("");
223
+ return;
224
+ }
225
+ if (!isControlInput(data)) this.setQuery(this.query + data);
226
+ }
227
+ handleInput(data) {
228
+ if (this.filtering) {
229
+ this.handleFilterInput(data);
230
+ return;
231
+ }
232
+ if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c")) {
233
+ this.done(void 0);
234
+ return;
235
+ }
236
+ if (matchesKey(data, Key.shift("k"))) return this.scrollDetail(-1);
237
+ if (matchesKey(data, Key.shift("j"))) return this.scrollDetail(1);
238
+ if (matchesKey(data, "up") || data === "k") return this.moveCursor(-1);
239
+ if (matchesKey(data, "down") || data === "j") return this.moveCursor(1);
240
+ if (matchesKey(data, "pageUp")) return this.moveCursor(-this.listPageSize);
241
+ if (matchesKey(data, "pageDown")) return this.moveCursor(this.listPageSize);
242
+ if (matchesKey(data, "tab")) return this.cycleTab();
243
+ if (data === FILTER_KEY) {
244
+ this.filtering = true;
245
+ this.notice = void 0;
246
+ this.invalidate();
247
+ return;
248
+ }
249
+ if (data === LAUNCH_KEY) return this.launchCursor();
250
+ const tab = TAB_KEYS[data];
251
+ if (tab) this.switchTab(tab);
252
+ }
253
+ getChrome() {
254
+ const matches = this.matches();
255
+ const scope = this.query ? `${matches.length} of ${this.rows.length}` : `${this.rows.length}`;
256
+ return {
257
+ title: TITLE,
258
+ accent: DOOM_OVERLAY_ACCENT,
259
+ breadcrumb: BREADCRUMB,
260
+ headerRight: `${scope} workflows · ${this.tab}`,
261
+ footer: this.filtering ? FILTER_FOOTER : FOOTER,
262
+ footerHints: this.filtering ? FILTER_FOOTER_HINTS : FOOTER_HINTS,
263
+ footerRight: matches.length ? `${Math.min(this.cursorIndex, matches.length - 1) + 1}/${matches.length}` : "no match"
264
+ };
265
+ }
266
+ renderBody(width, height) {
267
+ const filterRows = this.filtering || this.query ? 1 : 0;
268
+ const transientRows = filterRows + (this.notice === void 0 ? 0 : 1);
269
+ const mainHeight = Math.max(0, height - transientRows);
270
+ const layout = splitLayout(width);
271
+ const left = this.renderList(layout.leftContentWidth, mainHeight);
272
+ const right = this.renderDetail(layout.rightContentWidth, mainHeight);
273
+ const gutter = " ".repeat(layout.gutterWidth);
274
+ const divider = this.theme.fg("borderMuted", DIVIDER);
275
+ const lines = [];
276
+ for (let index = 0; index < mainHeight; index++) lines.push(`${fit(left[index] ?? "", layout.leftContentWidth)}${gutter}${divider}${gutter}${fit(right[index] ?? "", layout.rightContentWidth)}`);
277
+ if (filterRows) {
278
+ const value = this.filtering ? `${this.query}█` : this.query;
279
+ lines.push(` ${this.theme.bold(this.theme.fg("accent", FILTER_LABEL))} ${value}`);
280
+ }
281
+ if (this.notice !== void 0) lines.push(` ${this.theme.fg("muted", this.notice)}`);
282
+ return lines.slice(0, height).map((line) => fit(line, width));
283
+ }
284
+ renderList(width, height) {
285
+ const matches = this.matches();
286
+ const lines = [this.theme.bold(this.theme.fg("accent", `WORKFLOWS ${matches.length}`))];
287
+ if (matches.length === 0) {
288
+ appendWrapped(lines, this.rows.length === 0 ? EMPTY_MESSAGE : "No workflow matches this filter.", width, "dim", this.theme);
289
+ this.listPageSize = DEFAULT_PAGE_SIZE;
290
+ return lines.slice(0, height);
291
+ }
292
+ this.listPageSize = Math.max(DEFAULT_PAGE_SIZE, Math.floor((height - 1) / ROWS_PER_ENTRY));
293
+ const active = Math.min(this.cursorIndex, matches.length - 1);
294
+ const start = Math.max(0, Math.min(active - this.listPageSize + 1, Math.max(0, matches.length - this.listPageSize)));
295
+ for (const [offset, row] of matches.slice(start, start + this.listPageSize).entries()) {
296
+ const current = start + offset === active;
297
+ const marker = current ? this.theme.fg("accent", "›") : " ";
298
+ const label = row.name || EMPTY_NAME;
299
+ const name = current ? this.theme.bold(this.theme.fg("accent", label)) : this.theme.fg("text", label);
300
+ const meta = this.theme.fg("dim", pathTail(row.relativePath, Math.max(0, width - 2)));
301
+ lines.push(fit(`${marker} ${name}`, width));
302
+ lines.push(fit(`${META_INDENT}${meta}`, width));
303
+ }
304
+ return lines.slice(0, height);
305
+ }
306
+ renderDetail(width, height) {
307
+ const row = this.cursorRow();
308
+ if (!row) {
309
+ this.detailTotal = 0;
310
+ this.detailPageSize = Math.max(DEFAULT_PAGE_SIZE, height);
311
+ this.detailOffset = 0;
312
+ const lines = [this.theme.bold(this.theme.fg("accent", "WORKFLOW DETAIL")), ""];
313
+ appendWrapped(lines, this.rows.length === 0 ? EMPTY_MESSAGE : "No workflow matches this filter.", width, "text", this.theme);
314
+ return lines.slice(0, height);
315
+ }
316
+ const header = [rightAligned(this.theme.bold(this.theme.fg("accent", `INSPECTING ${row.name || EMPTY_NAME}`)), this.theme.fg("dim", pathTail(row.relativePath, Math.max(0, Math.floor(width / 2)))), width)];
317
+ if (row.description) appendWrapped(header, row.description, width, "text", this.theme);
318
+ if (row.tags.length > 0) appendWrapped(header, row.tags.join(" · "), width, "dim", this.theme);
319
+ header.push(tabStrip(this.tab, width, this.theme), "");
320
+ const body = workflowDetailLines(this.detailFor(row), this.tab, width, this.theme);
321
+ this.detailPageSize = Math.max(0, height - header.length);
322
+ this.detailTotal = body.length;
323
+ this.detailOffset = Math.min(this.detailOffset, Math.max(0, body.length - this.detailPageSize));
324
+ return [...header, ...body.slice(this.detailOffset, this.detailOffset + this.detailPageSize)].slice(0, height);
325
+ }
326
+ };
327
+ async function openWorkflowCatalogOverlay(ctx, rows, options) {
328
+ await ctx.ui.custom((tui, theme, _keybindings, done) => new WorkflowCatalogComponent(tui, theme, rows, done, options), DOOM_FULLSCREEN_UI_OPTIONS);
329
+ }
330
+ //#endregion
331
+ export { WorkflowCatalogComponent, filterWorkflowRows, openWorkflowCatalogOverlay, workflowDetailLines };
332
+
333
+ //# sourceMappingURL=workflowCatalog.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflowCatalog.mjs","names":[],"sources":["../../../../src/tui/workflow/workflowCatalog.ts"],"sourcesContent":["/**\n * The `SPC w l` board: every workflow this repository defines, with the cursor\n * workflow's parsed detail beside it and `r` to launch it.\n *\n * WHY NOT `workflowPicker.ts`:\n * That surface answers \"which one\", hands a value back, and closes - which is\n * what `SPC w c` recovery still needs. This one answers \"what is this workflow,\n * and do I want to run it\", so the detail has to be on screen next to the list\n * rather than behind a selection. The picker stays for the pick-and-return case\n * rather than growing a second mode.\n *\n * DESIGN PATTERNS:\n * - Detail is loaded through an injected loader, so parsing a workflow file\n * stays out of the TUI and the surface is assertable as text. Loaded on\n * demand for the cursor row and cached by row key: a repository with fifty\n * workflows must not parse fifty files to draw one pane\n * - A row is two lines, name over path. One line made the name - the field a\n * reader picks a row by - share a third of the overlay with a path that\n * repeats its directory on every row\n * - `/` opens the filter rather than plain letters filtering as they are typed:\n * the letter keys carry commands here (`r` launch, `t`/`i`/`s` tabs)\n */\n\nimport type { ExtensionContext, Theme } from '@earendil-works/pi-coding-agent';\nimport { Key, matchesKey, truncateToWidth, visibleWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';\n\nimport {\n DOOM_FULLSCREEN_UI_OPTIONS,\n DOOM_OVERLAY_ACCENT,\n DoomOverlay,\n type DoomOverlayChrome,\n type DoomOverlayTui,\n} from './doomOverlay';\nimport {\n CURSOR_BLOCK,\n ELLIPSIS,\n fit,\n isControlInput,\n matchesQuery,\n pathTail,\n rightAligned,\n SELECTION_MARKER,\n} from './overlayText';\n\nexport const WORKFLOW_CATALOG_OVERLAY_OPTIONS = DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions;\n\n/** One workflow file, as the catalog tool reports it. */\nexport interface WorkflowCatalogRow {\n /** Stable identity and the loader's cache key: the absolute path. */\n key: string;\n name: string;\n relativePath: string;\n description: string;\n tags: readonly string[];\n}\n\nexport interface WorkflowInputSummary {\n name: string;\n description?: string;\n required?: boolean;\n default?: string;\n options?: readonly string[];\n}\n\nexport interface WorkflowJobSummary {\n name: string;\n steps: readonly string[];\n}\n\n/**\n * What the detail pane shows for one workflow. `runners` is undefined when the\n * workflow names no runner map at all, which is not the same as naming an empty\n * one - see `compatibleRunners`.\n */\nexport interface WorkflowCatalogDetail {\n triggers: readonly string[];\n inputs: readonly WorkflowInputSummary[];\n jobs: readonly WorkflowJobSummary[];\n runners?: readonly string[];\n /** Set when the file could not be parsed; the pane shows this instead of guessing. */\n error?: string;\n}\n\nexport type WorkflowDetailLoader = (row: WorkflowCatalogRow) => WorkflowCatalogDetail;\n\n/** Starts one workflow and returns immediately; the overlay closes on launch. */\nexport type WorkflowLaunchDispatcher = (row: WorkflowCatalogRow) => void;\n\nexport interface WorkflowCatalogOptions {\n loadDetail: WorkflowDetailLoader;\n /** Absent until a composition root wires the launch key to a real launcher. */\n launchWorkflow?: WorkflowLaunchDispatcher;\n}\n\nexport type WorkflowDetailTab = 'triggers' | 'inputs' | 'steps';\n\ntype ThemeColor = Parameters<Theme['fg']>[0];\n\nconst TITLE = 'WORKFLOWS';\nconst BREADCRUMB = 'SPC › w / workflows › l / list';\nconst DIVIDER = '│';\nconst DEFAULT_PAGE_SIZE = 1;\nconst ROWS_PER_ENTRY = 2;\n/** Indent under `${SELECTION_MARKER} `, so the path line hangs under the name. */\nconst META_INDENT = ' ';\nconst EMPTY_NAME = '(unnamed)';\nconst LAUNCH_KEY = 'r';\nconst FILTER_KEY = '/';\nconst KEY_CLEAR = '\\x15';\nconst FILTER_LABEL = 'FILTER';\nconst EMPTY_MESSAGE = 'No workflow definitions were found in this repository.';\nconst TAB_ORDER: readonly WorkflowDetailTab[] = ['triggers', 'inputs', 'steps'];\nconst TAB_KEYS: Record<string, WorkflowDetailTab> = { t: 'triggers', i: 'inputs', s: 'steps' };\nconst FOOTER = '↑↓ cursor · JK scroll · tab detail · / filter · r launch · esc close';\nconst FOOTER_HINTS: readonly (readonly [string, string])[] = [\n ['↑↓', 'move'],\n ['JK', 'scroll'],\n ['tab', 'cycle'],\n ['/', 'filter'],\n ['r', 'launch'],\n];\nconst FILTER_FOOTER = 'enter keep · esc clear · ctrl+u wipe';\nconst FILTER_FOOTER_HINTS: readonly (readonly [string, string])[] = [\n ['enter', 'keep'],\n ['esc', 'clear'],\n ['ctrl+u', 'wipe'],\n];\n\ninterface SplitLayout {\n leftContentWidth: number;\n rightContentWidth: number;\n gutterWidth: number;\n}\n\nfunction splitLayout(width: number): SplitLayout {\n const paneBudget = Math.max(2, width - visibleWidth(DIVIDER));\n const leftPaneWidth = Math.max(1, Math.floor(paneBudget / 3));\n const rightPaneWidth = Math.max(1, paneBudget - leftPaneWidth);\n const gutterWidth = leftPaneWidth >= 3 && rightPaneWidth >= 3 ? 1 : 0;\n return {\n leftContentWidth: Math.max(1, leftPaneWidth - gutterWidth),\n rightContentWidth: Math.max(1, rightPaneWidth - gutterWidth),\n gutterWidth,\n };\n}\n\nfunction appendWrapped(lines: string[], text: string, width: number, colour: ThemeColor, theme: Theme): void {\n for (const line of wrapTextWithAnsi(text, Math.max(1, width))) lines.push(theme.fg(colour, line));\n}\n\nfunction appendSection(lines: string[], heading: string, items: readonly string[], width: number, theme: Theme): void {\n lines.push(theme.bold(theme.fg('accent', heading)));\n if (items.length === 0) lines.push(theme.fg('dim', ' none'));\n else for (const item of items) appendWrapped(lines, ` • ${item}`, width, 'text', theme);\n lines.push('');\n}\n\nfunction inputLabel(input: WorkflowInputSummary): string {\n const qualifiers = [\n input.required ? 'required' : 'optional',\n input.default === undefined ? undefined : `default ${input.default}`,\n input.options && input.options.length > 0 ? `one of ${input.options.join(', ')}` : undefined,\n ].filter((part): part is string => Boolean(part));\n const description = input.description ? `${input.description} · ` : '';\n return `${input.name} — ${description}${qualifiers.join(' · ')}`;\n}\n\nexport function workflowDetailLines(\n detail: WorkflowCatalogDetail,\n tab: WorkflowDetailTab,\n width: number,\n theme: Theme,\n): string[] {\n const lines: string[] = [];\n if (detail.error) {\n lines.push(theme.bold(theme.fg('error', 'WORKFLOW ERROR')));\n appendWrapped(lines, detail.error, width, 'error', theme);\n lines.push('');\n return lines;\n }\n if (tab === 'triggers') {\n appendSection(lines, 'TRIGGERS', detail.triggers, width, theme);\n // No runner map means every runner qualifies, which a bare \"none\" would\n // report as the opposite.\n appendSection(lines, 'RUNNERS', detail.runners ?? ['any available runner'], width, theme);\n return lines;\n }\n if (tab === 'inputs') {\n appendSection(lines, 'DISPATCH INPUTS', detail.inputs.map(inputLabel), width, theme);\n return lines;\n }\n for (const job of detail.jobs) {\n lines.push(theme.bold(theme.fg('accent', job.name)));\n if (job.steps.length === 0) lines.push(theme.fg('dim', ' no steps'));\n else for (const step of job.steps) appendWrapped(lines, ` • ${step}`, width, 'text', theme);\n lines.push('');\n }\n if (detail.jobs.length === 0) appendSection(lines, 'JOBS', [], width, theme);\n return lines;\n}\n\nfunction tabStrip(tab: WorkflowDetailTab, width: number, theme: Theme): string {\n const labels = TAB_ORDER.map((candidate) => {\n const label = candidate.toUpperCase();\n return candidate === tab ? theme.inverse(theme.bold(` ${label} `)) : theme.fg('dim', ` ${label} `);\n }).join(' ');\n return truncateToWidth(labels, Math.max(0, width), ELLIPSIS);\n}\n\nexport function filterWorkflowRows(rows: readonly WorkflowCatalogRow[], query: string): readonly WorkflowCatalogRow[] {\n if (!query.trim()) return rows;\n return rows.filter((row) =>\n matchesQuery([row.name, row.relativePath, row.description, row.tags.join(' ')].join(' '), query),\n );\n}\n\nexport class WorkflowCatalogComponent extends DoomOverlay {\n private readonly rows: readonly WorkflowCatalogRow[];\n private readonly detailCache = new Map<string, WorkflowCatalogDetail>();\n private cursorIndex = 0;\n private tab: WorkflowDetailTab = 'triggers';\n private query = '';\n private filtering = false;\n private notice: string | undefined;\n private listPageSize = DEFAULT_PAGE_SIZE;\n private detailPageSize = DEFAULT_PAGE_SIZE;\n private detailOffset = 0;\n private detailTotal = 0;\n\n constructor(\n tui: DoomOverlayTui,\n theme: Theme,\n rows: readonly WorkflowCatalogRow[],\n private readonly done: (result: undefined) => void,\n private readonly options: WorkflowCatalogOptions,\n ) {\n super(tui, theme);\n this.rows = [...rows].sort((left, right) => left.name.localeCompare(right.name));\n }\n\n private matches(): readonly WorkflowCatalogRow[] {\n return filterWorkflowRows(this.rows, this.query);\n }\n\n private cursorRow(): WorkflowCatalogRow | undefined {\n const matches = this.matches();\n return matches[Math.min(this.cursorIndex, Math.max(0, matches.length - 1))];\n }\n\n /** Parsed once per workflow, then reused for every repaint of that row. */\n private detailFor(row: WorkflowCatalogRow): WorkflowCatalogDetail {\n const cached = this.detailCache.get(row.key);\n if (cached) return cached;\n const detail = this.options.loadDetail(row);\n this.detailCache.set(row.key, detail);\n return detail;\n }\n\n private moveCursor(delta: number): void {\n const count = this.matches().length;\n if (count === 0) return;\n const next = Math.max(0, Math.min(count - 1, this.cursorIndex + delta));\n if (next === this.cursorIndex) return;\n this.cursorIndex = next;\n // The detail pane follows the cursor, so its scroll belonged to the row\n // that was showing, not the one replacing it.\n this.detailOffset = 0;\n this.invalidate();\n }\n\n private switchTab(tab: WorkflowDetailTab): void {\n if (this.tab === tab) return;\n this.tab = tab;\n this.detailOffset = 0;\n this.invalidate();\n }\n\n private cycleTab(): void {\n const current = TAB_ORDER.indexOf(this.tab);\n this.switchTab(TAB_ORDER[(current + 1) % TAB_ORDER.length] ?? 'triggers');\n }\n\n private scrollDetail(delta: number): void {\n if (!this.cursorRow()) return;\n const maximum = Math.max(0, this.detailTotal - this.detailPageSize);\n const next = Math.max(0, Math.min(maximum, this.detailOffset + delta));\n if (next === this.detailOffset) return;\n this.detailOffset = next;\n this.invalidate();\n }\n\n private setNotice(notice: string): void {\n this.notice = notice;\n this.invalidate();\n }\n\n private setQuery(query: string): void {\n if (query === this.query) return;\n this.query = query;\n // The previous index named a row this filter may no longer list.\n this.cursorIndex = 0;\n this.detailOffset = 0;\n this.invalidate();\n }\n\n private launchCursor(): void {\n const row = this.cursorRow();\n if (!row) {\n this.setNotice('launch unavailable · no workflow is selected');\n return;\n }\n const launchWorkflow = this.options.launchWorkflow;\n if (!launchWorkflow) {\n this.setNotice('launch unavailable · no workflow launcher is attached');\n return;\n }\n const detail = this.detailFor(row);\n if (detail.error) {\n this.setNotice(`launch unavailable · ${detail.error}`);\n return;\n }\n // Closing first is what makes the launcher's own prompts reachable: they\n // are host dialogs, and a fullscreen overlay sits over them.\n this.done(undefined);\n launchWorkflow(row);\n }\n\n private handleFilterInput(data: string): void {\n if (matchesKey(data, 'escape') || matchesKey(data, 'ctrl+c')) {\n this.filtering = false;\n this.setQuery('');\n this.invalidate();\n return;\n }\n if (matchesKey(data, 'enter')) {\n this.filtering = false;\n this.invalidate();\n return;\n }\n if (matchesKey(data, 'backspace')) {\n this.setQuery(this.query.slice(0, -1));\n return;\n }\n if (data === KEY_CLEAR) {\n this.setQuery('');\n return;\n }\n if (!isControlInput(data)) this.setQuery(this.query + data);\n }\n\n handleInput(data: string): void {\n if (this.filtering) {\n this.handleFilterInput(data);\n return;\n }\n if (matchesKey(data, 'escape') || matchesKey(data, 'ctrl+c')) {\n this.done(undefined);\n return;\n }\n if (matchesKey(data, Key.shift('k'))) return this.scrollDetail(-1);\n if (matchesKey(data, Key.shift('j'))) return this.scrollDetail(1);\n if (matchesKey(data, 'up') || data === 'k') return this.moveCursor(-1);\n if (matchesKey(data, 'down') || data === 'j') return this.moveCursor(1);\n if (matchesKey(data, 'pageUp')) return this.moveCursor(-this.listPageSize);\n if (matchesKey(data, 'pageDown')) return this.moveCursor(this.listPageSize);\n if (matchesKey(data, 'tab')) return this.cycleTab();\n if (data === FILTER_KEY) {\n this.filtering = true;\n this.notice = undefined;\n this.invalidate();\n return;\n }\n if (data === LAUNCH_KEY) return this.launchCursor();\n const tab = TAB_KEYS[data];\n if (tab) this.switchTab(tab);\n }\n\n protected getChrome(): DoomOverlayChrome {\n const matches = this.matches();\n const scope = this.query ? `${matches.length} of ${this.rows.length}` : `${this.rows.length}`;\n return {\n title: TITLE,\n accent: DOOM_OVERLAY_ACCENT,\n breadcrumb: BREADCRUMB,\n headerRight: `${scope} workflows · ${this.tab}`,\n footer: this.filtering ? FILTER_FOOTER : FOOTER,\n footerHints: this.filtering ? FILTER_FOOTER_HINTS : FOOTER_HINTS,\n footerRight: matches.length\n ? `${Math.min(this.cursorIndex, matches.length - 1) + 1}/${matches.length}`\n : 'no match',\n };\n }\n\n protected renderBody(width: number, height: number): string[] {\n const filterRows = this.filtering || this.query ? 1 : 0;\n const transientRows = filterRows + (this.notice === undefined ? 0 : 1);\n const mainHeight = Math.max(0, height - transientRows);\n const layout = splitLayout(width);\n const left = this.renderList(layout.leftContentWidth, mainHeight);\n const right = this.renderDetail(layout.rightContentWidth, mainHeight);\n const gutter = ' '.repeat(layout.gutterWidth);\n const divider = this.theme.fg('borderMuted', DIVIDER);\n const lines: string[] = [];\n for (let index = 0; index < mainHeight; index++) {\n lines.push(\n `${fit(left[index] ?? '', layout.leftContentWidth)}${gutter}${divider}${gutter}${fit(\n right[index] ?? '',\n layout.rightContentWidth,\n )}`,\n );\n }\n if (filterRows) {\n const value = this.filtering ? `${this.query}${CURSOR_BLOCK}` : this.query;\n lines.push(` ${this.theme.bold(this.theme.fg('accent', FILTER_LABEL))} ${value}`);\n }\n if (this.notice !== undefined) lines.push(` ${this.theme.fg('muted', this.notice)}`);\n return lines.slice(0, height).map((line) => fit(line, width));\n }\n\n private renderList(width: number, height: number): string[] {\n const matches = this.matches();\n const lines = [this.theme.bold(this.theme.fg('accent', `WORKFLOWS ${matches.length}`))];\n if (matches.length === 0) {\n appendWrapped(\n lines,\n this.rows.length === 0 ? EMPTY_MESSAGE : 'No workflow matches this filter.',\n width,\n 'dim',\n this.theme,\n );\n this.listPageSize = DEFAULT_PAGE_SIZE;\n return lines.slice(0, height);\n }\n\n this.listPageSize = Math.max(DEFAULT_PAGE_SIZE, Math.floor((height - 1) / ROWS_PER_ENTRY));\n const active = Math.min(this.cursorIndex, matches.length - 1);\n const start = Math.max(\n 0,\n Math.min(active - this.listPageSize + 1, Math.max(0, matches.length - this.listPageSize)),\n );\n for (const [offset, row] of matches.slice(start, start + this.listPageSize).entries()) {\n const current = start + offset === active;\n const marker = current ? this.theme.fg('accent', SELECTION_MARKER) : ' ';\n const label = row.name || EMPTY_NAME;\n const name = current ? this.theme.bold(this.theme.fg('accent', label)) : this.theme.fg('text', label);\n const meta = this.theme.fg('dim', pathTail(row.relativePath, Math.max(0, width - META_INDENT.length)));\n lines.push(fit(`${marker} ${name}`, width));\n lines.push(fit(`${META_INDENT}${meta}`, width));\n }\n return lines.slice(0, height);\n }\n\n private renderDetail(width: number, height: number): string[] {\n const row = this.cursorRow();\n if (!row) {\n this.detailTotal = 0;\n this.detailPageSize = Math.max(DEFAULT_PAGE_SIZE, height);\n this.detailOffset = 0;\n const lines = [this.theme.bold(this.theme.fg('accent', 'WORKFLOW DETAIL')), ''];\n appendWrapped(\n lines,\n this.rows.length === 0 ? EMPTY_MESSAGE : 'No workflow matches this filter.',\n width,\n 'text',\n this.theme,\n );\n return lines.slice(0, height);\n }\n\n const header = [\n rightAligned(\n this.theme.bold(this.theme.fg('accent', `INSPECTING ${row.name || EMPTY_NAME}`)),\n this.theme.fg('dim', pathTail(row.relativePath, Math.max(0, Math.floor(width / 2)))),\n width,\n ),\n ];\n if (row.description) appendWrapped(header, row.description, width, 'text', this.theme);\n if (row.tags.length > 0) appendWrapped(header, row.tags.join(' · '), width, 'dim', this.theme);\n header.push(tabStrip(this.tab, width, this.theme), '');\n\n const body = workflowDetailLines(this.detailFor(row), this.tab, width, this.theme);\n this.detailPageSize = Math.max(0, height - header.length);\n this.detailTotal = body.length;\n this.detailOffset = Math.min(this.detailOffset, Math.max(0, body.length - this.detailPageSize));\n return [...header, ...body.slice(this.detailOffset, this.detailOffset + this.detailPageSize)].slice(0, height);\n }\n}\n\nexport async function openWorkflowCatalogOverlay(\n ctx: ExtensionContext,\n rows: readonly WorkflowCatalogRow[],\n options: WorkflowCatalogOptions,\n): Promise<void> {\n await ctx.ui.custom<undefined>(\n (tui, theme, _keybindings, done) => new WorkflowCatalogComponent(tui, theme, rows, done, options),\n DOOM_FULLSCREEN_UI_OPTIONS,\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ let _earendil_works_pi_tui = require("@earendil-works/pi-tui");
2
+ //#region src/tui/workflow/workflowFinishedMessage.ts
3
+ const WORKFLOW_FINISHED_MESSAGE = "workflow-run-finished";
4
+ const COMPLETED_STAGE = "completed";
5
+ const HELD_STAGES = /* @__PURE__ */ new Set([
6
+ "stopped",
7
+ "paused",
8
+ "cancelled"
9
+ ]);
10
+ function statusIcon(stage, theme) {
11
+ if (stage === COMPLETED_STAGE) return theme.fg("success", "✔");
12
+ if (HELD_STAGES.has(stage)) return theme.fg("warning", "■");
13
+ return theme.fg("error", "✖");
14
+ }
15
+ function runLine(run, theme) {
16
+ const separator = ` ${theme.fg("dim", "·")} `;
17
+ const identity = [run.runKey, run.workspace].filter(Boolean).join("/");
18
+ const parts = [theme.fg("dim", identity), theme.fg("dim", run.stage)];
19
+ if (run.workflowId) parts.unshift(theme.bold(run.workflowId));
20
+ let text = `${statusIcon(run.stage, theme)} ${parts.join(separator)}`;
21
+ if (run.failedJob) text += `\n ${theme.fg("dim", `⎿ failed job: ${run.failedJob}`)}`;
22
+ if (run.error) text += `\n ${theme.fg("dim", `⎿ ${run.error}`)}`;
23
+ return text;
24
+ }
25
+ /**
26
+ * Exported for tests: the rendered string before it is wrapped in a `Text`
27
+ * component, so the formatting is assertable without a terminal.
28
+ */
29
+ function renderWorkflowFinished(runs, theme) {
30
+ return runs.map((run) => runLine(run, theme)).join("\n");
31
+ }
32
+ function isWorkflowFinishedRuns(value) {
33
+ if (!Array.isArray(value) || value.length === 0) return false;
34
+ return value.every((entry) => typeof entry === "object" && entry !== null && typeof entry.runKey === "string" && typeof entry.stage === "string");
35
+ }
36
+ function createWorkflowFinishedRenderer() {
37
+ return [WORKFLOW_FINISHED_MESSAGE, (message, _options, theme) => {
38
+ const content = typeof message.content === "string" ? message.content : JSON.stringify(message.content);
39
+ const runs = message.details?.runs;
40
+ if (!isWorkflowFinishedRuns(runs)) return new _earendil_works_pi_tui.Text(content, 0, 0);
41
+ return new _earendil_works_pi_tui.Text(renderWorkflowFinished(runs, theme), 0, 0);
42
+ }];
43
+ }
44
+ //#endregion
45
+ exports.WORKFLOW_FINISHED_MESSAGE = WORKFLOW_FINISHED_MESSAGE;
46
+ exports.createWorkflowFinishedRenderer = createWorkflowFinishedRenderer;
47
+ exports.isWorkflowFinishedRuns = isWorkflowFinishedRuns;
48
+ exports.renderWorkflowFinished = renderWorkflowFinished;
49
+
50
+ //# sourceMappingURL=workflowFinishedMessage.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflowFinishedMessage.cjs","names":["Text"],"sources":["../../../../src/tui/workflow/workflowFinishedMessage.ts"],"sourcesContent":["/**\n * Renders the `workflow-run-finished` custom message: one line per run that\n * reached a terminal state, rather than the host's default block of the\n * `[workflow-run-finished]` label above raw markdown.\n *\n * The same shape `@agimon-ai/doompi-team` gives a slash launch: a status glyph,\n * the run's identity, its outcome, and anything that went wrong indented under\n * it. A finished run is read at a glance in a transcript that is mostly about\n * something else, so it earns a line, not a card.\n *\n * DESIGN PATTERNS:\n * - A message with no `details` renders its content verbatim. That is a\n * transcript entry written before the field existed, and re-deriving it by\n * parsing the summary back out of markdown is exactly the liability\n * `completionNotice.ts` in the team package refused to port\n * - The full summary is still the message's `content`, which is what the model\n * reads and what `deliverAs: 'steer'` carries. This changes what a person\n * sees, never what the agent is told\n */\n\nimport type { ExtensionAPI, Theme } from '@earendil-works/pi-coding-agent';\nimport { type Component, Text } from '@earendil-works/pi-tui';\n\nexport const WORKFLOW_FINISHED_MESSAGE = 'workflow-run-finished';\n\n/** One finished run, as the extension records it on the message. */\nexport interface WorkflowFinishedRun {\n runKey: string;\n workspace: string;\n stage: string;\n workflowId?: string;\n failedJob?: string;\n error?: string;\n}\n\nexport interface WorkflowFinishedDetails {\n /** Kept for readers that already index runs by id; the lines come from `runs`. */\n runIds?: string[];\n runs?: WorkflowFinishedRun[];\n}\n\nconst COMPLETED_STAGE = 'completed';\nconst HELD_STAGES = new Set(['stopped', 'paused', 'cancelled']);\n\nfunction statusIcon(stage: string, theme: Theme): string {\n if (stage === COMPLETED_STAGE) return theme.fg('success', '✔');\n // Held is not failed: the run went nowhere wrong, it just stopped short.\n if (HELD_STAGES.has(stage)) return theme.fg('warning', '■');\n return theme.fg('error', '✖');\n}\n\nfunction runLine(run: WorkflowFinishedRun, theme: Theme): string {\n const separator = ` ${theme.fg('dim', '·')} `;\n const identity = [run.runKey, run.workspace].filter(Boolean).join('/');\n const parts = [theme.fg('dim', identity), theme.fg('dim', run.stage)];\n if (run.workflowId) parts.unshift(theme.bold(run.workflowId));\n let text = `${statusIcon(run.stage, theme)} ${parts.join(separator)}`;\n if (run.failedJob) text += `\\n ${theme.fg('dim', `⎿ failed job: ${run.failedJob}`)}`;\n if (run.error) text += `\\n ${theme.fg('dim', `⎿ ${run.error}`)}`;\n return text;\n}\n\n/**\n * Exported for tests: the rendered string before it is wrapped in a `Text`\n * component, so the formatting is assertable without a terminal.\n */\nexport function renderWorkflowFinished(runs: readonly WorkflowFinishedRun[], theme: Theme): string {\n return runs.map((run) => runLine(run, theme)).join('\\n');\n}\n\nexport function isWorkflowFinishedRuns(value: unknown): value is WorkflowFinishedRun[] {\n if (!Array.isArray(value) || value.length === 0) return false;\n return value.every(\n (entry) =>\n typeof entry === 'object' &&\n entry !== null &&\n typeof (entry as WorkflowFinishedRun).runKey === 'string' &&\n typeof (entry as WorkflowFinishedRun).stage === 'string',\n );\n}\n\nexport function createWorkflowFinishedRenderer(): readonly [...Parameters<ExtensionAPI['registerMessageRenderer']>] {\n return [\n WORKFLOW_FINISHED_MESSAGE,\n (message, _options, theme: Theme): Component => {\n const content = typeof message.content === 'string' ? message.content : JSON.stringify(message.content);\n const runs = (message.details as WorkflowFinishedDetails | undefined)?.runs;\n if (!isWorkflowFinishedRuns(runs)) return new Text(content, 0, 0);\n return new Text(renderWorkflowFinished(runs, theme), 0, 0);\n },\n ];\n}\n"],"mappings":";;AAuBA,MAAa,4BAA4B;AAkBzC,MAAM,kBAAkB;AACxB,MAAM,8BAAc,IAAI,IAAI;CAAC;CAAW;CAAU;AAAW,CAAC;AAE9D,SAAS,WAAW,OAAe,OAAsB;CACvD,IAAI,UAAU,iBAAiB,OAAO,MAAM,GAAG,WAAW,GAAG;CAE7D,IAAI,YAAY,IAAI,KAAK,GAAG,OAAO,MAAM,GAAG,WAAW,GAAG;CAC1D,OAAO,MAAM,GAAG,SAAS,GAAG;AAC9B;AAEA,SAAS,QAAQ,KAA0B,OAAsB;CAC/D,MAAM,YAAY,IAAI,MAAM,GAAG,OAAO,GAAG,EAAE;CAC3C,MAAM,WAAW,CAAC,IAAI,QAAQ,IAAI,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CACrE,MAAM,QAAQ,CAAC,MAAM,GAAG,OAAO,QAAQ,GAAG,MAAM,GAAG,OAAO,IAAI,KAAK,CAAC;CACpE,IAAI,IAAI,YAAY,MAAM,QAAQ,MAAM,KAAK,IAAI,UAAU,CAAC;CAC5D,IAAI,OAAO,GAAG,WAAW,IAAI,OAAO,KAAK,EAAE,GAAG,MAAM,KAAK,SAAS;CAClE,IAAI,IAAI,WAAW,QAAQ,OAAO,MAAM,GAAG,OAAO,kBAAkB,IAAI,WAAW;CACnF,IAAI,IAAI,OAAO,QAAQ,OAAO,MAAM,GAAG,OAAO,MAAM,IAAI,OAAO;CAC/D,OAAO;AACT;;;;;AAMA,SAAgB,uBAAuB,MAAsC,OAAsB;CACjG,OAAO,KAAK,KAAK,QAAQ,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;AACzD;AAEA,SAAgB,uBAAuB,OAAgD;CACrF,IAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,GAAG,OAAO;CACxD,OAAO,MAAM,OACV,UACC,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAA8B,WAAW,YACjD,OAAQ,MAA8B,UAAU,QACpD;AACF;AAEA,SAAgB,iCAAoG;CAClH,OAAO,CACL,4BACC,SAAS,UAAU,UAA4B;EAC9C,MAAM,UAAU,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,KAAK,UAAU,QAAQ,OAAO;EACtG,MAAM,OAAQ,QAAQ,SAAiD;EACvE,IAAI,CAAC,uBAAuB,IAAI,GAAG,OAAO,IAAIA,uBAAAA,KAAK,SAAS,GAAG,CAAC;EAChE,OAAO,IAAIA,uBAAAA,KAAK,uBAAuB,MAAM,KAAK,GAAG,GAAG,CAAC;CAC3D,CACF;AACF"}
@@ -0,0 +1,47 @@
1
+ import { Text } from "@earendil-works/pi-tui";
2
+ //#region src/tui/workflow/workflowFinishedMessage.ts
3
+ const WORKFLOW_FINISHED_MESSAGE = "workflow-run-finished";
4
+ const COMPLETED_STAGE = "completed";
5
+ const HELD_STAGES = /* @__PURE__ */ new Set([
6
+ "stopped",
7
+ "paused",
8
+ "cancelled"
9
+ ]);
10
+ function statusIcon(stage, theme) {
11
+ if (stage === COMPLETED_STAGE) return theme.fg("success", "✔");
12
+ if (HELD_STAGES.has(stage)) return theme.fg("warning", "■");
13
+ return theme.fg("error", "✖");
14
+ }
15
+ function runLine(run, theme) {
16
+ const separator = ` ${theme.fg("dim", "·")} `;
17
+ const identity = [run.runKey, run.workspace].filter(Boolean).join("/");
18
+ const parts = [theme.fg("dim", identity), theme.fg("dim", run.stage)];
19
+ if (run.workflowId) parts.unshift(theme.bold(run.workflowId));
20
+ let text = `${statusIcon(run.stage, theme)} ${parts.join(separator)}`;
21
+ if (run.failedJob) text += `\n ${theme.fg("dim", `⎿ failed job: ${run.failedJob}`)}`;
22
+ if (run.error) text += `\n ${theme.fg("dim", `⎿ ${run.error}`)}`;
23
+ return text;
24
+ }
25
+ /**
26
+ * Exported for tests: the rendered string before it is wrapped in a `Text`
27
+ * component, so the formatting is assertable without a terminal.
28
+ */
29
+ function renderWorkflowFinished(runs, theme) {
30
+ return runs.map((run) => runLine(run, theme)).join("\n");
31
+ }
32
+ function isWorkflowFinishedRuns(value) {
33
+ if (!Array.isArray(value) || value.length === 0) return false;
34
+ return value.every((entry) => typeof entry === "object" && entry !== null && typeof entry.runKey === "string" && typeof entry.stage === "string");
35
+ }
36
+ function createWorkflowFinishedRenderer() {
37
+ return [WORKFLOW_FINISHED_MESSAGE, (message, _options, theme) => {
38
+ const content = typeof message.content === "string" ? message.content : JSON.stringify(message.content);
39
+ const runs = message.details?.runs;
40
+ if (!isWorkflowFinishedRuns(runs)) return new Text(content, 0, 0);
41
+ return new Text(renderWorkflowFinished(runs, theme), 0, 0);
42
+ }];
43
+ }
44
+ //#endregion
45
+ export { WORKFLOW_FINISHED_MESSAGE, createWorkflowFinishedRenderer, isWorkflowFinishedRuns, renderWorkflowFinished };
46
+
47
+ //# sourceMappingURL=workflowFinishedMessage.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflowFinishedMessage.mjs","names":[],"sources":["../../../../src/tui/workflow/workflowFinishedMessage.ts"],"sourcesContent":["/**\n * Renders the `workflow-run-finished` custom message: one line per run that\n * reached a terminal state, rather than the host's default block of the\n * `[workflow-run-finished]` label above raw markdown.\n *\n * The same shape `@agimon-ai/doompi-team` gives a slash launch: a status glyph,\n * the run's identity, its outcome, and anything that went wrong indented under\n * it. A finished run is read at a glance in a transcript that is mostly about\n * something else, so it earns a line, not a card.\n *\n * DESIGN PATTERNS:\n * - A message with no `details` renders its content verbatim. That is a\n * transcript entry written before the field existed, and re-deriving it by\n * parsing the summary back out of markdown is exactly the liability\n * `completionNotice.ts` in the team package refused to port\n * - The full summary is still the message's `content`, which is what the model\n * reads and what `deliverAs: 'steer'` carries. This changes what a person\n * sees, never what the agent is told\n */\n\nimport type { ExtensionAPI, Theme } from '@earendil-works/pi-coding-agent';\nimport { type Component, Text } from '@earendil-works/pi-tui';\n\nexport const WORKFLOW_FINISHED_MESSAGE = 'workflow-run-finished';\n\n/** One finished run, as the extension records it on the message. */\nexport interface WorkflowFinishedRun {\n runKey: string;\n workspace: string;\n stage: string;\n workflowId?: string;\n failedJob?: string;\n error?: string;\n}\n\nexport interface WorkflowFinishedDetails {\n /** Kept for readers that already index runs by id; the lines come from `runs`. */\n runIds?: string[];\n runs?: WorkflowFinishedRun[];\n}\n\nconst COMPLETED_STAGE = 'completed';\nconst HELD_STAGES = new Set(['stopped', 'paused', 'cancelled']);\n\nfunction statusIcon(stage: string, theme: Theme): string {\n if (stage === COMPLETED_STAGE) return theme.fg('success', '✔');\n // Held is not failed: the run went nowhere wrong, it just stopped short.\n if (HELD_STAGES.has(stage)) return theme.fg('warning', '■');\n return theme.fg('error', '✖');\n}\n\nfunction runLine(run: WorkflowFinishedRun, theme: Theme): string {\n const separator = ` ${theme.fg('dim', '·')} `;\n const identity = [run.runKey, run.workspace].filter(Boolean).join('/');\n const parts = [theme.fg('dim', identity), theme.fg('dim', run.stage)];\n if (run.workflowId) parts.unshift(theme.bold(run.workflowId));\n let text = `${statusIcon(run.stage, theme)} ${parts.join(separator)}`;\n if (run.failedJob) text += `\\n ${theme.fg('dim', `⎿ failed job: ${run.failedJob}`)}`;\n if (run.error) text += `\\n ${theme.fg('dim', `⎿ ${run.error}`)}`;\n return text;\n}\n\n/**\n * Exported for tests: the rendered string before it is wrapped in a `Text`\n * component, so the formatting is assertable without a terminal.\n */\nexport function renderWorkflowFinished(runs: readonly WorkflowFinishedRun[], theme: Theme): string {\n return runs.map((run) => runLine(run, theme)).join('\\n');\n}\n\nexport function isWorkflowFinishedRuns(value: unknown): value is WorkflowFinishedRun[] {\n if (!Array.isArray(value) || value.length === 0) return false;\n return value.every(\n (entry) =>\n typeof entry === 'object' &&\n entry !== null &&\n typeof (entry as WorkflowFinishedRun).runKey === 'string' &&\n typeof (entry as WorkflowFinishedRun).stage === 'string',\n );\n}\n\nexport function createWorkflowFinishedRenderer(): readonly [...Parameters<ExtensionAPI['registerMessageRenderer']>] {\n return [\n WORKFLOW_FINISHED_MESSAGE,\n (message, _options, theme: Theme): Component => {\n const content = typeof message.content === 'string' ? message.content : JSON.stringify(message.content);\n const runs = (message.details as WorkflowFinishedDetails | undefined)?.runs;\n if (!isWorkflowFinishedRuns(runs)) return new Text(content, 0, 0);\n return new Text(renderWorkflowFinished(runs, theme), 0, 0);\n },\n ];\n}\n"],"mappings":";;AAuBA,MAAa,4BAA4B;AAkBzC,MAAM,kBAAkB;AACxB,MAAM,8BAAc,IAAI,IAAI;CAAC;CAAW;CAAU;AAAW,CAAC;AAE9D,SAAS,WAAW,OAAe,OAAsB;CACvD,IAAI,UAAU,iBAAiB,OAAO,MAAM,GAAG,WAAW,GAAG;CAE7D,IAAI,YAAY,IAAI,KAAK,GAAG,OAAO,MAAM,GAAG,WAAW,GAAG;CAC1D,OAAO,MAAM,GAAG,SAAS,GAAG;AAC9B;AAEA,SAAS,QAAQ,KAA0B,OAAsB;CAC/D,MAAM,YAAY,IAAI,MAAM,GAAG,OAAO,GAAG,EAAE;CAC3C,MAAM,WAAW,CAAC,IAAI,QAAQ,IAAI,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CACrE,MAAM,QAAQ,CAAC,MAAM,GAAG,OAAO,QAAQ,GAAG,MAAM,GAAG,OAAO,IAAI,KAAK,CAAC;CACpE,IAAI,IAAI,YAAY,MAAM,QAAQ,MAAM,KAAK,IAAI,UAAU,CAAC;CAC5D,IAAI,OAAO,GAAG,WAAW,IAAI,OAAO,KAAK,EAAE,GAAG,MAAM,KAAK,SAAS;CAClE,IAAI,IAAI,WAAW,QAAQ,OAAO,MAAM,GAAG,OAAO,kBAAkB,IAAI,WAAW;CACnF,IAAI,IAAI,OAAO,QAAQ,OAAO,MAAM,GAAG,OAAO,MAAM,IAAI,OAAO;CAC/D,OAAO;AACT;;;;;AAMA,SAAgB,uBAAuB,MAAsC,OAAsB;CACjG,OAAO,KAAK,KAAK,QAAQ,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;AACzD;AAEA,SAAgB,uBAAuB,OAAgD;CACrF,IAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,GAAG,OAAO;CACxD,OAAO,MAAM,OACV,UACC,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAA8B,WAAW,YACjD,OAAQ,MAA8B,UAAU,QACpD;AACF;AAEA,SAAgB,iCAAoG;CAClH,OAAO,CACL,4BACC,SAAS,UAAU,UAA4B;EAC9C,MAAM,UAAU,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,KAAK,UAAU,QAAQ,OAAO;EACtG,MAAM,OAAQ,QAAQ,SAAiD;EACvE,IAAI,CAAC,uBAAuB,IAAI,GAAG,OAAO,IAAI,KAAK,SAAS,GAAG,CAAC;EAChE,OAAO,IAAI,KAAK,uBAAuB,MAAM,KAAK,GAAG,GAAG,CAAC;CAC3D,CACF;AACF"}