@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,139 @@
1
+ import { DOOM_FULLSCREEN_UI_OPTIONS, DOOM_OVERLAY_ACCENT, DoomOverlay } from "./doomOverlay.mjs";
2
+ import { fit, isControlInput, rightAligned } from "./overlayText.mjs";
3
+ import { matchesKey } from "@earendil-works/pi-tui";
4
+ DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions;
5
+ const CHOICE_TITLE = "WORKFLOW PROMPT";
6
+ const CHOOSE_LABEL = "CHOOSE";
7
+ const VALUE_LABEL = "VALUE";
8
+ const DEFAULT_MARKER = "default";
9
+ const EMPTY_CHOICES = "No options are available.";
10
+ const CHOICE_HINTS = [
11
+ ["↑↓", "select"],
12
+ ["enter", "confirm"],
13
+ ["esc", "cancel"]
14
+ ];
15
+ const INPUT_HINTS = [
16
+ ["type", "edit"],
17
+ ["enter", "confirm"],
18
+ ["ctrl+u", "clear"],
19
+ ["esc", "cancel"]
20
+ ];
21
+ const KEY_CLEAR = "";
22
+ /** Rows the heading and its spacer take before the first option. */
23
+ const HEADING_ROWS = 2;
24
+ const DIM = "dim";
25
+ const ACCENT = "accent";
26
+ const SELECTED_BG = "selectedBg";
27
+ const ROW_BG = "userMessageBg";
28
+ var WorkflowChoiceComponent = class extends DoomOverlay {
29
+ options;
30
+ done;
31
+ selected;
32
+ constructor(tui, theme, options, done) {
33
+ super(tui, theme);
34
+ this.options = options;
35
+ this.done = done;
36
+ this.selected = Math.max(0, options.preselect ? options.choices.indexOf(options.preselect) : 0);
37
+ }
38
+ handleInput(data) {
39
+ if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c")) {
40
+ this.done(void 0);
41
+ return;
42
+ }
43
+ if (matchesKey(data, "enter")) {
44
+ const choice = this.options.choices[this.selected];
45
+ if (choice !== void 0) this.done(choice);
46
+ return;
47
+ }
48
+ const count = this.options.choices.length;
49
+ if (count === 0) return;
50
+ if (matchesKey(data, "up") || matchesKey(data, "ctrl+p")) this.selected = Math.max(0, this.selected - 1);
51
+ else if (matchesKey(data, "down") || matchesKey(data, "ctrl+n")) this.selected = Math.min(count - 1, this.selected + 1);
52
+ else return;
53
+ this.tui.requestRender();
54
+ }
55
+ getChrome() {
56
+ return {
57
+ title: CHOICE_TITLE,
58
+ accent: DOOM_OVERLAY_ACCENT,
59
+ breadcrumb: this.options.breadcrumb,
60
+ headerRight: `${this.options.choices.length} options`,
61
+ footer: "↑↓ select · enter confirm · esc cancel",
62
+ footerHints: CHOICE_HINTS,
63
+ footerRight: this.options.choices.length > 0 ? `${this.selected + 1}/${this.options.choices.length}` : "no options"
64
+ };
65
+ }
66
+ renderBody(width, height) {
67
+ const lines = [this.theme.bold(fit(this.options.title, width)), ""];
68
+ if (this.options.choices.length === 0) {
69
+ lines.push(this.theme.fg(DIM, EMPTY_CHOICES));
70
+ return lines.slice(0, height);
71
+ }
72
+ lines.push(this.theme.fg(DIM, CHOOSE_LABEL));
73
+ const capacity = Math.max(1, height - HEADING_ROWS - 1);
74
+ const start = Math.max(0, Math.min(this.selected - capacity + 1, Math.max(0, this.options.choices.length - capacity)));
75
+ for (const [offset, choice] of this.options.choices.slice(start, start + capacity).entries()) {
76
+ const current = start + offset === this.selected;
77
+ const marker = current ? this.theme.fg(ACCENT, "›") : " ";
78
+ const label = current ? this.theme.bold(choice) : choice;
79
+ const note = choice === this.options.preselect ? this.theme.fg(DIM, DEFAULT_MARKER) : "";
80
+ const background = current ? SELECTED_BG : ROW_BG;
81
+ lines.push(this.theme.bg(background, rightAligned(`${marker} ${label}`, note, width)));
82
+ }
83
+ return lines.slice(0, height);
84
+ }
85
+ };
86
+ var WorkflowInputComponent = class extends DoomOverlay {
87
+ options;
88
+ done;
89
+ draft = "";
90
+ constructor(tui, theme, options, done) {
91
+ super(tui, theme);
92
+ this.options = options;
93
+ this.done = done;
94
+ }
95
+ handleInput(data) {
96
+ if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c")) {
97
+ this.done(void 0);
98
+ return;
99
+ }
100
+ if (matchesKey(data, "enter")) {
101
+ this.done(this.draft.trim() || this.options.fallback || "");
102
+ return;
103
+ }
104
+ if (matchesKey(data, "backspace")) this.draft = this.draft.slice(0, -1);
105
+ else if (data === KEY_CLEAR) this.draft = "";
106
+ else if (!isControlInput(data)) this.draft += data;
107
+ else return;
108
+ this.tui.requestRender();
109
+ }
110
+ getChrome() {
111
+ return {
112
+ title: CHOICE_TITLE,
113
+ accent: DOOM_OVERLAY_ACCENT,
114
+ breadcrumb: this.options.breadcrumb,
115
+ headerRight: this.options.fallback ? `default ${this.options.fallback}` : "no default",
116
+ footer: "type to edit · enter confirm · ctrl+u clear · esc cancel",
117
+ footerHints: INPUT_HINTS
118
+ };
119
+ }
120
+ renderBody(width, height) {
121
+ const label = this.options.fallback ? rightAligned(this.theme.fg(DIM, VALUE_LABEL), this.theme.fg(DIM, `${DEFAULT_MARKER} ${this.options.fallback}`), width) : this.theme.fg(DIM, VALUE_LABEL);
122
+ return [
123
+ this.theme.bold(fit(this.options.title, width)),
124
+ "",
125
+ label,
126
+ this.theme.bg(SELECTED_BG, fit(` ${this.draft}█`, width))
127
+ ].slice(0, height);
128
+ }
129
+ };
130
+ async function openWorkflowChoice(ctx, options) {
131
+ return ctx.ui.custom((tui, theme, _keybindings, done) => new WorkflowChoiceComponent(tui, theme, options, done), DOOM_FULLSCREEN_UI_OPTIONS);
132
+ }
133
+ async function openWorkflowInput(ctx, options) {
134
+ return ctx.ui.custom((tui, theme, _keybindings, done) => new WorkflowInputComponent(tui, theme, options, done), DOOM_FULLSCREEN_UI_OPTIONS);
135
+ }
136
+ //#endregion
137
+ export { WorkflowChoiceComponent, WorkflowInputComponent, openWorkflowChoice, openWorkflowInput };
138
+
139
+ //# sourceMappingURL=workflowPrompt.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflowPrompt.mjs","names":[],"sources":["../../../../src/tui/workflow/workflowPrompt.ts"],"sourcesContent":["/**\n * The short prompts: pick one of a few options, or type one value.\n *\n * These were `ui.select` and `ui.input`, which meant the run manager, the runner\n * picker and every `workflow_dispatch` input rendered as native Pi widgets in the\n * middle of a flow whose other steps are framed doom overlays. Same surface for\n * all of them now, so a launch reads as one sequence rather than three styles.\n *\n * Rendering is pure, so both modes can be asserted as text without a terminal.\n */\n\nimport type { ExtensionContext, Theme } from '@earendil-works/pi-coding-agent';\nimport { matchesKey } 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 { CURSOR_BLOCK, fit, isControlInput, rightAligned, SELECTION_MARKER } from './overlayText';\n\nexport const WORKFLOW_PROMPT_OVERLAY_OPTIONS = DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions;\n\nconst CHOICE_TITLE = 'WORKFLOW PROMPT';\nconst CHOOSE_LABEL = 'CHOOSE';\nconst VALUE_LABEL = 'VALUE';\nconst DEFAULT_MARKER = 'default';\nconst EMPTY_CHOICES = 'No options are available.';\nconst CHOICE_HINTS: readonly (readonly [string, string])[] = [\n ['↑↓', 'select'],\n ['enter', 'confirm'],\n ['esc', 'cancel'],\n];\nconst INPUT_HINTS: readonly (readonly [string, string])[] = [\n ['type', 'edit'],\n ['enter', 'confirm'],\n ['ctrl+u', 'clear'],\n ['esc', 'cancel'],\n];\nconst KEY_CLEAR = '\\x15';\n/** Rows the heading and its spacer take before the first option. */\nconst HEADING_ROWS = 2;\n\n/** Neither palette name is exported, so take both from the theme's methods. */\ntype ThemeBg = Parameters<Theme['bg']>[0];\ntype ThemeColor = Parameters<Theme['fg']>[0];\n\nconst DIM: ThemeColor = 'dim';\nconst ACCENT: ThemeColor = 'accent';\nconst SELECTED_BG: ThemeBg = 'selectedBg';\nconst ROW_BG: ThemeBg = 'userMessageBg';\n\nexport interface WorkflowChoiceOptions {\n title: string;\n breadcrumb: string;\n choices: readonly string[];\n /** Marked `default` in the list and pre-selected. */\n preselect?: string;\n}\n\nexport interface WorkflowInputOptions {\n title: string;\n breadcrumb: string;\n /** Committed when the field is left empty, and shown beside the label. */\n fallback?: string;\n}\n\nexport class WorkflowChoiceComponent extends DoomOverlay {\n private selected: number;\n\n constructor(\n tui: DoomOverlayTui,\n theme: Theme,\n private readonly options: WorkflowChoiceOptions,\n private readonly done: (choice: string | undefined) => void,\n ) {\n super(tui, theme);\n this.selected = Math.max(0, options.preselect ? options.choices.indexOf(options.preselect) : 0);\n }\n\n handleInput(data: string): void {\n if (matchesKey(data, 'escape') || matchesKey(data, 'ctrl+c')) {\n this.done(undefined);\n return;\n }\n if (matchesKey(data, 'enter')) {\n const choice = this.options.choices[this.selected];\n if (choice !== undefined) this.done(choice);\n return;\n }\n const count = this.options.choices.length;\n if (count === 0) return;\n if (matchesKey(data, 'up') || matchesKey(data, 'ctrl+p')) this.selected = Math.max(0, this.selected - 1);\n else if (matchesKey(data, 'down') || matchesKey(data, 'ctrl+n'))\n this.selected = Math.min(count - 1, this.selected + 1);\n else return;\n this.tui.requestRender();\n }\n\n protected getChrome(): DoomOverlayChrome {\n return {\n title: CHOICE_TITLE,\n accent: DOOM_OVERLAY_ACCENT,\n breadcrumb: this.options.breadcrumb,\n headerRight: `${this.options.choices.length} options`,\n footer: '↑↓ select · enter confirm · esc cancel',\n footerHints: CHOICE_HINTS,\n footerRight:\n this.options.choices.length > 0 ? `${this.selected + 1}/${this.options.choices.length}` : 'no options',\n };\n }\n\n protected renderBody(width: number, height: number): string[] {\n const lines = [this.theme.bold(fit(this.options.title, width)), ''];\n if (this.options.choices.length === 0) {\n lines.push(this.theme.fg(DIM, EMPTY_CHOICES));\n return lines.slice(0, height);\n }\n\n lines.push(this.theme.fg(DIM, CHOOSE_LABEL));\n // The window follows the cursor, so a list longer than the body still scrolls.\n const capacity = Math.max(1, height - HEADING_ROWS - 1);\n const start = Math.max(\n 0,\n Math.min(this.selected - capacity + 1, Math.max(0, this.options.choices.length - capacity)),\n );\n for (const [offset, choice] of this.options.choices.slice(start, start + capacity).entries()) {\n const current = start + offset === this.selected;\n const marker = current ? this.theme.fg(ACCENT, SELECTION_MARKER) : ' ';\n const label = current ? this.theme.bold(choice) : choice;\n const note = choice === this.options.preselect ? this.theme.fg(DIM, DEFAULT_MARKER) : '';\n const background: ThemeBg = current ? SELECTED_BG : ROW_BG;\n lines.push(this.theme.bg(background, rightAligned(`${marker} ${label}`, note, width)));\n }\n return lines.slice(0, height);\n }\n}\n\nexport class WorkflowInputComponent extends DoomOverlay {\n private draft = '';\n\n constructor(\n tui: DoomOverlayTui,\n theme: Theme,\n private readonly options: WorkflowInputOptions,\n private readonly done: (value: string | undefined) => void,\n ) {\n super(tui, theme);\n }\n\n handleInput(data: string): void {\n if (matchesKey(data, 'escape') || matchesKey(data, 'ctrl+c')) {\n this.done(undefined);\n return;\n }\n if (matchesKey(data, 'enter')) {\n // An empty field commits the fallback rather than an empty string: the\n // caller offered a default, and pressing enter is how you accept it.\n this.done(this.draft.trim() || this.options.fallback || '');\n return;\n }\n if (matchesKey(data, 'backspace')) this.draft = this.draft.slice(0, -1);\n else if (data === KEY_CLEAR) this.draft = '';\n else if (!isControlInput(data)) this.draft += data;\n else return;\n this.tui.requestRender();\n }\n\n protected getChrome(): DoomOverlayChrome {\n return {\n title: CHOICE_TITLE,\n accent: DOOM_OVERLAY_ACCENT,\n breadcrumb: this.options.breadcrumb,\n headerRight: this.options.fallback ? `default ${this.options.fallback}` : 'no default',\n footer: 'type to edit · enter confirm · ctrl+u clear · esc cancel',\n footerHints: INPUT_HINTS,\n };\n }\n\n protected renderBody(width: number, height: number): string[] {\n const label = this.options.fallback\n ? rightAligned(\n this.theme.fg(DIM, VALUE_LABEL),\n this.theme.fg(DIM, `${DEFAULT_MARKER} ${this.options.fallback}`),\n width,\n )\n : this.theme.fg(DIM, VALUE_LABEL);\n return [\n this.theme.bold(fit(this.options.title, width)),\n '',\n label,\n this.theme.bg(SELECTED_BG, fit(` ${this.draft}${CURSOR_BLOCK}`, width)),\n ].slice(0, height);\n }\n}\n\nexport async function openWorkflowChoice(\n ctx: ExtensionContext,\n options: WorkflowChoiceOptions,\n): Promise<string | undefined> {\n return ctx.ui.custom<string | undefined>(\n (tui, theme, _keybindings, done) => new WorkflowChoiceComponent(tui, theme, options, done),\n DOOM_FULLSCREEN_UI_OPTIONS,\n );\n}\n\nexport async function openWorkflowInput(\n ctx: ExtensionContext,\n options: WorkflowInputOptions,\n): Promise<string | undefined> {\n return ctx.ui.custom<string | undefined>(\n (tui, theme, _keybindings, done) => new WorkflowInputComponent(tui, theme, options, done),\n DOOM_FULLSCREEN_UI_OPTIONS,\n );\n}\n"],"mappings":";;;AAuB+C,2BAA2B;AAE1E,MAAM,eAAe;AACrB,MAAM,eAAe;AACrB,MAAM,cAAc;AACpB,MAAM,iBAAiB;AACvB,MAAM,gBAAgB;AACtB,MAAM,eAAuD;CAC3D,CAAC,MAAM,QAAQ;CACf,CAAC,SAAS,SAAS;CACnB,CAAC,OAAO,QAAQ;AAClB;AACA,MAAM,cAAsD;CAC1D,CAAC,QAAQ,MAAM;CACf,CAAC,SAAS,SAAS;CACnB,CAAC,UAAU,OAAO;CAClB,CAAC,OAAO,QAAQ;AAClB;AACA,MAAM,YAAY;;AAElB,MAAM,eAAe;AAMrB,MAAM,MAAkB;AACxB,MAAM,SAAqB;AAC3B,MAAM,cAAuB;AAC7B,MAAM,SAAkB;AAiBxB,IAAa,0BAAb,cAA6C,YAAY;CAMpC;CACA;CANnB;CAEA,YACE,KACA,OACA,SACA,MACA;EACA,MAAM,KAAK,KAAK;EAHC,KAAA,UAAA;EACA,KAAA,OAAA;EAGjB,KAAK,WAAW,KAAK,IAAI,GAAG,QAAQ,YAAY,QAAQ,QAAQ,QAAQ,QAAQ,SAAS,IAAI,CAAC;CAChG;CAEA,YAAY,MAAoB;EAC9B,IAAI,WAAW,MAAM,QAAQ,KAAK,WAAW,MAAM,QAAQ,GAAG;GAC5D,KAAK,KAAK,KAAA,CAAS;GACnB;EACF;EACA,IAAI,WAAW,MAAM,OAAO,GAAG;GAC7B,MAAM,SAAS,KAAK,QAAQ,QAAQ,KAAK;GACzC,IAAI,WAAW,KAAA,GAAW,KAAK,KAAK,MAAM;GAC1C;EACF;EACA,MAAM,QAAQ,KAAK,QAAQ,QAAQ;EACnC,IAAI,UAAU,GAAG;EACjB,IAAI,WAAW,MAAM,IAAI,KAAK,WAAW,MAAM,QAAQ,GAAG,KAAK,WAAW,KAAK,IAAI,GAAG,KAAK,WAAW,CAAC;OAClG,IAAI,WAAW,MAAM,MAAM,KAAK,WAAW,MAAM,QAAQ,GAC5D,KAAK,WAAW,KAAK,IAAI,QAAQ,GAAG,KAAK,WAAW,CAAC;OAClD;EACL,KAAK,IAAI,cAAc;CACzB;CAEA,YAAyC;EACvC,OAAO;GACL,OAAO;GACP,QAAQ;GACR,YAAY,KAAK,QAAQ;GACzB,aAAa,GAAG,KAAK,QAAQ,QAAQ,OAAO;GAC5C,QAAQ;GACR,aAAa;GACb,aACE,KAAK,QAAQ,QAAQ,SAAS,IAAI,GAAG,KAAK,WAAW,EAAE,GAAG,KAAK,QAAQ,QAAQ,WAAW;EAC9F;CACF;CAEA,WAAqB,OAAe,QAA0B;EAC5D,MAAM,QAAQ,CAAC,KAAK,MAAM,KAAK,IAAI,KAAK,QAAQ,OAAO,KAAK,CAAC,GAAG,EAAE;EAClE,IAAI,KAAK,QAAQ,QAAQ,WAAW,GAAG;GACrC,MAAM,KAAK,KAAK,MAAM,GAAG,KAAK,aAAa,CAAC;GAC5C,OAAO,MAAM,MAAM,GAAG,MAAM;EAC9B;EAEA,MAAM,KAAK,KAAK,MAAM,GAAG,KAAK,YAAY,CAAC;EAE3C,MAAM,WAAW,KAAK,IAAI,GAAG,SAAS,eAAe,CAAC;EACtD,MAAM,QAAQ,KAAK,IACjB,GACA,KAAK,IAAI,KAAK,WAAW,WAAW,GAAG,KAAK,IAAI,GAAG,KAAK,QAAQ,QAAQ,SAAS,QAAQ,CAAC,CAC5F;EACA,KAAK,MAAM,CAAC,QAAQ,WAAW,KAAK,QAAQ,QAAQ,MAAM,OAAO,QAAQ,QAAQ,CAAC,CAAC,QAAQ,GAAG;GAC5F,MAAM,UAAU,QAAQ,WAAW,KAAK;GACxC,MAAM,SAAS,UAAU,KAAK,MAAM,GAAG,QAAA,GAAwB,IAAI;GACnE,MAAM,QAAQ,UAAU,KAAK,MAAM,KAAK,MAAM,IAAI;GAClD,MAAM,OAAO,WAAW,KAAK,QAAQ,YAAY,KAAK,MAAM,GAAG,KAAK,cAAc,IAAI;GACtF,MAAM,aAAsB,UAAU,cAAc;GACpD,MAAM,KAAK,KAAK,MAAM,GAAG,YAAY,aAAa,GAAG,OAAO,GAAG,SAAS,MAAM,KAAK,CAAC,CAAC;EACvF;EACA,OAAO,MAAM,MAAM,GAAG,MAAM;CAC9B;AACF;AAEA,IAAa,yBAAb,cAA4C,YAAY;CAMnC;CACA;CANnB,QAAgB;CAEhB,YACE,KACA,OACA,SACA,MACA;EACA,MAAM,KAAK,KAAK;EAHC,KAAA,UAAA;EACA,KAAA,OAAA;CAGnB;CAEA,YAAY,MAAoB;EAC9B,IAAI,WAAW,MAAM,QAAQ,KAAK,WAAW,MAAM,QAAQ,GAAG;GAC5D,KAAK,KAAK,KAAA,CAAS;GACnB;EACF;EACA,IAAI,WAAW,MAAM,OAAO,GAAG;GAG7B,KAAK,KAAK,KAAK,MAAM,KAAK,KAAK,KAAK,QAAQ,YAAY,EAAE;GAC1D;EACF;EACA,IAAI,WAAW,MAAM,WAAW,GAAG,KAAK,QAAQ,KAAK,MAAM,MAAM,GAAG,EAAE;OACjE,IAAI,SAAS,WAAW,KAAK,QAAQ;OACrC,IAAI,CAAC,eAAe,IAAI,GAAG,KAAK,SAAS;OACzC;EACL,KAAK,IAAI,cAAc;CACzB;CAEA,YAAyC;EACvC,OAAO;GACL,OAAO;GACP,QAAQ;GACR,YAAY,KAAK,QAAQ;GACzB,aAAa,KAAK,QAAQ,WAAW,WAAW,KAAK,QAAQ,aAAa;GAC1E,QAAQ;GACR,aAAa;EACf;CACF;CAEA,WAAqB,OAAe,QAA0B;EAC5D,MAAM,QAAQ,KAAK,QAAQ,WACvB,aACE,KAAK,MAAM,GAAG,KAAK,WAAW,GAC9B,KAAK,MAAM,GAAG,KAAK,GAAG,eAAe,GAAG,KAAK,QAAQ,UAAU,GAC/D,KACF,IACA,KAAK,MAAM,GAAG,KAAK,WAAW;EAClC,OAAO;GACL,KAAK,MAAM,KAAK,IAAI,KAAK,QAAQ,OAAO,KAAK,CAAC;GAC9C;GACA;GACA,KAAK,MAAM,GAAG,aAAa,IAAI,IAAI,KAAK,UAAwB,KAAK,CAAC;EACxE,CAAC,CAAC,MAAM,GAAG,MAAM;CACnB;AACF;AAEA,eAAsB,mBACpB,KACA,SAC6B;CAC7B,OAAO,IAAI,GAAG,QACX,KAAK,OAAO,cAAc,SAAS,IAAI,wBAAwB,KAAK,OAAO,SAAS,IAAI,GACzF,0BACF;AACF;AAEA,eAAsB,kBACpB,KACA,SAC6B;CAC7B,OAAO,IAAI,GAAG,QACX,KAAK,OAAO,cAAc,SAAS,IAAI,uBAAuB,KAAK,OAAO,SAAS,IAAI,GACxF,0BACF;AACF"}
@@ -0,0 +1,95 @@
1
+ const require_doomOverlay = require("./doomOverlay.cjs");
2
+ const require_overlayText = require("./overlayText.cjs");
3
+ const require_workflowOverlay = require("./workflowOverlay.cjs");
4
+ let _earendil_works_pi_tui = require("@earendil-works/pi-tui");
5
+ //#region src/tui/workflow/workflowRunPanel.ts
6
+ const TITLE = "WORKFLOW RUN";
7
+ const VIEW_ONLY = "view only · this run is hosted natively";
8
+ const OUTPUT_HEADING = "OUTPUT · newest last";
9
+ const WAITING = "Waiting for output…";
10
+ /** A divider and its heading earn their rows only when output sits beneath them. */
11
+ const OUTPUT_CHROME_ROWS = 2;
12
+ var WorkflowRunPanelComponent = class extends require_doomOverlay.DoomOverlay {
13
+ options;
14
+ escapes = new require_workflowOverlay.DoubleEscapeDetector();
15
+ constructor(tui, theme, options) {
16
+ super(tui, theme);
17
+ this.options = options;
18
+ }
19
+ /**
20
+ * The chords are matched against the whole chunk, as Pi delivers one per key
21
+ * event. A chord buried in a coalesced burst therefore misses, which is
22
+ * acceptable now that double-Escape guarantees an exit: scanning for the bytes
23
+ * anywhere in a chunk would instead eat legitimate input, since `\x1b\x17` is
24
+ * also a valid Escape-then-ctrl+w for the run's own editor.
25
+ */
26
+ handleInput(data) {
27
+ if ((0, _earendil_works_pi_tui.matchesKey)(data, this.options.unfollowShortcut)) {
28
+ this.options.onUnfollow();
29
+ return;
30
+ }
31
+ if ((0, _earendil_works_pi_tui.matchesKey)(data, this.options.closeShortcut)) {
32
+ this.options.onClose();
33
+ return;
34
+ }
35
+ if (this.escapes.observe(data) === "close") {
36
+ this.options.flushInput();
37
+ this.options.onClose();
38
+ return;
39
+ }
40
+ this.options.sendInput(data);
41
+ }
42
+ getChrome() {
43
+ return {
44
+ title: TITLE,
45
+ accent: require_doomOverlay.DOOM_OVERLAY_ACCENT,
46
+ breadcrumb: this.options.breadcrumb,
47
+ headerRight: this.options.interactive ? this.options.label : `${this.options.label} · ${VIEW_ONLY}`,
48
+ footer: this.options.footer,
49
+ footerHints: this.options.hints,
50
+ footerRight: this.options.interactive ? "typing goes to the run" : "typing stays here"
51
+ };
52
+ }
53
+ /**
54
+ * The tree is never truncated: knowing which job is running matters more than
55
+ * seeing another line of output, so the terminal pane absorbs whatever the
56
+ * tree does not use.
57
+ */
58
+ renderBody(width, height) {
59
+ const { progress, output } = this.options.snapshot(width);
60
+ const tree = progress.slice(0, height).map((line) => require_overlayText.fit(line, width));
61
+ const spare = height - tree.length;
62
+ if (spare <= OUTPUT_CHROME_ROWS) return tree.slice(0, height);
63
+ const rows = spare - OUTPUT_CHROME_ROWS;
64
+ this.options.onViewport?.(width, rows);
65
+ const tail = output.slice(-rows).map((line) => require_overlayText.fitTerminalLine(line, width));
66
+ return [
67
+ ...tree,
68
+ "",
69
+ this.theme.fg("dim", OUTPUT_HEADING),
70
+ ...tail.length > 0 ? tail : [this.theme.fg("dim", WAITING)]
71
+ ].slice(0, height);
72
+ }
73
+ dispose() {
74
+ this.options.onDispose();
75
+ }
76
+ };
77
+ /**
78
+ * A panel whose keys cannot reach anything must never take them. Pi focuses an
79
+ * overlay on show unless told otherwise, which for a native run would swallow
80
+ * the user's typing into a run with no terminal to receive it.
81
+ */
82
+ function runPanelUiOptions(interactive) {
83
+ return {
84
+ ...require_doomOverlay.DOOM_FULLSCREEN_UI_OPTIONS,
85
+ overlayOptions: {
86
+ ...require_doomOverlay.DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions,
87
+ ...interactive ? {} : { nonCapturing: true }
88
+ }
89
+ };
90
+ }
91
+ //#endregion
92
+ exports.WorkflowRunPanelComponent = WorkflowRunPanelComponent;
93
+ exports.runPanelUiOptions = runPanelUiOptions;
94
+
95
+ //# sourceMappingURL=workflowRunPanel.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflowRunPanel.cjs","names":["DoomOverlay","DoubleEscapeDetector","matchesKey","DOOM_OVERLAY_ACCENT","fit","fitTerminalLine","DOOM_FULLSCREEN_UI_OPTIONS"],"sources":["../../../../src/tui/workflow/workflowRunPanel.ts"],"sourcesContent":["/**\n * Run panel: the live view of one run's job tree and its terminal.\n *\n * A doom overlay rather than the bare header/body/footer it used to draw, so the\n * one surface a user sits inside for minutes at a time carries the same frame,\n * breadcrumb and key legend as every other. The base class owns the chrome and\n * hands the body an exact height, which also retires the hand-rolled row\n * arithmetic that existed only to stop Pi clipping the footer.\n *\n * Key routing is the reason this is a component rather than a renderer: a\n * focused panel receives input before Pi's global dispatcher, so the view\n * controls have to be handled here or the run's TTY swallows them.\n */\n\nimport type { ExtensionContext, Theme } from '@earendil-works/pi-coding-agent';\nimport { type KeyId, matchesKey } 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 { fit, fitTerminalLine } from './overlayText';\nimport { DoubleEscapeDetector } from './workflowOverlay';\n\nconst TITLE = 'WORKFLOW RUN';\nconst VIEW_ONLY = 'view only · this run is hosted natively';\nconst OUTPUT_HEADING = 'OUTPUT · newest last';\nconst WAITING = 'Waiting for output…';\n/** A divider and its heading earn their rows only when output sits beneath them. */\nconst OUTPUT_CHROME_ROWS = 2;\n\nexport interface WorkflowRunPanelSnapshot {\n /** Job tree lines, already themed by the caller. */\n progress: string[];\n /** Recent terminal output for the running step. */\n output: string[];\n}\n\nexport interface WorkflowRunPanelOptions {\n runKey: string;\n /** Full run label for the header, e.g. `name · workspace/runKey`. */\n label: string;\n breadcrumb: string;\n /** False for a natively hosted run, which has no terminal to type into. */\n interactive: boolean;\n /** Plain-sentence footer, used when the terminal cannot fit the key caps. */\n footer: string;\n /** Key legend, which differs between a typeable panel and a view. */\n hints: readonly (readonly [string, string])[];\n /** Given the body width, because the job tree is fitted as it is built. */\n snapshot: (width: number) => WorkflowRunPanelSnapshot;\n /**\n * The columns and rows the output pane can actually show, reported on each\n * paint so a launcher that supports resizing can match the run to them.\n * Called from render, so an implementation must not do the work inline: the\n * run's geometry changes out of band and the next poll picks up the reflow.\n */\n onViewport?: (columns: number, rows: number) => void;\n /** Hand typing back to the session, leaving the panel open. */\n onUnfollow: () => void;\n onClose: () => void;\n /** Forward a keystroke to the run. */\n sendInput: (data: string) => void;\n /**\n * Send whatever is buffered before the panel goes away, or the Escape that\n * closed it dies with the batcher.\n */\n flushInput: () => void;\n unfollowShortcut: KeyId;\n closeShortcut: KeyId;\n onDispose: () => void;\n}\n\nexport class WorkflowRunPanelComponent extends DoomOverlay {\n private readonly escapes = new DoubleEscapeDetector();\n\n constructor(\n tui: DoomOverlayTui,\n theme: Theme,\n private readonly options: WorkflowRunPanelOptions,\n ) {\n super(tui, theme);\n }\n\n /**\n * The chords are matched against the whole chunk, as Pi delivers one per key\n * event. A chord buried in a coalesced burst therefore misses, which is\n * acceptable now that double-Escape guarantees an exit: scanning for the bytes\n * anywhere in a chunk would instead eat legitimate input, since `\\x1b\\x17` is\n * also a valid Escape-then-ctrl+w for the run's own editor.\n */\n handleInput(data: string): void {\n if (matchesKey(data, this.options.unfollowShortcut)) {\n this.options.onUnfollow();\n return;\n }\n if (matchesKey(data, this.options.closeShortcut)) {\n this.options.onClose();\n return;\n }\n // The failsafe. The first Escape falls through to the run, so interrupting\n // the step is as fast as it ever was; only the second one inside the window\n // is consumed.\n if (this.escapes.observe(data) === 'close') {\n this.options.flushInput();\n this.options.onClose();\n return;\n }\n this.options.sendInput(data);\n }\n\n protected getChrome(): DoomOverlayChrome {\n return {\n title: TITLE,\n accent: DOOM_OVERLAY_ACCENT,\n breadcrumb: this.options.breadcrumb,\n headerRight: this.options.interactive ? this.options.label : `${this.options.label} · ${VIEW_ONLY}`,\n footer: this.options.footer,\n footerHints: this.options.hints,\n footerRight: this.options.interactive ? 'typing goes to the run' : 'typing stays here',\n };\n }\n\n /**\n * The tree is never truncated: knowing which job is running matters more than\n * seeing another line of output, so the terminal pane absorbs whatever the\n * tree does not use.\n */\n protected renderBody(width: number, height: number): string[] {\n const { progress, output } = this.options.snapshot(width);\n const tree = progress.slice(0, height).map((line) => fit(line, width));\n\n const spare = height - tree.length;\n if (spare <= OUTPUT_CHROME_ROWS) return tree.slice(0, height);\n\n const rows = spare - OUTPUT_CHROME_ROWS;\n this.options.onViewport?.(width, rows);\n // Output keeps its own colour, so it is fitted by the escape-preserving\n // path rather than the themed-row one; see `fitTerminalLine`.\n const tail = output.slice(-rows).map((line) => fitTerminalLine(line, width));\n return [\n ...tree,\n '',\n this.theme.fg('dim', OUTPUT_HEADING),\n ...(tail.length > 0 ? tail : [this.theme.fg('dim', WAITING)]),\n ].slice(0, height);\n }\n\n dispose(): void {\n this.options.onDispose();\n }\n}\n\n/**\n * A panel whose keys cannot reach anything must never take them. Pi focuses an\n * overlay on show unless told otherwise, which for a native run would swallow\n * the user's typing into a run with no terminal to receive it.\n */\nexport function runPanelUiOptions(interactive: boolean): Record<string, unknown> {\n return {\n ...DOOM_FULLSCREEN_UI_OPTIONS,\n overlayOptions: {\n ...DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions,\n ...(interactive ? {} : { nonCapturing: true }),\n },\n };\n}\n\nexport type WorkflowRunPanelHost = Pick<ExtensionContext['ui'], 'custom'>;\n"],"mappings":";;;;;AA2BA,MAAM,QAAQ;AACd,MAAM,YAAY;AAClB,MAAM,iBAAiB;AACvB,MAAM,UAAU;;AAEhB,MAAM,qBAAqB;AA4C3B,IAAa,4BAAb,cAA+CA,oBAAAA,YAAY;CAMtC;CALnB,UAA2B,IAAIC,wBAAAA,qBAAqB;CAEpD,YACE,KACA,OACA,SACA;EACA,MAAM,KAAK,KAAK;EAFC,KAAA,UAAA;CAGnB;;;;;;;;CASA,YAAY,MAAoB;EAC9B,KAAA,GAAIC,uBAAAA,WAAAA,CAAW,MAAM,KAAK,QAAQ,gBAAgB,GAAG;GACnD,KAAK,QAAQ,WAAW;GACxB;EACF;EACA,KAAA,GAAIA,uBAAAA,WAAAA,CAAW,MAAM,KAAK,QAAQ,aAAa,GAAG;GAChD,KAAK,QAAQ,QAAQ;GACrB;EACF;EAIA,IAAI,KAAK,QAAQ,QAAQ,IAAI,MAAM,SAAS;GAC1C,KAAK,QAAQ,WAAW;GACxB,KAAK,QAAQ,QAAQ;GACrB;EACF;EACA,KAAK,QAAQ,UAAU,IAAI;CAC7B;CAEA,YAAyC;EACvC,OAAO;GACL,OAAO;GACP,QAAQC,oBAAAA;GACR,YAAY,KAAK,QAAQ;GACzB,aAAa,KAAK,QAAQ,cAAc,KAAK,QAAQ,QAAQ,GAAG,KAAK,QAAQ,MAAM,KAAK;GACxF,QAAQ,KAAK,QAAQ;GACrB,aAAa,KAAK,QAAQ;GAC1B,aAAa,KAAK,QAAQ,cAAc,2BAA2B;EACrE;CACF;;;;;;CAOA,WAAqB,OAAe,QAA0B;EAC5D,MAAM,EAAE,UAAU,WAAW,KAAK,QAAQ,SAAS,KAAK;EACxD,MAAM,OAAO,SAAS,MAAM,GAAG,MAAM,CAAC,CAAC,KAAK,SAASC,oBAAAA,IAAI,MAAM,KAAK,CAAC;EAErE,MAAM,QAAQ,SAAS,KAAK;EAC5B,IAAI,SAAS,oBAAoB,OAAO,KAAK,MAAM,GAAG,MAAM;EAE5D,MAAM,OAAO,QAAQ;EACrB,KAAK,QAAQ,aAAa,OAAO,IAAI;EAGrC,MAAM,OAAO,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,SAASC,oBAAAA,gBAAgB,MAAM,KAAK,CAAC;EAC3E,OAAO;GACL,GAAG;GACH;GACA,KAAK,MAAM,GAAG,OAAO,cAAc;GACnC,GAAI,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,MAAM,GAAG,OAAO,OAAO,CAAC;EAC7D,CAAC,CAAC,MAAM,GAAG,MAAM;CACnB;CAEA,UAAgB;EACd,KAAK,QAAQ,UAAU;CACzB;AACF;;;;;;AAOA,SAAgB,kBAAkB,aAA+C;CAC/E,OAAO;EACL,GAAGC,oBAAAA;EACH,gBAAgB;GACd,GAAGA,oBAAAA,2BAA2B;GAC9B,GAAI,cAAc,CAAC,IAAI,EAAE,cAAc,KAAK;EAC9C;CACF;AACF"}
@@ -0,0 +1,94 @@
1
+ import { DOOM_FULLSCREEN_UI_OPTIONS, DOOM_OVERLAY_ACCENT, DoomOverlay } from "./doomOverlay.mjs";
2
+ import { fit, fitTerminalLine } from "./overlayText.mjs";
3
+ import { DoubleEscapeDetector } from "./workflowOverlay.mjs";
4
+ import { matchesKey } from "@earendil-works/pi-tui";
5
+ //#region src/tui/workflow/workflowRunPanel.ts
6
+ const TITLE = "WORKFLOW RUN";
7
+ const VIEW_ONLY = "view only · this run is hosted natively";
8
+ const OUTPUT_HEADING = "OUTPUT · newest last";
9
+ const WAITING = "Waiting for output…";
10
+ /** A divider and its heading earn their rows only when output sits beneath them. */
11
+ const OUTPUT_CHROME_ROWS = 2;
12
+ var WorkflowRunPanelComponent = class extends DoomOverlay {
13
+ options;
14
+ escapes = new DoubleEscapeDetector();
15
+ constructor(tui, theme, options) {
16
+ super(tui, theme);
17
+ this.options = options;
18
+ }
19
+ /**
20
+ * The chords are matched against the whole chunk, as Pi delivers one per key
21
+ * event. A chord buried in a coalesced burst therefore misses, which is
22
+ * acceptable now that double-Escape guarantees an exit: scanning for the bytes
23
+ * anywhere in a chunk would instead eat legitimate input, since `\x1b\x17` is
24
+ * also a valid Escape-then-ctrl+w for the run's own editor.
25
+ */
26
+ handleInput(data) {
27
+ if (matchesKey(data, this.options.unfollowShortcut)) {
28
+ this.options.onUnfollow();
29
+ return;
30
+ }
31
+ if (matchesKey(data, this.options.closeShortcut)) {
32
+ this.options.onClose();
33
+ return;
34
+ }
35
+ if (this.escapes.observe(data) === "close") {
36
+ this.options.flushInput();
37
+ this.options.onClose();
38
+ return;
39
+ }
40
+ this.options.sendInput(data);
41
+ }
42
+ getChrome() {
43
+ return {
44
+ title: TITLE,
45
+ accent: DOOM_OVERLAY_ACCENT,
46
+ breadcrumb: this.options.breadcrumb,
47
+ headerRight: this.options.interactive ? this.options.label : `${this.options.label} · ${VIEW_ONLY}`,
48
+ footer: this.options.footer,
49
+ footerHints: this.options.hints,
50
+ footerRight: this.options.interactive ? "typing goes to the run" : "typing stays here"
51
+ };
52
+ }
53
+ /**
54
+ * The tree is never truncated: knowing which job is running matters more than
55
+ * seeing another line of output, so the terminal pane absorbs whatever the
56
+ * tree does not use.
57
+ */
58
+ renderBody(width, height) {
59
+ const { progress, output } = this.options.snapshot(width);
60
+ const tree = progress.slice(0, height).map((line) => fit(line, width));
61
+ const spare = height - tree.length;
62
+ if (spare <= OUTPUT_CHROME_ROWS) return tree.slice(0, height);
63
+ const rows = spare - OUTPUT_CHROME_ROWS;
64
+ this.options.onViewport?.(width, rows);
65
+ const tail = output.slice(-rows).map((line) => fitTerminalLine(line, width));
66
+ return [
67
+ ...tree,
68
+ "",
69
+ this.theme.fg("dim", OUTPUT_HEADING),
70
+ ...tail.length > 0 ? tail : [this.theme.fg("dim", WAITING)]
71
+ ].slice(0, height);
72
+ }
73
+ dispose() {
74
+ this.options.onDispose();
75
+ }
76
+ };
77
+ /**
78
+ * A panel whose keys cannot reach anything must never take them. Pi focuses an
79
+ * overlay on show unless told otherwise, which for a native run would swallow
80
+ * the user's typing into a run with no terminal to receive it.
81
+ */
82
+ function runPanelUiOptions(interactive) {
83
+ return {
84
+ ...DOOM_FULLSCREEN_UI_OPTIONS,
85
+ overlayOptions: {
86
+ ...DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions,
87
+ ...interactive ? {} : { nonCapturing: true }
88
+ }
89
+ };
90
+ }
91
+ //#endregion
92
+ export { WorkflowRunPanelComponent, runPanelUiOptions };
93
+
94
+ //# sourceMappingURL=workflowRunPanel.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflowRunPanel.mjs","names":[],"sources":["../../../../src/tui/workflow/workflowRunPanel.ts"],"sourcesContent":["/**\n * Run panel: the live view of one run's job tree and its terminal.\n *\n * A doom overlay rather than the bare header/body/footer it used to draw, so the\n * one surface a user sits inside for minutes at a time carries the same frame,\n * breadcrumb and key legend as every other. The base class owns the chrome and\n * hands the body an exact height, which also retires the hand-rolled row\n * arithmetic that existed only to stop Pi clipping the footer.\n *\n * Key routing is the reason this is a component rather than a renderer: a\n * focused panel receives input before Pi's global dispatcher, so the view\n * controls have to be handled here or the run's TTY swallows them.\n */\n\nimport type { ExtensionContext, Theme } from '@earendil-works/pi-coding-agent';\nimport { type KeyId, matchesKey } 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 { fit, fitTerminalLine } from './overlayText';\nimport { DoubleEscapeDetector } from './workflowOverlay';\n\nconst TITLE = 'WORKFLOW RUN';\nconst VIEW_ONLY = 'view only · this run is hosted natively';\nconst OUTPUT_HEADING = 'OUTPUT · newest last';\nconst WAITING = 'Waiting for output…';\n/** A divider and its heading earn their rows only when output sits beneath them. */\nconst OUTPUT_CHROME_ROWS = 2;\n\nexport interface WorkflowRunPanelSnapshot {\n /** Job tree lines, already themed by the caller. */\n progress: string[];\n /** Recent terminal output for the running step. */\n output: string[];\n}\n\nexport interface WorkflowRunPanelOptions {\n runKey: string;\n /** Full run label for the header, e.g. `name · workspace/runKey`. */\n label: string;\n breadcrumb: string;\n /** False for a natively hosted run, which has no terminal to type into. */\n interactive: boolean;\n /** Plain-sentence footer, used when the terminal cannot fit the key caps. */\n footer: string;\n /** Key legend, which differs between a typeable panel and a view. */\n hints: readonly (readonly [string, string])[];\n /** Given the body width, because the job tree is fitted as it is built. */\n snapshot: (width: number) => WorkflowRunPanelSnapshot;\n /**\n * The columns and rows the output pane can actually show, reported on each\n * paint so a launcher that supports resizing can match the run to them.\n * Called from render, so an implementation must not do the work inline: the\n * run's geometry changes out of band and the next poll picks up the reflow.\n */\n onViewport?: (columns: number, rows: number) => void;\n /** Hand typing back to the session, leaving the panel open. */\n onUnfollow: () => void;\n onClose: () => void;\n /** Forward a keystroke to the run. */\n sendInput: (data: string) => void;\n /**\n * Send whatever is buffered before the panel goes away, or the Escape that\n * closed it dies with the batcher.\n */\n flushInput: () => void;\n unfollowShortcut: KeyId;\n closeShortcut: KeyId;\n onDispose: () => void;\n}\n\nexport class WorkflowRunPanelComponent extends DoomOverlay {\n private readonly escapes = new DoubleEscapeDetector();\n\n constructor(\n tui: DoomOverlayTui,\n theme: Theme,\n private readonly options: WorkflowRunPanelOptions,\n ) {\n super(tui, theme);\n }\n\n /**\n * The chords are matched against the whole chunk, as Pi delivers one per key\n * event. A chord buried in a coalesced burst therefore misses, which is\n * acceptable now that double-Escape guarantees an exit: scanning for the bytes\n * anywhere in a chunk would instead eat legitimate input, since `\\x1b\\x17` is\n * also a valid Escape-then-ctrl+w for the run's own editor.\n */\n handleInput(data: string): void {\n if (matchesKey(data, this.options.unfollowShortcut)) {\n this.options.onUnfollow();\n return;\n }\n if (matchesKey(data, this.options.closeShortcut)) {\n this.options.onClose();\n return;\n }\n // The failsafe. The first Escape falls through to the run, so interrupting\n // the step is as fast as it ever was; only the second one inside the window\n // is consumed.\n if (this.escapes.observe(data) === 'close') {\n this.options.flushInput();\n this.options.onClose();\n return;\n }\n this.options.sendInput(data);\n }\n\n protected getChrome(): DoomOverlayChrome {\n return {\n title: TITLE,\n accent: DOOM_OVERLAY_ACCENT,\n breadcrumb: this.options.breadcrumb,\n headerRight: this.options.interactive ? this.options.label : `${this.options.label} · ${VIEW_ONLY}`,\n footer: this.options.footer,\n footerHints: this.options.hints,\n footerRight: this.options.interactive ? 'typing goes to the run' : 'typing stays here',\n };\n }\n\n /**\n * The tree is never truncated: knowing which job is running matters more than\n * seeing another line of output, so the terminal pane absorbs whatever the\n * tree does not use.\n */\n protected renderBody(width: number, height: number): string[] {\n const { progress, output } = this.options.snapshot(width);\n const tree = progress.slice(0, height).map((line) => fit(line, width));\n\n const spare = height - tree.length;\n if (spare <= OUTPUT_CHROME_ROWS) return tree.slice(0, height);\n\n const rows = spare - OUTPUT_CHROME_ROWS;\n this.options.onViewport?.(width, rows);\n // Output keeps its own colour, so it is fitted by the escape-preserving\n // path rather than the themed-row one; see `fitTerminalLine`.\n const tail = output.slice(-rows).map((line) => fitTerminalLine(line, width));\n return [\n ...tree,\n '',\n this.theme.fg('dim', OUTPUT_HEADING),\n ...(tail.length > 0 ? tail : [this.theme.fg('dim', WAITING)]),\n ].slice(0, height);\n }\n\n dispose(): void {\n this.options.onDispose();\n }\n}\n\n/**\n * A panel whose keys cannot reach anything must never take them. Pi focuses an\n * overlay on show unless told otherwise, which for a native run would swallow\n * the user's typing into a run with no terminal to receive it.\n */\nexport function runPanelUiOptions(interactive: boolean): Record<string, unknown> {\n return {\n ...DOOM_FULLSCREEN_UI_OPTIONS,\n overlayOptions: {\n ...DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions,\n ...(interactive ? {} : { nonCapturing: true }),\n },\n };\n}\n\nexport type WorkflowRunPanelHost = Pick<ExtensionContext['ui'], 'custom'>;\n"],"mappings":";;;;;AA2BA,MAAM,QAAQ;AACd,MAAM,YAAY;AAClB,MAAM,iBAAiB;AACvB,MAAM,UAAU;;AAEhB,MAAM,qBAAqB;AA4C3B,IAAa,4BAAb,cAA+C,YAAY;CAMtC;CALnB,UAA2B,IAAI,qBAAqB;CAEpD,YACE,KACA,OACA,SACA;EACA,MAAM,KAAK,KAAK;EAFC,KAAA,UAAA;CAGnB;;;;;;;;CASA,YAAY,MAAoB;EAC9B,IAAI,WAAW,MAAM,KAAK,QAAQ,gBAAgB,GAAG;GACnD,KAAK,QAAQ,WAAW;GACxB;EACF;EACA,IAAI,WAAW,MAAM,KAAK,QAAQ,aAAa,GAAG;GAChD,KAAK,QAAQ,QAAQ;GACrB;EACF;EAIA,IAAI,KAAK,QAAQ,QAAQ,IAAI,MAAM,SAAS;GAC1C,KAAK,QAAQ,WAAW;GACxB,KAAK,QAAQ,QAAQ;GACrB;EACF;EACA,KAAK,QAAQ,UAAU,IAAI;CAC7B;CAEA,YAAyC;EACvC,OAAO;GACL,OAAO;GACP,QAAQ;GACR,YAAY,KAAK,QAAQ;GACzB,aAAa,KAAK,QAAQ,cAAc,KAAK,QAAQ,QAAQ,GAAG,KAAK,QAAQ,MAAM,KAAK;GACxF,QAAQ,KAAK,QAAQ;GACrB,aAAa,KAAK,QAAQ;GAC1B,aAAa,KAAK,QAAQ,cAAc,2BAA2B;EACrE;CACF;;;;;;CAOA,WAAqB,OAAe,QAA0B;EAC5D,MAAM,EAAE,UAAU,WAAW,KAAK,QAAQ,SAAS,KAAK;EACxD,MAAM,OAAO,SAAS,MAAM,GAAG,MAAM,CAAC,CAAC,KAAK,SAAS,IAAI,MAAM,KAAK,CAAC;EAErE,MAAM,QAAQ,SAAS,KAAK;EAC5B,IAAI,SAAS,oBAAoB,OAAO,KAAK,MAAM,GAAG,MAAM;EAE5D,MAAM,OAAO,QAAQ;EACrB,KAAK,QAAQ,aAAa,OAAO,IAAI;EAGrC,MAAM,OAAO,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,SAAS,gBAAgB,MAAM,KAAK,CAAC;EAC3E,OAAO;GACL,GAAG;GACH;GACA,KAAK,MAAM,GAAG,OAAO,cAAc;GACnC,GAAI,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,MAAM,GAAG,OAAO,OAAO,CAAC;EAC7D,CAAC,CAAC,MAAM,GAAG,MAAM;CACnB;CAEA,UAAgB;EACd,KAAK,QAAQ,UAAU;CACzB;AACF;;;;;;AAOA,SAAgB,kBAAkB,aAA+C;CAC/E,OAAO;EACL,GAAG;EACH,gBAAgB;GACd,GAAG,2BAA2B;GAC9B,GAAI,cAAc,CAAC,IAAI,EAAE,cAAc,KAAK;EAC9C;CACF;AACF"}
@@ -0,0 +1,20 @@
1
+ //#region src/tui/workflow/workflowStatusRow.ts
2
+ /**
3
+ * Human-scale duration.
4
+ *
5
+ * Rounded hard on purpose: this is read at a glance next to a step name, where
6
+ * milliseconds are noise and "4m12s" answers the only question being asked.
7
+ */
8
+ function humanizeDuration(ms) {
9
+ if (!Number.isFinite(ms) || ms < 0) return "?";
10
+ if (ms < 1e3) return `${ms}ms`;
11
+ const seconds = Math.round(ms / 1e3);
12
+ if (seconds < 60) return `${seconds}s`;
13
+ const minutes = Math.floor(seconds / 60);
14
+ if (minutes < 60) return `${minutes}m${String(seconds % 60).padStart(2, "0")}s`;
15
+ return `${Math.floor(minutes / 60)}h${String(minutes % 60).padStart(2, "0")}m`;
16
+ }
17
+ //#endregion
18
+ exports.humanizeDuration = humanizeDuration;
19
+
20
+ //# sourceMappingURL=workflowStatusRow.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflowStatusRow.cjs","names":[],"sources":["../../../../src/tui/workflow/workflowStatusRow.ts"],"sourcesContent":["/**\n * Session reporting for a run's progress log.\n *\n * DESIGN PATTERNS:\n * - Pure derivation. Takes a run's raw progress events and returns report lines,\n * so the behaviour is unit-testable without a registry or a live run.\n *\n * CODING STANDARDS:\n * - Named exports only\n * - Explicit return types on exported members\n *\n * Live progress now renders through `workflowProgressOverlay.ts`. This module\n * remains the compatibility derivation used by terminal summaries and legacy\n * workflow-step cards already persisted in older sessions.\n */\n\nimport type { WorkflowProgressEvent } from '@agimon-ai/workflow-mcp';\n\n/** Step names come from workflow YAML and can be sentences. */\nconst MAX_STEP_LABEL = 48;\n\n/** One session line, plus the key that stops it being reported twice. */\nexport interface StepReport {\n duration?: string;\n job: string;\n key: string;\n status: 'FAILED' | 'FINISHED' | 'STARTED';\n step: string;\n}\n\nfunction truncateStep(step: string): string {\n return step.length <= MAX_STEP_LABEL ? step : `${step.slice(0, MAX_STEP_LABEL - 1)}…`;\n}\n\n/**\n * Human-scale duration.\n *\n * Rounded hard on purpose: this is read at a glance next to a step name, where\n * milliseconds are noise and \"4m12s\" answers the only question being asked.\n */\nexport function humanizeDuration(ms: number): string {\n if (!Number.isFinite(ms) || ms < 0) return '?';\n if (ms < 1000) return `${ms}ms`;\n const seconds = Math.round(ms / 1000);\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m${String(seconds % 60).padStart(2, '0')}s`;\n return `${Math.floor(minutes / 60)}h${String(minutes % 60).padStart(2, '0')}m`;\n}\n\n/**\n * Turn a run's raw progress log into session report lines.\n *\n * Derives durations by pairing each step's start with its end rather than\n * recording a duration in the log, so nothing about the log format has to\n * change and old runs read back the same way.\n *\n * Keyed by the event's own timestamp so a caller polling the same append-only\n * file repeatedly reports each transition exactly once, however often it polls.\n */\nexport function stepReportLines(runKey: string, events: WorkflowProgressEvent[]): StepReport[] {\n const startedAt = new Map<string, string>();\n const reports: StepReport[] = [];\n\n for (const event of events) {\n if (event.type !== 'step' || !event.step) continue;\n const id = `${runKey}/${event.job}`;\n const stepKey = `${id}/${event.step}`;\n const label = truncateStep(event.step);\n\n if (event.status === 'running') {\n startedAt.set(stepKey, event.at);\n reports.push({ job: event.job, key: `started:${stepKey}:${event.at}`, status: 'STARTED', step: label });\n continue;\n }\n\n const began = startedAt.get(stepKey);\n const duration = began ? humanizeDuration(Date.parse(event.at) - Date.parse(began)) : '?';\n // A failed step did finish, but calling it FINISHED buries the one outcome\n // the reader needs to see. Same shape, honest verb.\n const status = event.status === 'failed' ? 'FAILED' : 'FINISHED';\n reports.push({ duration, job: event.job, key: `${status}:${stepKey}:${event.at}`, status, step: label });\n }\n\n return reports;\n}\n"],"mappings":";;;;;;;AAwCA,SAAgB,iBAAiB,IAAoB;CACnD,IAAI,CAAC,OAAO,SAAS,EAAE,KAAK,KAAK,GAAG,OAAO;CAC3C,IAAI,KAAK,KAAM,OAAO,GAAG,GAAG;CAC5B,MAAM,UAAU,KAAK,MAAM,KAAK,GAAI;CACpC,IAAI,UAAU,IAAI,OAAO,GAAG,QAAQ;CACpC,MAAM,UAAU,KAAK,MAAM,UAAU,EAAE;CACvC,IAAI,UAAU,IAAI,OAAO,GAAG,QAAQ,GAAG,OAAO,UAAU,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE;CAC7E,OAAO,GAAG,KAAK,MAAM,UAAU,EAAE,EAAE,GAAG,OAAO,UAAU,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE;AAC9E"}
@@ -0,0 +1,20 @@
1
+ //#region src/tui/workflow/workflowStatusRow.ts
2
+ /**
3
+ * Human-scale duration.
4
+ *
5
+ * Rounded hard on purpose: this is read at a glance next to a step name, where
6
+ * milliseconds are noise and "4m12s" answers the only question being asked.
7
+ */
8
+ function humanizeDuration(ms) {
9
+ if (!Number.isFinite(ms) || ms < 0) return "?";
10
+ if (ms < 1e3) return `${ms}ms`;
11
+ const seconds = Math.round(ms / 1e3);
12
+ if (seconds < 60) return `${seconds}s`;
13
+ const minutes = Math.floor(seconds / 60);
14
+ if (minutes < 60) return `${minutes}m${String(seconds % 60).padStart(2, "0")}s`;
15
+ return `${Math.floor(minutes / 60)}h${String(minutes % 60).padStart(2, "0")}m`;
16
+ }
17
+ //#endregion
18
+ export { humanizeDuration };
19
+
20
+ //# sourceMappingURL=workflowStatusRow.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflowStatusRow.mjs","names":[],"sources":["../../../../src/tui/workflow/workflowStatusRow.ts"],"sourcesContent":["/**\n * Session reporting for a run's progress log.\n *\n * DESIGN PATTERNS:\n * - Pure derivation. Takes a run's raw progress events and returns report lines,\n * so the behaviour is unit-testable without a registry or a live run.\n *\n * CODING STANDARDS:\n * - Named exports only\n * - Explicit return types on exported members\n *\n * Live progress now renders through `workflowProgressOverlay.ts`. This module\n * remains the compatibility derivation used by terminal summaries and legacy\n * workflow-step cards already persisted in older sessions.\n */\n\nimport type { WorkflowProgressEvent } from '@agimon-ai/workflow-mcp';\n\n/** Step names come from workflow YAML and can be sentences. */\nconst MAX_STEP_LABEL = 48;\n\n/** One session line, plus the key that stops it being reported twice. */\nexport interface StepReport {\n duration?: string;\n job: string;\n key: string;\n status: 'FAILED' | 'FINISHED' | 'STARTED';\n step: string;\n}\n\nfunction truncateStep(step: string): string {\n return step.length <= MAX_STEP_LABEL ? step : `${step.slice(0, MAX_STEP_LABEL - 1)}…`;\n}\n\n/**\n * Human-scale duration.\n *\n * Rounded hard on purpose: this is read at a glance next to a step name, where\n * milliseconds are noise and \"4m12s\" answers the only question being asked.\n */\nexport function humanizeDuration(ms: number): string {\n if (!Number.isFinite(ms) || ms < 0) return '?';\n if (ms < 1000) return `${ms}ms`;\n const seconds = Math.round(ms / 1000);\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m${String(seconds % 60).padStart(2, '0')}s`;\n return `${Math.floor(minutes / 60)}h${String(minutes % 60).padStart(2, '0')}m`;\n}\n\n/**\n * Turn a run's raw progress log into session report lines.\n *\n * Derives durations by pairing each step's start with its end rather than\n * recording a duration in the log, so nothing about the log format has to\n * change and old runs read back the same way.\n *\n * Keyed by the event's own timestamp so a caller polling the same append-only\n * file repeatedly reports each transition exactly once, however often it polls.\n */\nexport function stepReportLines(runKey: string, events: WorkflowProgressEvent[]): StepReport[] {\n const startedAt = new Map<string, string>();\n const reports: StepReport[] = [];\n\n for (const event of events) {\n if (event.type !== 'step' || !event.step) continue;\n const id = `${runKey}/${event.job}`;\n const stepKey = `${id}/${event.step}`;\n const label = truncateStep(event.step);\n\n if (event.status === 'running') {\n startedAt.set(stepKey, event.at);\n reports.push({ job: event.job, key: `started:${stepKey}:${event.at}`, status: 'STARTED', step: label });\n continue;\n }\n\n const began = startedAt.get(stepKey);\n const duration = began ? humanizeDuration(Date.parse(event.at) - Date.parse(began)) : '?';\n // A failed step did finish, but calling it FINISHED buries the one outcome\n // the reader needs to see. Same shape, honest verb.\n const status = event.status === 'failed' ? 'FAILED' : 'FINISHED';\n reports.push({ duration, job: event.job, key: `${status}:${stepKey}:${event.at}`, status, step: label });\n }\n\n return reports;\n}\n"],"mappings":";;;;;;;AAwCA,SAAgB,iBAAiB,IAAoB;CACnD,IAAI,CAAC,OAAO,SAAS,EAAE,KAAK,KAAK,GAAG,OAAO;CAC3C,IAAI,KAAK,KAAM,OAAO,GAAG,GAAG;CAC5B,MAAM,UAAU,KAAK,MAAM,KAAK,GAAI;CACpC,IAAI,UAAU,IAAI,OAAO,GAAG,QAAQ;CACpC,MAAM,UAAU,KAAK,MAAM,UAAU,EAAE;CACvC,IAAI,UAAU,IAAI,OAAO,GAAG,QAAQ,GAAG,OAAO,UAAU,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE;CAC7E,OAAO,GAAG,KAAK,MAAM,UAAU,EAAE,EAAE,GAAG,OAAO,UAAU,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE;AAC9E"}
@@ -0,0 +1,32 @@
1
+ let _earendil_works_pi_tui = require("@earendil-works/pi-tui");
2
+ //#region src/tui/workflow/workflowStepMessage.ts
3
+ function isWorkflowStepMessageDetails(value) {
4
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
5
+ const candidate = value;
6
+ return typeof candidate.displayName === "string" && typeof candidate.job === "string" && typeof candidate.step === "string" && (candidate.status === "STARTED" || candidate.status === "FINISHED" || candidate.status === "FAILED") && (candidate.duration === void 0 || typeof candidate.duration === "string");
7
+ }
8
+ var WorkflowStepMessageLines = class {
9
+ details;
10
+ theme;
11
+ constructor(details, theme) {
12
+ this.details = details;
13
+ this.theme = theme;
14
+ }
15
+ render(width) {
16
+ const header = `${this.theme.fg("accent", `[${this.details.displayName}]:`)} ${this.details.job}`;
17
+ const transition = this.details.duration ? `${this.details.status}::${this.details.duration}::${this.details.step}` : `${this.details.status}::${this.details.step}`;
18
+ const colour = this.details.status === "FAILED" ? "error" : this.details.status === "FINISHED" ? "success" : "accent";
19
+ return [(0, _earendil_works_pi_tui.truncateToWidth)(header, width), (0, _earendil_works_pi_tui.truncateToWidth)(this.theme.fg(colour, transition), width)];
20
+ }
21
+ invalidate() {}
22
+ };
23
+ function renderWorkflowStepMessage(details, fallback, outputPad, theme) {
24
+ const box = new _earendil_works_pi_tui.Box(outputPad, 1, (text) => theme.bg("customMessageBg", text));
25
+ box.addChild(details ? new WorkflowStepMessageLines(details, theme) : new _earendil_works_pi_tui.Text(fallback, 0, 0));
26
+ return box;
27
+ }
28
+ //#endregion
29
+ exports.isWorkflowStepMessageDetails = isWorkflowStepMessageDetails;
30
+ exports.renderWorkflowStepMessage = renderWorkflowStepMessage;
31
+
32
+ //# sourceMappingURL=workflowStepMessage.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflowStepMessage.cjs","names":["truncateToWidth","Box","Text"],"sources":["../../../../src/tui/workflow/workflowStepMessage.ts"],"sourcesContent":["import type { Theme } from '@earendil-works/pi-coding-agent';\nimport { Box, type Component, Text, truncateToWidth } from '@earendil-works/pi-tui';\n\nimport type { StepReport } from './workflowStatusRow';\n\nexport interface WorkflowStepMessageDetails {\n displayName: string;\n duration?: string;\n job: string;\n status: StepReport['status'];\n step: string;\n}\n\nexport function workflowStepMessageDetails(displayName: string, report: StepReport): WorkflowStepMessageDetails {\n return {\n displayName,\n job: report.job,\n status: report.status,\n step: report.step,\n ...(report.duration ? { duration: report.duration } : {}),\n };\n}\n\nexport function formatWorkflowStepMessage(details: WorkflowStepMessageDetails): string {\n const transition = details.duration\n ? `${details.status}::${details.duration}::${details.step}`\n : `${details.status}::${details.step}`;\n return `[${details.displayName}]: ${details.job}\\n${transition}`;\n}\n\nexport function isWorkflowStepMessageDetails(value: unknown): value is WorkflowStepMessageDetails {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false;\n const candidate = value as Partial<WorkflowStepMessageDetails>;\n return (\n typeof candidate.displayName === 'string' &&\n typeof candidate.job === 'string' &&\n typeof candidate.step === 'string' &&\n (candidate.status === 'STARTED' || candidate.status === 'FINISHED' || candidate.status === 'FAILED') &&\n (candidate.duration === undefined || typeof candidate.duration === 'string')\n );\n}\n\nclass WorkflowStepMessageLines implements Component {\n constructor(\n private readonly details: WorkflowStepMessageDetails,\n private readonly theme: Theme,\n ) {}\n\n render(width: number): string[] {\n const header = `${this.theme.fg('accent', `[${this.details.displayName}]:`)} ${this.details.job}`;\n const transition = this.details.duration\n ? `${this.details.status}::${this.details.duration}::${this.details.step}`\n : `${this.details.status}::${this.details.step}`;\n const colour =\n this.details.status === 'FAILED' ? 'error' : this.details.status === 'FINISHED' ? 'success' : 'accent';\n return [truncateToWidth(header, width), truncateToWidth(this.theme.fg(colour, transition), width)];\n }\n\n invalidate(): void {}\n}\n\nexport function renderWorkflowStepMessage(\n details: WorkflowStepMessageDetails | undefined,\n fallback: string,\n outputPad: number,\n theme: Theme,\n): Component {\n const box = new Box(outputPad, 1, (text) => theme.bg('customMessageBg', text));\n box.addChild(details ? new WorkflowStepMessageLines(details, theme) : new Text(fallback, 0, 0));\n return box;\n}\n"],"mappings":";;AA8BA,SAAgB,6BAA6B,OAAqD;CAChG,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG,OAAO;CACxE,MAAM,YAAY;CAClB,OACE,OAAO,UAAU,gBAAgB,YACjC,OAAO,UAAU,QAAQ,YACzB,OAAO,UAAU,SAAS,aACzB,UAAU,WAAW,aAAa,UAAU,WAAW,cAAc,UAAU,WAAW,cAC1F,UAAU,aAAa,KAAA,KAAa,OAAO,UAAU,aAAa;AAEvE;AAEA,IAAM,2BAAN,MAAoD;CAE/B;CACA;CAFnB,YACE,SACA,OACA;EAFiB,KAAA,UAAA;EACA,KAAA,QAAA;CAChB;CAEH,OAAO,OAAyB;EAC9B,MAAM,SAAS,GAAG,KAAK,MAAM,GAAG,UAAU,IAAI,KAAK,QAAQ,YAAY,GAAG,EAAE,GAAG,KAAK,QAAQ;EAC5F,MAAM,aAAa,KAAK,QAAQ,WAC5B,GAAG,KAAK,QAAQ,OAAO,IAAI,KAAK,QAAQ,SAAS,IAAI,KAAK,QAAQ,SAClE,GAAG,KAAK,QAAQ,OAAO,IAAI,KAAK,QAAQ;EAC5C,MAAM,SACJ,KAAK,QAAQ,WAAW,WAAW,UAAU,KAAK,QAAQ,WAAW,aAAa,YAAY;EAChG,OAAO,EAAA,GAACA,uBAAAA,gBAAAA,CAAgB,QAAQ,KAAK,IAAA,GAAGA,uBAAAA,gBAAAA,CAAgB,KAAK,MAAM,GAAG,QAAQ,UAAU,GAAG,KAAK,CAAC;CACnG;CAEA,aAAmB,CAAC;AACtB;AAEA,SAAgB,0BACd,SACA,UACA,WACA,OACW;CACX,MAAM,MAAM,IAAIC,uBAAAA,IAAI,WAAW,IAAI,SAAS,MAAM,GAAG,mBAAmB,IAAI,CAAC;CAC7E,IAAI,SAAS,UAAU,IAAI,yBAAyB,SAAS,KAAK,IAAI,IAAIC,uBAAAA,KAAK,UAAU,GAAG,CAAC,CAAC;CAC9F,OAAO;AACT"}
@@ -0,0 +1,31 @@
1
+ import { Box, Text, truncateToWidth } from "@earendil-works/pi-tui";
2
+ //#region src/tui/workflow/workflowStepMessage.ts
3
+ function isWorkflowStepMessageDetails(value) {
4
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
5
+ const candidate = value;
6
+ return typeof candidate.displayName === "string" && typeof candidate.job === "string" && typeof candidate.step === "string" && (candidate.status === "STARTED" || candidate.status === "FINISHED" || candidate.status === "FAILED") && (candidate.duration === void 0 || typeof candidate.duration === "string");
7
+ }
8
+ var WorkflowStepMessageLines = class {
9
+ details;
10
+ theme;
11
+ constructor(details, theme) {
12
+ this.details = details;
13
+ this.theme = theme;
14
+ }
15
+ render(width) {
16
+ const header = `${this.theme.fg("accent", `[${this.details.displayName}]:`)} ${this.details.job}`;
17
+ const transition = this.details.duration ? `${this.details.status}::${this.details.duration}::${this.details.step}` : `${this.details.status}::${this.details.step}`;
18
+ const colour = this.details.status === "FAILED" ? "error" : this.details.status === "FINISHED" ? "success" : "accent";
19
+ return [truncateToWidth(header, width), truncateToWidth(this.theme.fg(colour, transition), width)];
20
+ }
21
+ invalidate() {}
22
+ };
23
+ function renderWorkflowStepMessage(details, fallback, outputPad, theme) {
24
+ const box = new Box(outputPad, 1, (text) => theme.bg("customMessageBg", text));
25
+ box.addChild(details ? new WorkflowStepMessageLines(details, theme) : new Text(fallback, 0, 0));
26
+ return box;
27
+ }
28
+ //#endregion
29
+ export { isWorkflowStepMessageDetails, renderWorkflowStepMessage };
30
+
31
+ //# sourceMappingURL=workflowStepMessage.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflowStepMessage.mjs","names":[],"sources":["../../../../src/tui/workflow/workflowStepMessage.ts"],"sourcesContent":["import type { Theme } from '@earendil-works/pi-coding-agent';\nimport { Box, type Component, Text, truncateToWidth } from '@earendil-works/pi-tui';\n\nimport type { StepReport } from './workflowStatusRow';\n\nexport interface WorkflowStepMessageDetails {\n displayName: string;\n duration?: string;\n job: string;\n status: StepReport['status'];\n step: string;\n}\n\nexport function workflowStepMessageDetails(displayName: string, report: StepReport): WorkflowStepMessageDetails {\n return {\n displayName,\n job: report.job,\n status: report.status,\n step: report.step,\n ...(report.duration ? { duration: report.duration } : {}),\n };\n}\n\nexport function formatWorkflowStepMessage(details: WorkflowStepMessageDetails): string {\n const transition = details.duration\n ? `${details.status}::${details.duration}::${details.step}`\n : `${details.status}::${details.step}`;\n return `[${details.displayName}]: ${details.job}\\n${transition}`;\n}\n\nexport function isWorkflowStepMessageDetails(value: unknown): value is WorkflowStepMessageDetails {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false;\n const candidate = value as Partial<WorkflowStepMessageDetails>;\n return (\n typeof candidate.displayName === 'string' &&\n typeof candidate.job === 'string' &&\n typeof candidate.step === 'string' &&\n (candidate.status === 'STARTED' || candidate.status === 'FINISHED' || candidate.status === 'FAILED') &&\n (candidate.duration === undefined || typeof candidate.duration === 'string')\n );\n}\n\nclass WorkflowStepMessageLines implements Component {\n constructor(\n private readonly details: WorkflowStepMessageDetails,\n private readonly theme: Theme,\n ) {}\n\n render(width: number): string[] {\n const header = `${this.theme.fg('accent', `[${this.details.displayName}]:`)} ${this.details.job}`;\n const transition = this.details.duration\n ? `${this.details.status}::${this.details.duration}::${this.details.step}`\n : `${this.details.status}::${this.details.step}`;\n const colour =\n this.details.status === 'FAILED' ? 'error' : this.details.status === 'FINISHED' ? 'success' : 'accent';\n return [truncateToWidth(header, width), truncateToWidth(this.theme.fg(colour, transition), width)];\n }\n\n invalidate(): void {}\n}\n\nexport function renderWorkflowStepMessage(\n details: WorkflowStepMessageDetails | undefined,\n fallback: string,\n outputPad: number,\n theme: Theme,\n): Component {\n const box = new Box(outputPad, 1, (text) => theme.bg('customMessageBg', text));\n box.addChild(details ? new WorkflowStepMessageLines(details, theme) : new Text(fallback, 0, 0));\n return box;\n}\n"],"mappings":";;AA8BA,SAAgB,6BAA6B,OAAqD;CAChG,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG,OAAO;CACxE,MAAM,YAAY;CAClB,OACE,OAAO,UAAU,gBAAgB,YACjC,OAAO,UAAU,QAAQ,YACzB,OAAO,UAAU,SAAS,aACzB,UAAU,WAAW,aAAa,UAAU,WAAW,cAAc,UAAU,WAAW,cAC1F,UAAU,aAAa,KAAA,KAAa,OAAO,UAAU,aAAa;AAEvE;AAEA,IAAM,2BAAN,MAAoD;CAE/B;CACA;CAFnB,YACE,SACA,OACA;EAFiB,KAAA,UAAA;EACA,KAAA,QAAA;CAChB;CAEH,OAAO,OAAyB;EAC9B,MAAM,SAAS,GAAG,KAAK,MAAM,GAAG,UAAU,IAAI,KAAK,QAAQ,YAAY,GAAG,EAAE,GAAG,KAAK,QAAQ;EAC5F,MAAM,aAAa,KAAK,QAAQ,WAC5B,GAAG,KAAK,QAAQ,OAAO,IAAI,KAAK,QAAQ,SAAS,IAAI,KAAK,QAAQ,SAClE,GAAG,KAAK,QAAQ,OAAO,IAAI,KAAK,QAAQ;EAC5C,MAAM,SACJ,KAAK,QAAQ,WAAW,WAAW,UAAU,KAAK,QAAQ,WAAW,aAAa,YAAY;EAChG,OAAO,CAAC,gBAAgB,QAAQ,KAAK,GAAG,gBAAgB,KAAK,MAAM,GAAG,QAAQ,UAAU,GAAG,KAAK,CAAC;CACnG;CAEA,aAAmB,CAAC;AACtB;AAEA,SAAgB,0BACd,SACA,UACA,WACA,OACW;CACX,MAAM,MAAM,IAAI,IAAI,WAAW,IAAI,SAAS,MAAM,GAAG,mBAAmB,IAAI,CAAC;CAC7E,IAAI,SAAS,UAAU,IAAI,yBAAyB,SAAS,KAAK,IAAI,IAAI,KAAK,UAAU,GAAG,CAAC,CAAC;CAC9F,OAAO;AACT"}