@bastani/atomic 0.7.17 → 0.8.0-0

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 (1233) hide show
  1. package/CHANGELOG.md +4183 -0
  2. package/README.md +655 -0
  3. package/dist/builtin/intercom/CHANGELOG.md +195 -0
  4. package/dist/builtin/intercom/LICENSE +21 -0
  5. package/dist/builtin/intercom/README.md +484 -0
  6. package/dist/builtin/intercom/broker/broker.ts +346 -0
  7. package/dist/builtin/intercom/broker/client.ts +535 -0
  8. package/dist/builtin/intercom/broker/framing.ts +57 -0
  9. package/dist/builtin/intercom/broker/paths.ts +21 -0
  10. package/dist/builtin/intercom/broker/spawn.ts +308 -0
  11. package/dist/builtin/intercom/config.ts +109 -0
  12. package/dist/builtin/intercom/index.ts +1780 -0
  13. package/dist/builtin/intercom/package.json +59 -0
  14. package/dist/builtin/intercom/reply-tracker.ts +102 -0
  15. package/dist/builtin/intercom/skills/intercom/SKILL.md +513 -0
  16. package/dist/builtin/intercom/types.ts +46 -0
  17. package/dist/builtin/intercom/ui/compose.ts +139 -0
  18. package/dist/builtin/intercom/ui/inline-message.ts +76 -0
  19. package/dist/builtin/intercom/ui/session-list.ts +162 -0
  20. package/dist/builtin/mcp/CHANGELOG.md +346 -0
  21. package/dist/builtin/mcp/LICENSE +21 -0
  22. package/dist/builtin/mcp/OAUTH.md +324 -0
  23. package/dist/builtin/mcp/README.md +373 -0
  24. package/dist/builtin/mcp/agent-dir.ts +21 -0
  25. package/dist/builtin/mcp/app-bridge.bundle.js +67 -0
  26. package/dist/builtin/mcp/cli.js +186 -0
  27. package/dist/builtin/mcp/commands.ts +420 -0
  28. package/dist/builtin/mcp/config.ts +667 -0
  29. package/dist/builtin/mcp/consent-manager.ts +64 -0
  30. package/dist/builtin/mcp/direct-tools.ts +427 -0
  31. package/dist/builtin/mcp/errors.ts +219 -0
  32. package/dist/builtin/mcp/glimpse-ui.ts +80 -0
  33. package/dist/builtin/mcp/host-html-template.ts +427 -0
  34. package/dist/builtin/mcp/index.ts +334 -0
  35. package/dist/builtin/mcp/init.ts +336 -0
  36. package/dist/builtin/mcp/lifecycle.ts +93 -0
  37. package/dist/builtin/mcp/logger.ts +169 -0
  38. package/dist/builtin/mcp/mcp-auth-flow.ts +362 -0
  39. package/dist/builtin/mcp/mcp-auth.ts +297 -0
  40. package/dist/builtin/mcp/mcp-callback-server.ts +284 -0
  41. package/dist/builtin/mcp/mcp-oauth-provider.ts +302 -0
  42. package/dist/builtin/mcp/mcp-panel.ts +826 -0
  43. package/dist/builtin/mcp/mcp-setup-panel.ts +577 -0
  44. package/dist/builtin/mcp/metadata-cache.ts +201 -0
  45. package/dist/builtin/mcp/npx-resolver.ts +424 -0
  46. package/dist/builtin/mcp/oauth-handler.ts +60 -0
  47. package/dist/builtin/mcp/onboarding-state.ts +68 -0
  48. package/dist/builtin/mcp/package.json +61 -0
  49. package/dist/builtin/mcp/proxy-modes.ts +803 -0
  50. package/dist/builtin/mcp/resource-tools.ts +17 -0
  51. package/dist/builtin/mcp/sampling-handler.ts +268 -0
  52. package/dist/builtin/mcp/server-manager.ts +375 -0
  53. package/dist/builtin/mcp/state.ts +41 -0
  54. package/dist/builtin/mcp/tool-metadata.ts +152 -0
  55. package/dist/builtin/mcp/tool-registrar.ts +46 -0
  56. package/dist/builtin/mcp/tool-result-renderer.ts +65 -0
  57. package/dist/builtin/mcp/types.ts +441 -0
  58. package/dist/builtin/mcp/ui-resource-handler.ts +145 -0
  59. package/dist/builtin/mcp/ui-server.ts +623 -0
  60. package/dist/builtin/mcp/ui-session.ts +384 -0
  61. package/dist/builtin/mcp/ui-stream-types.ts +89 -0
  62. package/dist/builtin/mcp/utils.ts +129 -0
  63. package/dist/builtin/subagents/CHANGELOG.md +1019 -0
  64. package/dist/builtin/subagents/README.md +991 -0
  65. package/dist/builtin/subagents/agents/code-simplifier.md +84 -0
  66. package/dist/builtin/subagents/agents/codebase-analyzer.md +158 -0
  67. package/dist/builtin/subagents/agents/codebase-locator.md +113 -0
  68. package/dist/builtin/subagents/agents/codebase-online-researcher.md +317 -0
  69. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +236 -0
  70. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +181 -0
  71. package/dist/builtin/subagents/agents/codebase-research-locator.md +146 -0
  72. package/dist/builtin/subagents/agents/debugger.md +92 -0
  73. package/dist/builtin/subagents/package.json +67 -0
  74. package/dist/builtin/subagents/prompts/gather-context-and-clarify.md +20 -0
  75. package/dist/builtin/subagents/prompts/parallel-cleanup.md +60 -0
  76. package/dist/builtin/subagents/prompts/parallel-context-build.md +55 -0
  77. package/dist/builtin/subagents/prompts/parallel-handoff-plan.md +77 -0
  78. package/dist/builtin/subagents/prompts/parallel-research.md +58 -0
  79. package/dist/builtin/subagents/prompts/parallel-review.md +52 -0
  80. package/dist/builtin/subagents/prompts/review-loop.md +48 -0
  81. package/dist/builtin/subagents/skills/subagent/SKILL.md +734 -0
  82. package/dist/builtin/subagents/src/agents/agent-management.ts +644 -0
  83. package/dist/builtin/subagents/src/agents/agent-scope.ts +6 -0
  84. package/dist/builtin/subagents/src/agents/agent-selection.ts +23 -0
  85. package/dist/builtin/subagents/src/agents/agent-serializer.ts +84 -0
  86. package/dist/builtin/subagents/src/agents/agents.ts +809 -0
  87. package/dist/builtin/subagents/src/agents/chain-serializer.ts +137 -0
  88. package/dist/builtin/subagents/src/agents/frontmatter.ts +29 -0
  89. package/dist/builtin/subagents/src/agents/identity.ts +30 -0
  90. package/dist/builtin/subagents/src/agents/skills.ts +630 -0
  91. package/dist/builtin/subagents/src/extension/control-notices.ts +92 -0
  92. package/dist/builtin/subagents/src/extension/doctor.ts +199 -0
  93. package/dist/builtin/subagents/src/extension/index.ts +586 -0
  94. package/dist/builtin/subagents/src/extension/schemas.ts +168 -0
  95. package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +378 -0
  96. package/dist/builtin/subagents/src/intercom/result-intercom.ts +269 -0
  97. package/dist/builtin/subagents/src/runs/background/async-execution.ts +612 -0
  98. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +267 -0
  99. package/dist/builtin/subagents/src/runs/background/async-resume.ts +332 -0
  100. package/dist/builtin/subagents/src/runs/background/async-status.ts +295 -0
  101. package/dist/builtin/subagents/src/runs/background/completion-dedupe.ts +63 -0
  102. package/dist/builtin/subagents/src/runs/background/notify.ts +108 -0
  103. package/dist/builtin/subagents/src/runs/background/parallel-groups.ts +45 -0
  104. package/dist/builtin/subagents/src/runs/background/result-watcher.ts +250 -0
  105. package/dist/builtin/subagents/src/runs/background/run-status.ts +193 -0
  106. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +291 -0
  107. package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +1760 -0
  108. package/dist/builtin/subagents/src/runs/background/top-level-async.ts +13 -0
  109. package/dist/builtin/subagents/src/runs/foreground/chain-clarify.ts +1333 -0
  110. package/dist/builtin/subagents/src/runs/foreground/chain-execution.ts +932 -0
  111. package/dist/builtin/subagents/src/runs/foreground/execution.ts +902 -0
  112. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +2231 -0
  113. package/dist/builtin/subagents/src/runs/shared/completion-guard.ts +125 -0
  114. package/dist/builtin/subagents/src/runs/shared/long-running-guard.ts +175 -0
  115. package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +103 -0
  116. package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +108 -0
  117. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +163 -0
  118. package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +115 -0
  119. package/dist/builtin/subagents/src/runs/shared/run-history.ts +56 -0
  120. package/dist/builtin/subagents/src/runs/shared/single-output.ts +154 -0
  121. package/dist/builtin/subagents/src/runs/shared/subagent-control.ts +226 -0
  122. package/dist/builtin/subagents/src/runs/shared/subagent-prompt-runtime.ts +152 -0
  123. package/dist/builtin/subagents/src/runs/shared/worktree.ts +577 -0
  124. package/dist/builtin/subagents/src/shared/artifacts.ts +99 -0
  125. package/dist/builtin/subagents/src/shared/atomic-json.ts +16 -0
  126. package/dist/builtin/subagents/src/shared/file-coalescer.ts +40 -0
  127. package/dist/builtin/subagents/src/shared/fork-context.ts +76 -0
  128. package/dist/builtin/subagents/src/shared/formatters.ts +133 -0
  129. package/dist/builtin/subagents/src/shared/jsonl-writer.ts +81 -0
  130. package/dist/builtin/subagents/src/shared/model-info.ts +78 -0
  131. package/dist/builtin/subagents/src/shared/post-exit-stdio-guard.ts +85 -0
  132. package/dist/builtin/subagents/src/shared/session-identity.ts +10 -0
  133. package/dist/builtin/subagents/src/shared/session-tokens.ts +44 -0
  134. package/dist/builtin/subagents/src/shared/settings.ts +397 -0
  135. package/dist/builtin/subagents/src/shared/status-format.ts +49 -0
  136. package/dist/builtin/subagents/src/shared/types.ts +732 -0
  137. package/dist/builtin/subagents/src/shared/utils.ts +440 -0
  138. package/dist/builtin/subagents/src/slash/prompt-template-bridge.ts +397 -0
  139. package/dist/builtin/subagents/src/slash/slash-bridge.ts +174 -0
  140. package/dist/builtin/subagents/src/slash/slash-commands.ts +528 -0
  141. package/dist/builtin/subagents/src/slash/slash-live-state.ts +292 -0
  142. package/dist/builtin/subagents/src/tui/render-helpers.ts +80 -0
  143. package/dist/builtin/subagents/src/tui/render.ts +1257 -0
  144. package/dist/builtin/web-access/CHANGELOG.md +387 -0
  145. package/dist/builtin/web-access/LICENSE +21 -0
  146. package/dist/builtin/web-access/README.md +346 -0
  147. package/dist/builtin/web-access/activity.ts +101 -0
  148. package/dist/builtin/web-access/chrome-cookies.ts +322 -0
  149. package/dist/builtin/web-access/code-search.ts +107 -0
  150. package/dist/builtin/web-access/curator-page.ts +3359 -0
  151. package/dist/builtin/web-access/curator-server.ts +605 -0
  152. package/dist/builtin/web-access/exa.ts +521 -0
  153. package/dist/builtin/web-access/extract.ts +701 -0
  154. package/dist/builtin/web-access/gemini-api.ts +113 -0
  155. package/dist/builtin/web-access/gemini-search.ts +362 -0
  156. package/dist/builtin/web-access/gemini-url-context.ts +126 -0
  157. package/dist/builtin/web-access/gemini-web-config.ts +54 -0
  158. package/dist/builtin/web-access/gemini-web.ts +396 -0
  159. package/dist/builtin/web-access/github-api.ts +196 -0
  160. package/dist/builtin/web-access/github-extract.ts +635 -0
  161. package/dist/builtin/web-access/index.ts +2347 -0
  162. package/dist/builtin/web-access/package.json +54 -0
  163. package/dist/builtin/web-access/pdf-extract.ts +192 -0
  164. package/dist/builtin/web-access/perplexity.ts +196 -0
  165. package/dist/builtin/web-access/rsc-extract.ts +338 -0
  166. package/dist/builtin/web-access/storage.ts +72 -0
  167. package/dist/builtin/web-access/summary-review.ts +276 -0
  168. package/dist/builtin/web-access/utils.ts +44 -0
  169. package/dist/builtin/web-access/video-extract.ts +379 -0
  170. package/dist/builtin/web-access/youtube-extract.ts +311 -0
  171. package/dist/builtin/workflows/CHANGELOG.md +20 -0
  172. package/dist/builtin/workflows/README.md +323 -0
  173. package/dist/builtin/workflows/builtin/deep-research-codebase.ts +567 -0
  174. package/dist/builtin/workflows/builtin/index.ts +10 -0
  175. package/dist/builtin/workflows/builtin/open-claude-design.ts +985 -0
  176. package/dist/builtin/workflows/builtin/ralph.ts +613 -0
  177. package/dist/builtin/workflows/package.json +89 -0
  178. package/dist/builtin/workflows/skills/create-spec/SKILL.md +247 -0
  179. package/dist/builtin/workflows/skills/impeccable/SKILL.md +173 -0
  180. package/dist/builtin/workflows/skills/impeccable/reference/adapt.md +190 -0
  181. package/dist/builtin/workflows/skills/impeccable/reference/animate.md +175 -0
  182. package/dist/builtin/workflows/skills/impeccable/reference/audit.md +133 -0
  183. package/dist/builtin/workflows/skills/impeccable/reference/bolder.md +113 -0
  184. package/dist/builtin/workflows/skills/impeccable/reference/brand.md +118 -0
  185. package/dist/builtin/workflows/skills/impeccable/reference/clarify.md +174 -0
  186. package/dist/builtin/workflows/skills/impeccable/reference/codex.md +105 -0
  187. package/dist/builtin/workflows/skills/impeccable/reference/cognitive-load.md +106 -0
  188. package/dist/builtin/workflows/skills/impeccable/reference/color-and-contrast.md +105 -0
  189. package/dist/builtin/workflows/skills/impeccable/reference/colorize.md +154 -0
  190. package/dist/builtin/workflows/skills/impeccable/reference/craft.md +123 -0
  191. package/dist/builtin/workflows/skills/impeccable/reference/critique.md +261 -0
  192. package/dist/builtin/workflows/skills/impeccable/reference/delight.md +302 -0
  193. package/dist/builtin/workflows/skills/impeccable/reference/distill.md +111 -0
  194. package/dist/builtin/workflows/skills/impeccable/reference/document.md +427 -0
  195. package/dist/builtin/workflows/skills/impeccable/reference/extract.md +69 -0
  196. package/dist/builtin/workflows/skills/impeccable/reference/harden.md +347 -0
  197. package/dist/builtin/workflows/skills/impeccable/reference/heuristics-scoring.md +234 -0
  198. package/dist/builtin/workflows/skills/impeccable/reference/interaction-design.md +195 -0
  199. package/dist/builtin/workflows/skills/impeccable/reference/layout.md +141 -0
  200. package/dist/builtin/workflows/skills/impeccable/reference/live.md +622 -0
  201. package/dist/builtin/workflows/skills/impeccable/reference/motion-design.md +109 -0
  202. package/dist/builtin/workflows/skills/impeccable/reference/onboard.md +234 -0
  203. package/dist/builtin/workflows/skills/impeccable/reference/optimize.md +258 -0
  204. package/dist/builtin/workflows/skills/impeccable/reference/overdrive.md +130 -0
  205. package/dist/builtin/workflows/skills/impeccable/reference/personas.md +179 -0
  206. package/dist/builtin/workflows/skills/impeccable/reference/polish.md +242 -0
  207. package/dist/builtin/workflows/skills/impeccable/reference/product.md +62 -0
  208. package/dist/builtin/workflows/skills/impeccable/reference/quieter.md +99 -0
  209. package/dist/builtin/workflows/skills/impeccable/reference/responsive-design.md +114 -0
  210. package/dist/builtin/workflows/skills/impeccable/reference/shape.md +165 -0
  211. package/dist/builtin/workflows/skills/impeccable/reference/spatial-design.md +100 -0
  212. package/dist/builtin/workflows/skills/impeccable/reference/teach.md +156 -0
  213. package/dist/builtin/workflows/skills/impeccable/reference/typeset.md +124 -0
  214. package/dist/builtin/workflows/skills/impeccable/reference/typography.md +159 -0
  215. package/dist/builtin/workflows/skills/impeccable/reference/ux-writing.md +107 -0
  216. package/dist/builtin/workflows/skills/impeccable/scripts/cleanup-deprecated.mjs +284 -0
  217. package/dist/builtin/workflows/skills/impeccable/scripts/command-metadata.json +94 -0
  218. package/dist/builtin/workflows/skills/impeccable/scripts/critique-storage.mjs +226 -0
  219. package/dist/builtin/workflows/skills/impeccable/scripts/design-parser.mjs +820 -0
  220. package/dist/builtin/workflows/skills/impeccable/scripts/detect-csp.mjs +198 -0
  221. package/dist/builtin/workflows/skills/impeccable/scripts/impeccable-paths.mjs +110 -0
  222. package/dist/builtin/workflows/skills/impeccable/scripts/is-generated.mjs +69 -0
  223. package/dist/builtin/workflows/skills/impeccable/scripts/live-accept.mjs +646 -0
  224. package/dist/builtin/workflows/skills/impeccable/scripts/live-browser-session.js +123 -0
  225. package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +4865 -0
  226. package/dist/builtin/workflows/skills/impeccable/scripts/live-complete.mjs +75 -0
  227. package/dist/builtin/workflows/skills/impeccable/scripts/live-completion.mjs +18 -0
  228. package/dist/builtin/workflows/skills/impeccable/scripts/live-inject.mjs +446 -0
  229. package/dist/builtin/workflows/skills/impeccable/scripts/live-poll.mjs +200 -0
  230. package/dist/builtin/workflows/skills/impeccable/scripts/live-resume.mjs +48 -0
  231. package/dist/builtin/workflows/skills/impeccable/scripts/live-server.mjs +847 -0
  232. package/dist/builtin/workflows/skills/impeccable/scripts/live-session-store.mjs +254 -0
  233. package/dist/builtin/workflows/skills/impeccable/scripts/live-status.mjs +47 -0
  234. package/dist/builtin/workflows/skills/impeccable/scripts/live-wrap.mjs +632 -0
  235. package/dist/builtin/workflows/skills/impeccable/scripts/live.mjs +247 -0
  236. package/dist/builtin/workflows/skills/impeccable/scripts/load-context.mjs +141 -0
  237. package/dist/builtin/workflows/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
  238. package/dist/builtin/workflows/skills/impeccable/scripts/pin.mjs +214 -0
  239. package/dist/builtin/workflows/skills/playwright-cli/SKILL.md +392 -0
  240. package/dist/builtin/workflows/skills/playwright-cli/references/element-attributes.md +23 -0
  241. package/dist/builtin/workflows/skills/playwright-cli/references/playwright-tests.md +39 -0
  242. package/dist/builtin/workflows/skills/playwright-cli/references/request-mocking.md +87 -0
  243. package/dist/builtin/workflows/skills/playwright-cli/references/running-code.md +241 -0
  244. package/dist/builtin/workflows/skills/playwright-cli/references/session-management.md +225 -0
  245. package/dist/builtin/workflows/skills/playwright-cli/references/spec-driven-testing.md +305 -0
  246. package/dist/builtin/workflows/skills/playwright-cli/references/storage-state.md +275 -0
  247. package/dist/builtin/workflows/skills/playwright-cli/references/test-generation.md +134 -0
  248. package/dist/builtin/workflows/skills/playwright-cli/references/tracing.md +139 -0
  249. package/dist/builtin/workflows/skills/playwright-cli/references/video-recording.md +143 -0
  250. package/dist/builtin/workflows/skills/prompt-engineer/SKILL.md +263 -0
  251. package/dist/builtin/workflows/skills/prompt-engineer/references/advanced_patterns.md +271 -0
  252. package/dist/builtin/workflows/skills/prompt-engineer/references/core_prompting.md +137 -0
  253. package/dist/builtin/workflows/skills/prompt-engineer/references/quality_improvement.md +193 -0
  254. package/dist/builtin/workflows/skills/research-codebase/SKILL.md +226 -0
  255. package/dist/builtin/workflows/skills/tdd/SKILL.md +109 -0
  256. package/dist/builtin/workflows/skills/tdd/deep-modules.md +33 -0
  257. package/dist/builtin/workflows/skills/tdd/interface-design.md +31 -0
  258. package/dist/builtin/workflows/skills/tdd/mocking.md +59 -0
  259. package/dist/builtin/workflows/skills/tdd/refactoring.md +10 -0
  260. package/dist/builtin/workflows/skills/tdd/tests.md +61 -0
  261. package/dist/builtin/workflows/skills/workflow/SKILL.md +255 -0
  262. package/dist/builtin/workflows/skills/workflow/references/context-engineering/advanced-evaluation.md +404 -0
  263. package/dist/builtin/workflows/skills/workflow/references/context-engineering/bdi-mental-states.md +313 -0
  264. package/dist/builtin/workflows/skills/workflow/references/context-engineering/context-compression.md +274 -0
  265. package/dist/builtin/workflows/skills/workflow/references/context-engineering/context-degradation.md +208 -0
  266. package/dist/builtin/workflows/skills/workflow/references/context-engineering/context-fundamentals.md +203 -0
  267. package/dist/builtin/workflows/skills/workflow/references/context-engineering/context-optimization.md +197 -0
  268. package/dist/builtin/workflows/skills/workflow/references/context-engineering/evaluation.md +253 -0
  269. package/dist/builtin/workflows/skills/workflow/references/context-engineering/filesystem-context.md +289 -0
  270. package/dist/builtin/workflows/skills/workflow/references/context-engineering/hosted-agents.md +262 -0
  271. package/dist/builtin/workflows/skills/workflow/references/context-engineering/memory-systems.md +221 -0
  272. package/dist/builtin/workflows/skills/workflow/references/context-engineering/multi-agent-patterns.md +259 -0
  273. package/dist/builtin/workflows/skills/workflow/references/context-engineering/project-development.md +293 -0
  274. package/dist/builtin/workflows/skills/workflow/references/context-engineering/tool-design.md +273 -0
  275. package/dist/builtin/workflows/skills/workflow/references/context-engineering.md +23 -0
  276. package/dist/builtin/workflows/skills/workflow/references/design-checklist.md +79 -0
  277. package/dist/builtin/workflows/skills/workflow/references/running-workflows.md +107 -0
  278. package/dist/builtin/workflows/skills/workflow/references/sdk-authoring.md +140 -0
  279. package/dist/builtin/workflows/src/extension/background-ui-adapter.ts +168 -0
  280. package/dist/builtin/workflows/src/extension/companions.ts +210 -0
  281. package/dist/builtin/workflows/src/extension/config-loader.ts +493 -0
  282. package/dist/builtin/workflows/src/extension/discovery.ts +501 -0
  283. package/dist/builtin/workflows/src/extension/dispatcher.ts +173 -0
  284. package/dist/builtin/workflows/src/extension/index.ts +2143 -0
  285. package/dist/builtin/workflows/src/extension/mcp.ts +110 -0
  286. package/dist/builtin/workflows/src/extension/render-call.ts +39 -0
  287. package/dist/builtin/workflows/src/extension/render-result.ts +214 -0
  288. package/dist/builtin/workflows/src/extension/renderers.ts +87 -0
  289. package/dist/builtin/workflows/src/extension/runtime.ts +360 -0
  290. package/dist/builtin/workflows/src/extension/status-writer.ts +167 -0
  291. package/dist/builtin/workflows/src/extension/wiring.ts +555 -0
  292. package/dist/builtin/workflows/src/extension/workflow-schema.ts +102 -0
  293. package/dist/builtin/workflows/src/index.ts +25 -0
  294. package/dist/builtin/workflows/src/intercom/intercom-bridge.ts +93 -0
  295. package/dist/builtin/workflows/src/intercom/intercom-routing.ts +125 -0
  296. package/dist/builtin/workflows/src/intercom/result-intercom.ts +240 -0
  297. package/dist/builtin/workflows/src/runs/background/cancellation-registry.ts +113 -0
  298. package/dist/builtin/workflows/src/runs/background/job-tracker.ts +81 -0
  299. package/dist/builtin/workflows/src/runs/background/runner.ts +152 -0
  300. package/dist/builtin/workflows/src/runs/background/status.ts +354 -0
  301. package/dist/builtin/workflows/src/runs/foreground/executor.ts +1522 -0
  302. package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +233 -0
  303. package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +712 -0
  304. package/dist/builtin/workflows/src/runs/shared/concurrency.ts +76 -0
  305. package/dist/builtin/workflows/src/runs/shared/graph-inference.ts +69 -0
  306. package/dist/builtin/workflows/src/runs/shared/model-fallback.ts +293 -0
  307. package/dist/builtin/workflows/src/runs/shared/validate-inputs.ts +83 -0
  308. package/dist/builtin/workflows/src/runs/shared/workflow-runner.ts +170 -0
  309. package/dist/builtin/workflows/src/runs/shared/worktree.ts +577 -0
  310. package/dist/builtin/workflows/src/shared/persistence-compaction-policy.ts +72 -0
  311. package/dist/builtin/workflows/src/shared/persistence-restore.ts +257 -0
  312. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +145 -0
  313. package/dist/builtin/workflows/src/shared/render-inputs-schema.ts +196 -0
  314. package/dist/builtin/workflows/src/shared/store-types.ts +160 -0
  315. package/dist/builtin/workflows/src/shared/store.ts +579 -0
  316. package/dist/builtin/workflows/src/shared/types.ts +566 -0
  317. package/dist/builtin/workflows/src/tui/chat-surface-message.ts +224 -0
  318. package/dist/builtin/workflows/src/tui/chat-surface.ts +511 -0
  319. package/dist/builtin/workflows/src/tui/color-utils.ts +64 -0
  320. package/dist/builtin/workflows/src/tui/connectors.ts +88 -0
  321. package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +307 -0
  322. package/dist/builtin/workflows/src/tui/edge.ts +24 -0
  323. package/dist/builtin/workflows/src/tui/graph-canvas.ts +108 -0
  324. package/dist/builtin/workflows/src/tui/graph-theme.ts +283 -0
  325. package/dist/builtin/workflows/src/tui/graph-view.ts +1217 -0
  326. package/dist/builtin/workflows/src/tui/header.ts +172 -0
  327. package/dist/builtin/workflows/src/tui/inline-form-card.ts +421 -0
  328. package/dist/builtin/workflows/src/tui/inline-form-editor.ts +638 -0
  329. package/dist/builtin/workflows/src/tui/inline-form-overlay.ts +326 -0
  330. package/dist/builtin/workflows/src/tui/inline-form-store.ts +78 -0
  331. package/dist/builtin/workflows/src/tui/inputs-overlay.ts +163 -0
  332. package/dist/builtin/workflows/src/tui/inputs-picker.ts +888 -0
  333. package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +154 -0
  334. package/dist/builtin/workflows/src/tui/layout.ts +153 -0
  335. package/dist/builtin/workflows/src/tui/node-card.ts +274 -0
  336. package/dist/builtin/workflows/src/tui/overlay-adapter.ts +277 -0
  337. package/dist/builtin/workflows/src/tui/prompt-card.ts +501 -0
  338. package/dist/builtin/workflows/src/tui/renderers.ts +15 -0
  339. package/dist/builtin/workflows/src/tui/run-detail.ts +339 -0
  340. package/dist/builtin/workflows/src/tui/session-confirm.ts +202 -0
  341. package/dist/builtin/workflows/src/tui/session-list.ts +32 -0
  342. package/dist/builtin/workflows/src/tui/session-overlays.ts +239 -0
  343. package/dist/builtin/workflows/src/tui/session-picker.ts +399 -0
  344. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +1873 -0
  345. package/dist/builtin/workflows/src/tui/status-helpers.ts +73 -0
  346. package/dist/builtin/workflows/src/tui/status-list.ts +361 -0
  347. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +206 -0
  348. package/dist/builtin/workflows/src/tui/switcher.ts +121 -0
  349. package/dist/builtin/workflows/src/tui/text-helpers.ts +31 -0
  350. package/dist/builtin/workflows/src/tui/toast.ts +106 -0
  351. package/dist/builtin/workflows/src/tui/widget.ts +348 -0
  352. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +285 -0
  353. package/dist/builtin/workflows/src/tui/workflow-list.ts +224 -0
  354. package/dist/builtin/workflows/src/workflows/define-workflow.ts +150 -0
  355. package/dist/builtin/workflows/src/workflows/identity.ts +39 -0
  356. package/dist/builtin/workflows/src/workflows/registry.ts +113 -0
  357. package/dist/bun/cli.d.ts +3 -0
  358. package/dist/bun/cli.d.ts.map +1 -0
  359. package/dist/bun/cli.js +9 -0
  360. package/dist/bun/cli.js.map +1 -0
  361. package/dist/bun/register-bedrock.d.ts +2 -0
  362. package/dist/bun/register-bedrock.d.ts.map +1 -0
  363. package/dist/bun/register-bedrock.js +4 -0
  364. package/dist/bun/register-bedrock.js.map +1 -0
  365. package/dist/bun/restore-sandbox-env.d.ts +13 -0
  366. package/dist/bun/restore-sandbox-env.d.ts.map +1 -0
  367. package/dist/bun/restore-sandbox-env.js +32 -0
  368. package/dist/bun/restore-sandbox-env.js.map +1 -0
  369. package/dist/cli/args.d.ts +53 -0
  370. package/dist/cli/args.d.ts.map +1 -0
  371. package/dist/cli/args.js +341 -0
  372. package/dist/cli/args.js.map +1 -0
  373. package/dist/cli/config-selector.d.ts +14 -0
  374. package/dist/cli/config-selector.d.ts.map +1 -0
  375. package/dist/cli/config-selector.js +31 -0
  376. package/dist/cli/config-selector.js.map +1 -0
  377. package/dist/cli/file-processor.d.ts +15 -0
  378. package/dist/cli/file-processor.d.ts.map +1 -0
  379. package/dist/cli/file-processor.js +83 -0
  380. package/dist/cli/file-processor.js.map +1 -0
  381. package/dist/cli/initial-message.d.ts +18 -0
  382. package/dist/cli/initial-message.d.ts.map +1 -0
  383. package/dist/cli/initial-message.js +22 -0
  384. package/dist/cli/initial-message.js.map +1 -0
  385. package/dist/cli/list-models.d.ts +9 -0
  386. package/dist/cli/list-models.d.ts.map +1 -0
  387. package/dist/cli/list-models.js +98 -0
  388. package/dist/cli/list-models.js.map +1 -0
  389. package/dist/cli/session-picker.d.ts +9 -0
  390. package/dist/cli/session-picker.d.ts.map +1 -0
  391. package/dist/cli/session-picker.js +35 -0
  392. package/dist/cli/session-picker.js.map +1 -0
  393. package/dist/cli.d.ts +3 -0
  394. package/dist/cli.d.ts.map +1 -0
  395. package/dist/cli.js +20 -0
  396. package/dist/cli.js.map +1 -0
  397. package/dist/config.d.ts +102 -0
  398. package/dist/config.d.ts.map +1 -0
  399. package/dist/config.js +411 -0
  400. package/dist/config.js.map +1 -0
  401. package/dist/core/agent-session-runtime.d.ts +117 -0
  402. package/dist/core/agent-session-runtime.d.ts.map +1 -0
  403. package/dist/core/agent-session-runtime.js +292 -0
  404. package/dist/core/agent-session-runtime.js.map +1 -0
  405. package/dist/core/agent-session-services.d.ts +86 -0
  406. package/dist/core/agent-session-services.d.ts.map +1 -0
  407. package/dist/core/agent-session-services.js +117 -0
  408. package/dist/core/agent-session-services.js.map +1 -0
  409. package/dist/core/agent-session.d.ts +595 -0
  410. package/dist/core/agent-session.d.ts.map +1 -0
  411. package/dist/core/agent-session.js +2518 -0
  412. package/dist/core/agent-session.js.map +1 -0
  413. package/dist/core/auth-guidance.d.ts +5 -0
  414. package/dist/core/auth-guidance.d.ts.map +1 -0
  415. package/dist/core/auth-guidance.js +21 -0
  416. package/dist/core/auth-guidance.js.map +1 -0
  417. package/dist/core/auth-storage.d.ts +141 -0
  418. package/dist/core/auth-storage.d.ts.map +1 -0
  419. package/dist/core/auth-storage.js +437 -0
  420. package/dist/core/auth-storage.js.map +1 -0
  421. package/dist/core/bash-executor.d.ts +32 -0
  422. package/dist/core/bash-executor.d.ts.map +1 -0
  423. package/dist/core/bash-executor.js +111 -0
  424. package/dist/core/bash-executor.js.map +1 -0
  425. package/dist/core/builtin-packages.d.ts +14 -0
  426. package/dist/core/builtin-packages.d.ts.map +1 -0
  427. package/dist/core/builtin-packages.js +113 -0
  428. package/dist/core/builtin-packages.js.map +1 -0
  429. package/dist/core/compaction/branch-summarization.d.ts +88 -0
  430. package/dist/core/compaction/branch-summarization.d.ts.map +1 -0
  431. package/dist/core/compaction/branch-summarization.js +243 -0
  432. package/dist/core/compaction/branch-summarization.js.map +1 -0
  433. package/dist/core/compaction/compaction.d.ts +121 -0
  434. package/dist/core/compaction/compaction.d.ts.map +1 -0
  435. package/dist/core/compaction/compaction.js +615 -0
  436. package/dist/core/compaction/compaction.js.map +1 -0
  437. package/dist/core/compaction/index.d.ts +7 -0
  438. package/dist/core/compaction/index.d.ts.map +1 -0
  439. package/dist/core/compaction/index.js +7 -0
  440. package/dist/core/compaction/index.js.map +1 -0
  441. package/dist/core/compaction/utils.d.ts +38 -0
  442. package/dist/core/compaction/utils.d.ts.map +1 -0
  443. package/dist/core/compaction/utils.js +153 -0
  444. package/dist/core/compaction/utils.js.map +1 -0
  445. package/dist/core/defaults.d.ts +3 -0
  446. package/dist/core/defaults.d.ts.map +1 -0
  447. package/dist/core/defaults.js +2 -0
  448. package/dist/core/defaults.js.map +1 -0
  449. package/dist/core/diagnostics.d.ts +15 -0
  450. package/dist/core/diagnostics.d.ts.map +1 -0
  451. package/dist/core/diagnostics.js +2 -0
  452. package/dist/core/diagnostics.js.map +1 -0
  453. package/dist/core/event-bus.d.ts +9 -0
  454. package/dist/core/event-bus.d.ts.map +1 -0
  455. package/dist/core/event-bus.js +25 -0
  456. package/dist/core/event-bus.js.map +1 -0
  457. package/dist/core/exec.d.ts +29 -0
  458. package/dist/core/exec.d.ts.map +1 -0
  459. package/dist/core/exec.js +75 -0
  460. package/dist/core/exec.js.map +1 -0
  461. package/dist/core/export-html/ansi-to-html.d.ts +22 -0
  462. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
  463. package/dist/core/export-html/ansi-to-html.js +249 -0
  464. package/dist/core/export-html/ansi-to-html.js.map +1 -0
  465. package/dist/core/export-html/index.d.ts +37 -0
  466. package/dist/core/export-html/index.d.ts.map +1 -0
  467. package/dist/core/export-html/index.js +224 -0
  468. package/dist/core/export-html/index.js.map +1 -0
  469. package/dist/core/export-html/template.css +1066 -0
  470. package/dist/core/export-html/template.html +55 -0
  471. package/dist/core/export-html/template.js +1834 -0
  472. package/dist/core/export-html/tool-renderer.d.ts +34 -0
  473. package/dist/core/export-html/tool-renderer.d.ts.map +1 -0
  474. package/dist/core/export-html/tool-renderer.js +108 -0
  475. package/dist/core/export-html/tool-renderer.js.map +1 -0
  476. package/dist/core/export-html/vendor/highlight.min.js +1213 -0
  477. package/dist/core/export-html/vendor/marked.min.js +6 -0
  478. package/dist/core/extensions/index.d.ts +12 -0
  479. package/dist/core/extensions/index.d.ts.map +1 -0
  480. package/dist/core/extensions/index.js +9 -0
  481. package/dist/core/extensions/index.js.map +1 -0
  482. package/dist/core/extensions/loader.d.ts +24 -0
  483. package/dist/core/extensions/loader.d.ts.map +1 -0
  484. package/dist/core/extensions/loader.js +501 -0
  485. package/dist/core/extensions/loader.js.map +1 -0
  486. package/dist/core/extensions/runner.d.ts +159 -0
  487. package/dist/core/extensions/runner.d.ts.map +1 -0
  488. package/dist/core/extensions/runner.js +817 -0
  489. package/dist/core/extensions/runner.js.map +1 -0
  490. package/dist/core/extensions/types.d.ts +1173 -0
  491. package/dist/core/extensions/types.d.ts.map +1 -0
  492. package/dist/core/extensions/types.js +45 -0
  493. package/dist/core/extensions/types.js.map +1 -0
  494. package/dist/core/extensions/wrapper.d.ts +20 -0
  495. package/dist/core/extensions/wrapper.d.ts.map +1 -0
  496. package/dist/core/extensions/wrapper.js +22 -0
  497. package/dist/core/extensions/wrapper.js.map +1 -0
  498. package/dist/core/footer-data-provider.d.ts +52 -0
  499. package/dist/core/footer-data-provider.d.ts.map +1 -0
  500. package/dist/core/footer-data-provider.js +309 -0
  501. package/dist/core/footer-data-provider.js.map +1 -0
  502. package/dist/core/index.d.ts +12 -0
  503. package/dist/core/index.d.ts.map +1 -0
  504. package/dist/core/index.js +12 -0
  505. package/dist/core/index.js.map +1 -0
  506. package/dist/core/keybindings.d.ts +353 -0
  507. package/dist/core/keybindings.d.ts.map +1 -0
  508. package/dist/core/keybindings.js +294 -0
  509. package/dist/core/keybindings.js.map +1 -0
  510. package/dist/core/messages.d.ts +77 -0
  511. package/dist/core/messages.d.ts.map +1 -0
  512. package/dist/core/messages.js +123 -0
  513. package/dist/core/messages.js.map +1 -0
  514. package/dist/core/model-registry.d.ts +150 -0
  515. package/dist/core/model-registry.d.ts.map +1 -0
  516. package/dist/core/model-registry.js +726 -0
  517. package/dist/core/model-registry.js.map +1 -0
  518. package/dist/core/model-resolver.d.ts +110 -0
  519. package/dist/core/model-resolver.d.ts.map +1 -0
  520. package/dist/core/model-resolver.js +493 -0
  521. package/dist/core/model-resolver.js.map +1 -0
  522. package/dist/core/output-guard.d.ts +6 -0
  523. package/dist/core/output-guard.d.ts.map +1 -0
  524. package/dist/core/output-guard.js +59 -0
  525. package/dist/core/output-guard.js.map +1 -0
  526. package/dist/core/package-manager.d.ts +198 -0
  527. package/dist/core/package-manager.d.ts.map +1 -0
  528. package/dist/core/package-manager.js +1970 -0
  529. package/dist/core/package-manager.js.map +1 -0
  530. package/dist/core/prompt-templates.d.ts +52 -0
  531. package/dist/core/prompt-templates.d.ts.map +1 -0
  532. package/dist/core/prompt-templates.js +250 -0
  533. package/dist/core/prompt-templates.js.map +1 -0
  534. package/dist/core/provider-display-names.d.ts +2 -0
  535. package/dist/core/provider-display-names.d.ts.map +1 -0
  536. package/dist/core/provider-display-names.js +33 -0
  537. package/dist/core/provider-display-names.js.map +1 -0
  538. package/dist/core/resolve-config-value.d.ts +23 -0
  539. package/dist/core/resolve-config-value.d.ts.map +1 -0
  540. package/dist/core/resolve-config-value.js +126 -0
  541. package/dist/core/resolve-config-value.js.map +1 -0
  542. package/dist/core/resource-loader.d.ts +196 -0
  543. package/dist/core/resource-loader.d.ts.map +1 -0
  544. package/dist/core/resource-loader.js +698 -0
  545. package/dist/core/resource-loader.js.map +1 -0
  546. package/dist/core/sdk.d.ts +107 -0
  547. package/dist/core/sdk.d.ts.map +1 -0
  548. package/dist/core/sdk.js +291 -0
  549. package/dist/core/sdk.js.map +1 -0
  550. package/dist/core/session-cwd.d.ts +19 -0
  551. package/dist/core/session-cwd.d.ts.map +1 -0
  552. package/dist/core/session-cwd.js +37 -0
  553. package/dist/core/session-cwd.js.map +1 -0
  554. package/dist/core/session-manager.d.ts +333 -0
  555. package/dist/core/session-manager.d.ts.map +1 -0
  556. package/dist/core/session-manager.js +1118 -0
  557. package/dist/core/session-manager.js.map +1 -0
  558. package/dist/core/settings-manager.d.ts +261 -0
  559. package/dist/core/settings-manager.d.ts.map +1 -0
  560. package/dist/core/settings-manager.js +773 -0
  561. package/dist/core/settings-manager.js.map +1 -0
  562. package/dist/core/skills.d.ts +60 -0
  563. package/dist/core/skills.d.ts.map +1 -0
  564. package/dist/core/skills.js +404 -0
  565. package/dist/core/skills.js.map +1 -0
  566. package/dist/core/slash-commands.d.ts +14 -0
  567. package/dist/core/slash-commands.d.ts.map +1 -0
  568. package/dist/core/slash-commands.js +25 -0
  569. package/dist/core/slash-commands.js.map +1 -0
  570. package/dist/core/source-info.d.ts +18 -0
  571. package/dist/core/source-info.d.ts.map +1 -0
  572. package/dist/core/source-info.js +19 -0
  573. package/dist/core/source-info.js.map +1 -0
  574. package/dist/core/system-prompt.d.ts +28 -0
  575. package/dist/core/system-prompt.d.ts.map +1 -0
  576. package/dist/core/system-prompt.js +120 -0
  577. package/dist/core/system-prompt.js.map +1 -0
  578. package/dist/core/telemetry.d.ts +3 -0
  579. package/dist/core/telemetry.d.ts.map +1 -0
  580. package/dist/core/telemetry.js +10 -0
  581. package/dist/core/telemetry.js.map +1 -0
  582. package/dist/core/timings.d.ts +8 -0
  583. package/dist/core/timings.d.ts.map +1 -0
  584. package/dist/core/timings.js +32 -0
  585. package/dist/core/timings.js.map +1 -0
  586. package/dist/core/tools/ask-user-question/ask-user-question.d.ts +10 -0
  587. package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -0
  588. package/dist/core/tools/ask-user-question/ask-user-question.js +82 -0
  589. package/dist/core/tools/ask-user-question/ask-user-question.js.map +1 -0
  590. package/dist/core/tools/ask-user-question/config.d.ts +11 -0
  591. package/dist/core/tools/ask-user-question/config.d.ts.map +1 -0
  592. package/dist/core/tools/ask-user-question/config.js +34 -0
  593. package/dist/core/tools/ask-user-question/config.js.map +1 -0
  594. package/dist/core/tools/ask-user-question/index.d.ts +19 -0
  595. package/dist/core/tools/ask-user-question/index.d.ts.map +1 -0
  596. package/dist/core/tools/ask-user-question/index.js +19 -0
  597. package/dist/core/tools/ask-user-question/index.js.map +1 -0
  598. package/dist/core/tools/ask-user-question/state/build-questionnaire.d.ts +36 -0
  599. package/dist/core/tools/ask-user-question/state/build-questionnaire.d.ts.map +1 -0
  600. package/dist/core/tools/ask-user-question/state/build-questionnaire.js +213 -0
  601. package/dist/core/tools/ask-user-question/state/build-questionnaire.js.map +1 -0
  602. package/dist/core/tools/ask-user-question/state/key-router.d.ts +53 -0
  603. package/dist/core/tools/ask-user-question/state/key-router.d.ts.map +1 -0
  604. package/dist/core/tools/ask-user-question/state/key-router.js +240 -0
  605. package/dist/core/tools/ask-user-question/state/key-router.js.map +1 -0
  606. package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts +61 -0
  607. package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts.map +1 -0
  608. package/dist/core/tools/ask-user-question/state/questionnaire-session.js +147 -0
  609. package/dist/core/tools/ask-user-question/state/questionnaire-session.js.map +1 -0
  610. package/dist/core/tools/ask-user-question/state/row-intent.d.ts +91 -0
  611. package/dist/core/tools/ask-user-question/state/row-intent.d.ts.map +1 -0
  612. package/dist/core/tools/ask-user-question/state/row-intent.js +91 -0
  613. package/dist/core/tools/ask-user-question/state/row-intent.js.map +1 -0
  614. package/dist/core/tools/ask-user-question/state/selectors/contract.d.ts +21 -0
  615. package/dist/core/tools/ask-user-question/state/selectors/contract.d.ts.map +1 -0
  616. package/dist/core/tools/ask-user-question/state/selectors/contract.js +2 -0
  617. package/dist/core/tools/ask-user-question/state/selectors/contract.js.map +1 -0
  618. package/dist/core/tools/ask-user-question/state/selectors/derivations.d.ts +44 -0
  619. package/dist/core/tools/ask-user-question/state/selectors/derivations.d.ts.map +1 -0
  620. package/dist/core/tools/ask-user-question/state/selectors/derivations.js +76 -0
  621. package/dist/core/tools/ask-user-question/state/selectors/derivations.js.map +1 -0
  622. package/dist/core/tools/ask-user-question/state/selectors/focus.d.ts +15 -0
  623. package/dist/core/tools/ask-user-question/state/selectors/focus.d.ts.map +1 -0
  624. package/dist/core/tools/ask-user-question/state/selectors/focus.js +18 -0
  625. package/dist/core/tools/ask-user-question/state/selectors/focus.js.map +1 -0
  626. package/dist/core/tools/ask-user-question/state/selectors/projections.d.ts +16 -0
  627. package/dist/core/tools/ask-user-question/state/selectors/projections.d.ts.map +1 -0
  628. package/dist/core/tools/ask-user-question/state/selectors/projections.js +71 -0
  629. package/dist/core/tools/ask-user-question/state/selectors/projections.js.map +1 -0
  630. package/dist/core/tools/ask-user-question/state/state-reducer.d.ts +44 -0
  631. package/dist/core/tools/ask-user-question/state/state-reducer.d.ts.map +1 -0
  632. package/dist/core/tools/ask-user-question/state/state-reducer.js +239 -0
  633. package/dist/core/tools/ask-user-question/state/state-reducer.js.map +1 -0
  634. package/dist/core/tools/ask-user-question/state/state.d.ts +42 -0
  635. package/dist/core/tools/ask-user-question/state/state.d.ts.map +1 -0
  636. package/dist/core/tools/ask-user-question/state/state.js +2 -0
  637. package/dist/core/tools/ask-user-question/state/state.js.map +1 -0
  638. package/dist/core/tools/ask-user-question/tool/format-answer.d.ts +30 -0
  639. package/dist/core/tools/ask-user-question/tool/format-answer.d.ts.map +1 -0
  640. package/dist/core/tools/ask-user-question/tool/format-answer.js +39 -0
  641. package/dist/core/tools/ask-user-question/tool/format-answer.js.map +1 -0
  642. package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts +29 -0
  643. package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts.map +1 -0
  644. package/dist/core/tools/ask-user-question/tool/response-envelope.js +46 -0
  645. package/dist/core/tools/ask-user-question/tool/response-envelope.js.map +1 -0
  646. package/dist/core/tools/ask-user-question/tool/types.d.ts +113 -0
  647. package/dist/core/tools/ask-user-question/tool/types.d.ts.map +1 -0
  648. package/dist/core/tools/ask-user-question/tool/types.js +81 -0
  649. package/dist/core/tools/ask-user-question/tool/types.js.map +1 -0
  650. package/dist/core/tools/ask-user-question/tool/validate-questionnaire.d.ts +21 -0
  651. package/dist/core/tools/ask-user-question/tool/validate-questionnaire.d.ts.map +1 -0
  652. package/dist/core/tools/ask-user-question/tool/validate-questionnaire.js +49 -0
  653. package/dist/core/tools/ask-user-question/tool/validate-questionnaire.js.map +1 -0
  654. package/dist/core/tools/ask-user-question/view/body-residual-spacer.d.ts +18 -0
  655. package/dist/core/tools/ask-user-question/view/body-residual-spacer.d.ts.map +1 -0
  656. package/dist/core/tools/ask-user-question/view/body-residual-spacer.js +21 -0
  657. package/dist/core/tools/ask-user-question/view/body-residual-spacer.js.map +1 -0
  658. package/dist/core/tools/ask-user-question/view/component-binding.d.ts +23 -0
  659. package/dist/core/tools/ask-user-question/view/component-binding.d.ts.map +1 -0
  660. package/dist/core/tools/ask-user-question/view/component-binding.js +16 -0
  661. package/dist/core/tools/ask-user-question/view/component-binding.js.map +1 -0
  662. package/dist/core/tools/ask-user-question/view/components/chat-row-view.d.ts +40 -0
  663. package/dist/core/tools/ask-user-question/view/components/chat-row-view.d.ts.map +1 -0
  664. package/dist/core/tools/ask-user-question/view/components/chat-row-view.js +31 -0
  665. package/dist/core/tools/ask-user-question/view/components/chat-row-view.js.map +1 -0
  666. package/dist/core/tools/ask-user-question/view/components/multi-select-view.d.ts +35 -0
  667. package/dist/core/tools/ask-user-question/view/components/multi-select-view.d.ts.map +1 -0
  668. package/dist/core/tools/ask-user-question/view/components/multi-select-view.js +91 -0
  669. package/dist/core/tools/ask-user-question/view/components/multi-select-view.js.map +1 -0
  670. package/dist/core/tools/ask-user-question/view/components/option-list-view.d.ts +43 -0
  671. package/dist/core/tools/ask-user-question/view/components/option-list-view.d.ts.map +1 -0
  672. package/dist/core/tools/ask-user-question/view/components/option-list-view.js +37 -0
  673. package/dist/core/tools/ask-user-question/view/components/option-list-view.js.map +1 -0
  674. package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.d.ts +36 -0
  675. package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.d.ts.map +1 -0
  676. package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.js +66 -0
  677. package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.js.map +1 -0
  678. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.d.ts +46 -0
  679. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.d.ts.map +1 -0
  680. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.js +69 -0
  681. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.js.map +1 -0
  682. package/dist/core/tools/ask-user-question/view/components/preview/preview-box-renderer.d.ts +39 -0
  683. package/dist/core/tools/ask-user-question/view/components/preview/preview-box-renderer.d.ts.map +1 -0
  684. package/dist/core/tools/ask-user-question/view/components/preview/preview-box-renderer.js +76 -0
  685. package/dist/core/tools/ask-user-question/view/components/preview/preview-box-renderer.js.map +1 -0
  686. package/dist/core/tools/ask-user-question/view/components/preview/preview-layout-decider.d.ts +116 -0
  687. package/dist/core/tools/ask-user-question/view/components/preview/preview-layout-decider.d.ts.map +1 -0
  688. package/dist/core/tools/ask-user-question/view/components/preview/preview-layout-decider.js +173 -0
  689. package/dist/core/tools/ask-user-question/view/components/preview/preview-layout-decider.js.map +1 -0
  690. package/dist/core/tools/ask-user-question/view/components/preview/preview-pane.d.ts +66 -0
  691. package/dist/core/tools/ask-user-question/view/components/preview/preview-pane.d.ts.map +1 -0
  692. package/dist/core/tools/ask-user-question/view/components/preview/preview-pane.js +124 -0
  693. package/dist/core/tools/ask-user-question/view/components/preview/preview-pane.js.map +1 -0
  694. package/dist/core/tools/ask-user-question/view/components/submit-picker.d.ts +37 -0
  695. package/dist/core/tools/ask-user-question/view/components/submit-picker.d.ts.map +1 -0
  696. package/dist/core/tools/ask-user-question/view/components/submit-picker.js +44 -0
  697. package/dist/core/tools/ask-user-question/view/components/submit-picker.js.map +1 -0
  698. package/dist/core/tools/ask-user-question/view/components/tab-bar.d.ts +32 -0
  699. package/dist/core/tools/ask-user-question/view/components/tab-bar.d.ts.map +1 -0
  700. package/dist/core/tools/ask-user-question/view/components/tab-bar.js +33 -0
  701. package/dist/core/tools/ask-user-question/view/components/tab-bar.js.map +1 -0
  702. package/dist/core/tools/ask-user-question/view/components/wrapping-select.d.ts +122 -0
  703. package/dist/core/tools/ask-user-question/view/components/wrapping-select.d.ts.map +1 -0
  704. package/dist/core/tools/ask-user-question/view/components/wrapping-select.js +161 -0
  705. package/dist/core/tools/ask-user-question/view/components/wrapping-select.js.map +1 -0
  706. package/dist/core/tools/ask-user-question/view/dialog-builder.d.ts +66 -0
  707. package/dist/core/tools/ask-user-question/view/dialog-builder.d.ts.map +1 -0
  708. package/dist/core/tools/ask-user-question/view/dialog-builder.js +85 -0
  709. package/dist/core/tools/ask-user-question/view/dialog-builder.js.map +1 -0
  710. package/dist/core/tools/ask-user-question/view/props-adapter.d.ts +58 -0
  711. package/dist/core/tools/ask-user-question/view/props-adapter.d.ts.map +1 -0
  712. package/dist/core/tools/ask-user-question/view/props-adapter.js +67 -0
  713. package/dist/core/tools/ask-user-question/view/props-adapter.js.map +1 -0
  714. package/dist/core/tools/ask-user-question/view/stateful-view.d.ts +24 -0
  715. package/dist/core/tools/ask-user-question/view/stateful-view.d.ts.map +1 -0
  716. package/dist/core/tools/ask-user-question/view/stateful-view.js +2 -0
  717. package/dist/core/tools/ask-user-question/view/stateful-view.js.map +1 -0
  718. package/dist/core/tools/ask-user-question/view/tab-components.d.ts +15 -0
  719. package/dist/core/tools/ask-user-question/view/tab-components.d.ts.map +1 -0
  720. package/dist/core/tools/ask-user-question/view/tab-components.js +2 -0
  721. package/dist/core/tools/ask-user-question/view/tab-components.js.map +1 -0
  722. package/dist/core/tools/ask-user-question/view/tab-content-strategy.d.ts +71 -0
  723. package/dist/core/tools/ask-user-question/view/tab-content-strategy.d.ts.map +1 -0
  724. package/dist/core/tools/ask-user-question/view/tab-content-strategy.js +129 -0
  725. package/dist/core/tools/ask-user-question/view/tab-content-strategy.js.map +1 -0
  726. package/dist/core/tools/bash.d.ts +68 -0
  727. package/dist/core/tools/bash.d.ts.map +1 -0
  728. package/dist/core/tools/bash.js +338 -0
  729. package/dist/core/tools/bash.js.map +1 -0
  730. package/dist/core/tools/edit-diff.d.ts +85 -0
  731. package/dist/core/tools/edit-diff.d.ts.map +1 -0
  732. package/dist/core/tools/edit-diff.js +338 -0
  733. package/dist/core/tools/edit-diff.js.map +1 -0
  734. package/dist/core/tools/edit.d.ts +49 -0
  735. package/dist/core/tools/edit.d.ts.map +1 -0
  736. package/dist/core/tools/edit.js +324 -0
  737. package/dist/core/tools/edit.js.map +1 -0
  738. package/dist/core/tools/file-mutation-queue.d.ts +6 -0
  739. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
  740. package/dist/core/tools/file-mutation-queue.js +37 -0
  741. package/dist/core/tools/file-mutation-queue.js.map +1 -0
  742. package/dist/core/tools/find.d.ts +35 -0
  743. package/dist/core/tools/find.d.ts.map +1 -0
  744. package/dist/core/tools/find.js +298 -0
  745. package/dist/core/tools/find.js.map +1 -0
  746. package/dist/core/tools/grep.d.ts +37 -0
  747. package/dist/core/tools/grep.d.ts.map +1 -0
  748. package/dist/core/tools/grep.js +304 -0
  749. package/dist/core/tools/grep.js.map +1 -0
  750. package/dist/core/tools/index.d.ts +42 -0
  751. package/dist/core/tools/index.d.ts.map +1 -0
  752. package/dist/core/tools/index.js +139 -0
  753. package/dist/core/tools/index.js.map +1 -0
  754. package/dist/core/tools/ls.d.ts +37 -0
  755. package/dist/core/tools/ls.d.ts.map +1 -0
  756. package/dist/core/tools/ls.js +169 -0
  757. package/dist/core/tools/ls.js.map +1 -0
  758. package/dist/core/tools/output-accumulator.d.ts +50 -0
  759. package/dist/core/tools/output-accumulator.d.ts.map +1 -0
  760. package/dist/core/tools/output-accumulator.js +172 -0
  761. package/dist/core/tools/output-accumulator.js.map +1 -0
  762. package/dist/core/tools/path-utils.d.ts +8 -0
  763. package/dist/core/tools/path-utils.d.ts.map +1 -0
  764. package/dist/core/tools/path-utils.js +81 -0
  765. package/dist/core/tools/path-utils.js.map +1 -0
  766. package/dist/core/tools/read.d.ts +35 -0
  767. package/dist/core/tools/read.d.ts.map +1 -0
  768. package/dist/core/tools/read.js +289 -0
  769. package/dist/core/tools/read.js.map +1 -0
  770. package/dist/core/tools/render-utils.d.ts +21 -0
  771. package/dist/core/tools/render-utils.d.ts.map +1 -0
  772. package/dist/core/tools/render-utils.js +49 -0
  773. package/dist/core/tools/render-utils.js.map +1 -0
  774. package/dist/core/tools/todos.d.ts +35 -0
  775. package/dist/core/tools/todos.d.ts.map +1 -0
  776. package/dist/core/tools/todos.js +906 -0
  777. package/dist/core/tools/todos.js.map +1 -0
  778. package/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
  779. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
  780. package/dist/core/tools/tool-definition-wrapper.js +34 -0
  781. package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
  782. package/dist/core/tools/truncate.d.ts +70 -0
  783. package/dist/core/tools/truncate.d.ts.map +1 -0
  784. package/dist/core/tools/truncate.js +205 -0
  785. package/dist/core/tools/truncate.js.map +1 -0
  786. package/dist/core/tools/write.d.ts +26 -0
  787. package/dist/core/tools/write.d.ts.map +1 -0
  788. package/dist/core/tools/write.js +212 -0
  789. package/dist/core/tools/write.js.map +1 -0
  790. package/dist/index.d.ts +28 -0
  791. package/dist/index.d.ts.map +1 -0
  792. package/dist/index.js +41 -0
  793. package/dist/index.js.map +1 -0
  794. package/dist/main.d.ts +13 -0
  795. package/dist/main.d.ts.map +1 -0
  796. package/dist/main.js +586 -0
  797. package/dist/main.js.map +1 -0
  798. package/dist/migrations.d.ts +33 -0
  799. package/dist/migrations.d.ts.map +1 -0
  800. package/dist/migrations.js +281 -0
  801. package/dist/migrations.js.map +1 -0
  802. package/dist/modes/index.d.ts +9 -0
  803. package/dist/modes/index.d.ts.map +1 -0
  804. package/dist/modes/index.js +8 -0
  805. package/dist/modes/index.js.map +1 -0
  806. package/dist/modes/interactive/assets/clankolas.png +3 -0
  807. package/dist/modes/interactive/components/armin.d.ts +34 -0
  808. package/dist/modes/interactive/components/armin.d.ts.map +1 -0
  809. package/dist/modes/interactive/components/armin.js +329 -0
  810. package/dist/modes/interactive/components/armin.js.map +1 -0
  811. package/dist/modes/interactive/components/assistant-message.d.ts +20 -0
  812. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
  813. package/dist/modes/interactive/components/assistant-message.js +116 -0
  814. package/dist/modes/interactive/components/assistant-message.js.map +1 -0
  815. package/dist/modes/interactive/components/bash-execution.d.ts +34 -0
  816. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -0
  817. package/dist/modes/interactive/components/bash-execution.js +170 -0
  818. package/dist/modes/interactive/components/bash-execution.js.map +1 -0
  819. package/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
  820. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -0
  821. package/dist/modes/interactive/components/bordered-loader.js +51 -0
  822. package/dist/modes/interactive/components/bordered-loader.js.map +1 -0
  823. package/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
  824. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -0
  825. package/dist/modes/interactive/components/branch-summary-message.js +42 -0
  826. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -0
  827. package/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
  828. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -0
  829. package/dist/modes/interactive/components/compaction-summary-message.js +43 -0
  830. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -0
  831. package/dist/modes/interactive/components/config-selector.d.ts +71 -0
  832. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
  833. package/dist/modes/interactive/components/config-selector.js +496 -0
  834. package/dist/modes/interactive/components/config-selector.js.map +1 -0
  835. package/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
  836. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -0
  837. package/dist/modes/interactive/components/countdown-timer.js +28 -0
  838. package/dist/modes/interactive/components/countdown-timer.js.map +1 -0
  839. package/dist/modes/interactive/components/custom-editor.d.ts +29 -0
  840. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -0
  841. package/dist/modes/interactive/components/custom-editor.js +113 -0
  842. package/dist/modes/interactive/components/custom-editor.js.map +1 -0
  843. package/dist/modes/interactive/components/custom-message.d.ts +20 -0
  844. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
  845. package/dist/modes/interactive/components/custom-message.js +74 -0
  846. package/dist/modes/interactive/components/custom-message.js.map +1 -0
  847. package/dist/modes/interactive/components/daxnuts.d.ts +23 -0
  848. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -0
  849. package/dist/modes/interactive/components/daxnuts.js +138 -0
  850. package/dist/modes/interactive/components/daxnuts.js.map +1 -0
  851. package/dist/modes/interactive/components/diff.d.ts +12 -0
  852. package/dist/modes/interactive/components/diff.d.ts.map +1 -0
  853. package/dist/modes/interactive/components/diff.js +151 -0
  854. package/dist/modes/interactive/components/diff.js.map +1 -0
  855. package/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
  856. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -0
  857. package/dist/modes/interactive/components/dynamic-border.js +20 -0
  858. package/dist/modes/interactive/components/dynamic-border.js.map +1 -0
  859. package/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
  860. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -0
  861. package/dist/modes/interactive/components/earendil-announcement.js +40 -0
  862. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -0
  863. package/dist/modes/interactive/components/extension-editor.d.ts +20 -0
  864. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
  865. package/dist/modes/interactive/components/extension-editor.js +106 -0
  866. package/dist/modes/interactive/components/extension-editor.js.map +1 -0
  867. package/dist/modes/interactive/components/extension-input.d.ts +23 -0
  868. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
  869. package/dist/modes/interactive/components/extension-input.js +55 -0
  870. package/dist/modes/interactive/components/extension-input.js.map +1 -0
  871. package/dist/modes/interactive/components/extension-selector.d.ts +26 -0
  872. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
  873. package/dist/modes/interactive/components/extension-selector.js +75 -0
  874. package/dist/modes/interactive/components/extension-selector.js.map +1 -0
  875. package/dist/modes/interactive/components/footer.d.ts +27 -0
  876. package/dist/modes/interactive/components/footer.d.ts.map +1 -0
  877. package/dist/modes/interactive/components/footer.js +199 -0
  878. package/dist/modes/interactive/components/footer.js.map +1 -0
  879. package/dist/modes/interactive/components/index.d.ts +32 -0
  880. package/dist/modes/interactive/components/index.d.ts.map +1 -0
  881. package/dist/modes/interactive/components/index.js +33 -0
  882. package/dist/modes/interactive/components/index.js.map +1 -0
  883. package/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
  884. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -0
  885. package/dist/modes/interactive/components/keybinding-hints.js +36 -0
  886. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -0
  887. package/dist/modes/interactive/components/login-dialog.d.ts +46 -0
  888. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -0
  889. package/dist/modes/interactive/components/login-dialog.js +158 -0
  890. package/dist/modes/interactive/components/login-dialog.js.map +1 -0
  891. package/dist/modes/interactive/components/model-selector.d.ts +47 -0
  892. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -0
  893. package/dist/modes/interactive/components/model-selector.js +266 -0
  894. package/dist/modes/interactive/components/model-selector.js.map +1 -0
  895. package/dist/modes/interactive/components/oauth-selector.d.ts +31 -0
  896. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -0
  897. package/dist/modes/interactive/components/oauth-selector.js +156 -0
  898. package/dist/modes/interactive/components/oauth-selector.js.map +1 -0
  899. package/dist/modes/interactive/components/scoped-models-selector.d.ts +42 -0
  900. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -0
  901. package/dist/modes/interactive/components/scoped-models-selector.js +286 -0
  902. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -0
  903. package/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
  904. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -0
  905. package/dist/modes/interactive/components/session-selector-search.js +155 -0
  906. package/dist/modes/interactive/components/session-selector-search.js.map +1 -0
  907. package/dist/modes/interactive/components/session-selector.d.ts +96 -0
  908. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -0
  909. package/dist/modes/interactive/components/session-selector.js +836 -0
  910. package/dist/modes/interactive/components/session-selector.js.map +1 -0
  911. package/dist/modes/interactive/components/settings-selector.d.ts +67 -0
  912. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -0
  913. package/dist/modes/interactive/components/settings-selector.js +371 -0
  914. package/dist/modes/interactive/components/settings-selector.js.map +1 -0
  915. package/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
  916. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -0
  917. package/dist/modes/interactive/components/show-images-selector.js +38 -0
  918. package/dist/modes/interactive/components/show-images-selector.js.map +1 -0
  919. package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
  920. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
  921. package/dist/modes/interactive/components/skill-invocation-message.js +45 -0
  922. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
  923. package/dist/modes/interactive/components/theme-selector.d.ts +11 -0
  924. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -0
  925. package/dist/modes/interactive/components/theme-selector.js +48 -0
  926. package/dist/modes/interactive/components/theme-selector.js.map +1 -0
  927. package/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
  928. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -0
  929. package/dist/modes/interactive/components/thinking-selector.js +50 -0
  930. package/dist/modes/interactive/components/thinking-selector.js.map +1 -0
  931. package/dist/modes/interactive/components/tool-execution.d.ts +63 -0
  932. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
  933. package/dist/modes/interactive/components/tool-execution.js +280 -0
  934. package/dist/modes/interactive/components/tool-execution.js.map +1 -0
  935. package/dist/modes/interactive/components/tree-selector.d.ts +89 -0
  936. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -0
  937. package/dist/modes/interactive/components/tree-selector.js +1079 -0
  938. package/dist/modes/interactive/components/tree-selector.js.map +1 -0
  939. package/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
  940. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -0
  941. package/dist/modes/interactive/components/user-message-selector.js +111 -0
  942. package/dist/modes/interactive/components/user-message-selector.js.map +1 -0
  943. package/dist/modes/interactive/components/user-message.d.ts +10 -0
  944. package/dist/modes/interactive/components/user-message.d.ts.map +1 -0
  945. package/dist/modes/interactive/components/user-message.js +28 -0
  946. package/dist/modes/interactive/components/user-message.js.map +1 -0
  947. package/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
  948. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -0
  949. package/dist/modes/interactive/components/visual-truncate.js +33 -0
  950. package/dist/modes/interactive/components/visual-truncate.js.map +1 -0
  951. package/dist/modes/interactive/interactive-mode.d.ts +369 -0
  952. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
  953. package/dist/modes/interactive/interactive-mode.js +4709 -0
  954. package/dist/modes/interactive/interactive-mode.js.map +1 -0
  955. package/dist/modes/interactive/theme/catppuccin-frappe.json +90 -0
  956. package/dist/modes/interactive/theme/catppuccin-latte.json +90 -0
  957. package/dist/modes/interactive/theme/catppuccin-macchiato.json +90 -0
  958. package/dist/modes/interactive/theme/catppuccin-mocha.json +90 -0
  959. package/dist/modes/interactive/theme/dark.json +85 -0
  960. package/dist/modes/interactive/theme/light.json +84 -0
  961. package/dist/modes/interactive/theme/theme-schema.json +335 -0
  962. package/dist/modes/interactive/theme/theme.d.ts +81 -0
  963. package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
  964. package/dist/modes/interactive/theme/theme.js +970 -0
  965. package/dist/modes/interactive/theme/theme.js.map +1 -0
  966. package/dist/modes/interactive/whimsical-messages.d.ts +5 -0
  967. package/dist/modes/interactive/whimsical-messages.d.ts.map +1 -0
  968. package/dist/modes/interactive/whimsical-messages.js +464 -0
  969. package/dist/modes/interactive/whimsical-messages.js.map +1 -0
  970. package/dist/modes/print-mode.d.ts +28 -0
  971. package/dist/modes/print-mode.d.ts.map +1 -0
  972. package/dist/modes/print-mode.js +131 -0
  973. package/dist/modes/print-mode.js.map +1 -0
  974. package/dist/modes/rpc/jsonl.d.ts +17 -0
  975. package/dist/modes/rpc/jsonl.d.ts.map +1 -0
  976. package/dist/modes/rpc/jsonl.js +49 -0
  977. package/dist/modes/rpc/jsonl.js.map +1 -0
  978. package/dist/modes/rpc/rpc-client.d.ts +224 -0
  979. package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
  980. package/dist/modes/rpc/rpc-client.js +409 -0
  981. package/dist/modes/rpc/rpc-client.js.map +1 -0
  982. package/dist/modes/rpc/rpc-mode.d.ts +20 -0
  983. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -0
  984. package/dist/modes/rpc/rpc-mode.js +601 -0
  985. package/dist/modes/rpc/rpc-mode.js.map +1 -0
  986. package/dist/modes/rpc/rpc-types.d.ts +419 -0
  987. package/dist/modes/rpc/rpc-types.d.ts.map +1 -0
  988. package/dist/modes/rpc/rpc-types.js +8 -0
  989. package/dist/modes/rpc/rpc-types.js.map +1 -0
  990. package/dist/package-manager-cli.d.ts +4 -0
  991. package/dist/package-manager-cli.d.ts.map +1 -0
  992. package/dist/package-manager-cli.js +460 -0
  993. package/dist/package-manager-cli.js.map +1 -0
  994. package/dist/utils/ansi.d.ts +2 -0
  995. package/dist/utils/ansi.d.ts.map +1 -0
  996. package/dist/utils/ansi.js +52 -0
  997. package/dist/utils/ansi.js.map +1 -0
  998. package/dist/utils/changelog.d.ts +21 -0
  999. package/dist/utils/changelog.d.ts.map +1 -0
  1000. package/dist/utils/changelog.js +87 -0
  1001. package/dist/utils/changelog.js.map +1 -0
  1002. package/dist/utils/child-process.d.ts +12 -0
  1003. package/dist/utils/child-process.d.ts.map +1 -0
  1004. package/dist/utils/child-process.js +86 -0
  1005. package/dist/utils/child-process.js.map +1 -0
  1006. package/dist/utils/clipboard-image.d.ts +11 -0
  1007. package/dist/utils/clipboard-image.d.ts.map +1 -0
  1008. package/dist/utils/clipboard-image.js +245 -0
  1009. package/dist/utils/clipboard-image.js.map +1 -0
  1010. package/dist/utils/clipboard-native.d.ts +8 -0
  1011. package/dist/utils/clipboard-native.d.ts.map +1 -0
  1012. package/dist/utils/clipboard-native.js +14 -0
  1013. package/dist/utils/clipboard-native.js.map +1 -0
  1014. package/dist/utils/clipboard.d.ts +2 -0
  1015. package/dist/utils/clipboard.d.ts.map +1 -0
  1016. package/dist/utils/clipboard.js +117 -0
  1017. package/dist/utils/clipboard.js.map +1 -0
  1018. package/dist/utils/exif-orientation.d.ts +5 -0
  1019. package/dist/utils/exif-orientation.d.ts.map +1 -0
  1020. package/dist/utils/exif-orientation.js +158 -0
  1021. package/dist/utils/exif-orientation.js.map +1 -0
  1022. package/dist/utils/frontmatter.d.ts +8 -0
  1023. package/dist/utils/frontmatter.d.ts.map +1 -0
  1024. package/dist/utils/frontmatter.js +26 -0
  1025. package/dist/utils/frontmatter.js.map +1 -0
  1026. package/dist/utils/fs-watch.d.ts +5 -0
  1027. package/dist/utils/fs-watch.d.ts.map +1 -0
  1028. package/dist/utils/fs-watch.js +25 -0
  1029. package/dist/utils/fs-watch.js.map +1 -0
  1030. package/dist/utils/git.d.ts +26 -0
  1031. package/dist/utils/git.d.ts.map +1 -0
  1032. package/dist/utils/git.js +163 -0
  1033. package/dist/utils/git.js.map +1 -0
  1034. package/dist/utils/html.d.ts +7 -0
  1035. package/dist/utils/html.d.ts.map +1 -0
  1036. package/dist/utils/html.js +40 -0
  1037. package/dist/utils/html.js.map +1 -0
  1038. package/dist/utils/image-convert.d.ts +9 -0
  1039. package/dist/utils/image-convert.d.ts.map +1 -0
  1040. package/dist/utils/image-convert.js +39 -0
  1041. package/dist/utils/image-convert.js.map +1 -0
  1042. package/dist/utils/image-resize.d.ts +36 -0
  1043. package/dist/utils/image-resize.d.ts.map +1 -0
  1044. package/dist/utils/image-resize.js +137 -0
  1045. package/dist/utils/image-resize.js.map +1 -0
  1046. package/dist/utils/mime.d.ts +3 -0
  1047. package/dist/utils/mime.d.ts.map +1 -0
  1048. package/dist/utils/mime.js +69 -0
  1049. package/dist/utils/mime.js.map +1 -0
  1050. package/dist/utils/paths.d.ts +16 -0
  1051. package/dist/utils/paths.d.ts.map +1 -0
  1052. package/dist/utils/paths.js +50 -0
  1053. package/dist/utils/paths.js.map +1 -0
  1054. package/dist/utils/photon.d.ts +21 -0
  1055. package/dist/utils/photon.d.ts.map +1 -0
  1056. package/dist/utils/photon.js +121 -0
  1057. package/dist/utils/photon.js.map +1 -0
  1058. package/dist/utils/pi-user-agent.d.ts +2 -0
  1059. package/dist/utils/pi-user-agent.d.ts.map +1 -0
  1060. package/dist/utils/pi-user-agent.js +5 -0
  1061. package/dist/utils/pi-user-agent.js.map +1 -0
  1062. package/dist/utils/shell.d.ts +30 -0
  1063. package/dist/utils/shell.d.ts.map +1 -0
  1064. package/dist/utils/shell.js +190 -0
  1065. package/dist/utils/shell.js.map +1 -0
  1066. package/dist/utils/sleep.d.ts +5 -0
  1067. package/dist/utils/sleep.d.ts.map +1 -0
  1068. package/dist/utils/sleep.js +17 -0
  1069. package/dist/utils/sleep.js.map +1 -0
  1070. package/dist/utils/syntax-highlight.d.ts +12 -0
  1071. package/dist/utils/syntax-highlight.d.ts.map +1 -0
  1072. package/dist/utils/syntax-highlight.js +118 -0
  1073. package/dist/utils/syntax-highlight.js.map +1 -0
  1074. package/dist/utils/tools-manager.d.ts +3 -0
  1075. package/dist/utils/tools-manager.d.ts.map +1 -0
  1076. package/dist/utils/tools-manager.js +325 -0
  1077. package/dist/utils/tools-manager.js.map +1 -0
  1078. package/dist/utils/version-check.d.ts +14 -0
  1079. package/dist/utils/version-check.d.ts.map +1 -0
  1080. package/dist/utils/version-check.js +76 -0
  1081. package/dist/utils/version-check.js.map +1 -0
  1082. package/docs/compaction.md +394 -0
  1083. package/docs/custom-provider.md +646 -0
  1084. package/docs/development.md +71 -0
  1085. package/docs/docs.json +148 -0
  1086. package/docs/extensions.md +2596 -0
  1087. package/docs/images/doom-extension.png +0 -0
  1088. package/docs/images/exy.png +3 -0
  1089. package/docs/images/interactive-mode.png +0 -0
  1090. package/docs/images/tree-view.png +0 -0
  1091. package/docs/index.md +70 -0
  1092. package/docs/json.md +82 -0
  1093. package/docs/keybindings.md +197 -0
  1094. package/docs/models.md +474 -0
  1095. package/docs/packages.md +223 -0
  1096. package/docs/prompt-templates.md +88 -0
  1097. package/docs/providers.md +243 -0
  1098. package/docs/quickstart.md +142 -0
  1099. package/docs/rpc.md +1407 -0
  1100. package/docs/sdk.md +1129 -0
  1101. package/docs/session-format.md +412 -0
  1102. package/docs/sessions.md +137 -0
  1103. package/docs/settings.md +279 -0
  1104. package/docs/shell-aliases.md +13 -0
  1105. package/docs/skills.md +232 -0
  1106. package/docs/terminal-setup.md +106 -0
  1107. package/docs/termux.md +127 -0
  1108. package/docs/themes.md +299 -0
  1109. package/docs/tmux.md +61 -0
  1110. package/docs/tui.md +918 -0
  1111. package/docs/usage.md +277 -0
  1112. package/docs/windows.md +17 -0
  1113. package/examples/README.md +25 -0
  1114. package/examples/extensions/README.md +208 -0
  1115. package/examples/extensions/auto-commit-on-exit.ts +49 -0
  1116. package/examples/extensions/bash-spawn-hook.ts +30 -0
  1117. package/examples/extensions/bookmark.ts +50 -0
  1118. package/examples/extensions/border-status-editor.ts +150 -0
  1119. package/examples/extensions/built-in-tool-renderer.ts +249 -0
  1120. package/examples/extensions/claude-rules.ts +86 -0
  1121. package/examples/extensions/commands.ts +72 -0
  1122. package/examples/extensions/confirm-destructive.ts +59 -0
  1123. package/examples/extensions/custom-compaction.ts +127 -0
  1124. package/examples/extensions/custom-footer.ts +64 -0
  1125. package/examples/extensions/custom-header.ts +73 -0
  1126. package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
  1127. package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
  1128. package/examples/extensions/custom-provider-anthropic/package.json +19 -0
  1129. package/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
  1130. package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
  1131. package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
  1132. package/examples/extensions/dirty-repo-guard.ts +56 -0
  1133. package/examples/extensions/doom-overlay/README.md +46 -0
  1134. package/examples/extensions/doom-overlay/doom/build.sh +152 -0
  1135. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
  1136. package/examples/extensions/doom-overlay/doom-component.ts +132 -0
  1137. package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
  1138. package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
  1139. package/examples/extensions/doom-overlay/index.ts +74 -0
  1140. package/examples/extensions/doom-overlay/wad-finder.ts +51 -0
  1141. package/examples/extensions/dynamic-resources/SKILL.md +8 -0
  1142. package/examples/extensions/dynamic-resources/dynamic.json +79 -0
  1143. package/examples/extensions/dynamic-resources/dynamic.md +5 -0
  1144. package/examples/extensions/dynamic-resources/index.ts +15 -0
  1145. package/examples/extensions/dynamic-tools.ts +74 -0
  1146. package/examples/extensions/event-bus.ts +43 -0
  1147. package/examples/extensions/file-trigger.ts +41 -0
  1148. package/examples/extensions/git-checkpoint.ts +53 -0
  1149. package/examples/extensions/github-issue-autocomplete.ts +185 -0
  1150. package/examples/extensions/handoff.ts +191 -0
  1151. package/examples/extensions/hello.ts +26 -0
  1152. package/examples/extensions/hidden-thinking-label.ts +53 -0
  1153. package/examples/extensions/inline-bash.ts +94 -0
  1154. package/examples/extensions/input-transform.ts +43 -0
  1155. package/examples/extensions/interactive-shell.ts +196 -0
  1156. package/examples/extensions/mac-system-theme.ts +47 -0
  1157. package/examples/extensions/message-renderer.ts +59 -0
  1158. package/examples/extensions/minimal-mode.ts +426 -0
  1159. package/examples/extensions/modal-editor.ts +85 -0
  1160. package/examples/extensions/model-status.ts +31 -0
  1161. package/examples/extensions/notify.ts +55 -0
  1162. package/examples/extensions/overlay-qa-tests.ts +1348 -0
  1163. package/examples/extensions/overlay-test.ts +150 -0
  1164. package/examples/extensions/permission-gate.ts +34 -0
  1165. package/examples/extensions/pirate.ts +47 -0
  1166. package/examples/extensions/plan-mode/README.md +65 -0
  1167. package/examples/extensions/plan-mode/index.ts +340 -0
  1168. package/examples/extensions/plan-mode/utils.ts +168 -0
  1169. package/examples/extensions/preset.ts +430 -0
  1170. package/examples/extensions/prompt-customizer.ts +97 -0
  1171. package/examples/extensions/protected-paths.ts +30 -0
  1172. package/examples/extensions/provider-payload.ts +18 -0
  1173. package/examples/extensions/qna.ts +122 -0
  1174. package/examples/extensions/question.ts +264 -0
  1175. package/examples/extensions/questionnaire.ts +427 -0
  1176. package/examples/extensions/rainbow-editor.ts +88 -0
  1177. package/examples/extensions/reload-runtime.ts +37 -0
  1178. package/examples/extensions/rpc-demo.ts +118 -0
  1179. package/examples/extensions/sandbox/index.ts +321 -0
  1180. package/examples/extensions/sandbox/package-lock.json +92 -0
  1181. package/examples/extensions/sandbox/package.json +19 -0
  1182. package/examples/extensions/send-user-message.ts +97 -0
  1183. package/examples/extensions/session-name.ts +27 -0
  1184. package/examples/extensions/shutdown-command.ts +63 -0
  1185. package/examples/extensions/snake.ts +343 -0
  1186. package/examples/extensions/space-invaders.ts +560 -0
  1187. package/examples/extensions/ssh.ts +220 -0
  1188. package/examples/extensions/status-line.ts +32 -0
  1189. package/examples/extensions/structured-output.ts +65 -0
  1190. package/examples/extensions/subagent/README.md +172 -0
  1191. package/examples/extensions/subagent/agents/planner.md +37 -0
  1192. package/examples/extensions/subagent/agents/reviewer.md +35 -0
  1193. package/examples/extensions/subagent/agents/scout.md +50 -0
  1194. package/examples/extensions/subagent/agents/worker.md +24 -0
  1195. package/examples/extensions/subagent/agents.ts +126 -0
  1196. package/examples/extensions/subagent/index.ts +987 -0
  1197. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
  1198. package/examples/extensions/subagent/prompts/implement.md +10 -0
  1199. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
  1200. package/examples/extensions/summarize.ts +206 -0
  1201. package/examples/extensions/system-prompt-header.ts +17 -0
  1202. package/examples/extensions/tic-tac-toe.ts +1008 -0
  1203. package/examples/extensions/timed-confirm.ts +70 -0
  1204. package/examples/extensions/titlebar-spinner.ts +58 -0
  1205. package/examples/extensions/todo.ts +297 -0
  1206. package/examples/extensions/tool-override.ts +144 -0
  1207. package/examples/extensions/tools.ts +141 -0
  1208. package/examples/extensions/trigger-compact.ts +50 -0
  1209. package/examples/extensions/truncated-tool.ts +195 -0
  1210. package/examples/extensions/widget-placement.ts +9 -0
  1211. package/examples/extensions/with-deps/index.ts +32 -0
  1212. package/examples/extensions/with-deps/package-lock.json +31 -0
  1213. package/examples/extensions/with-deps/package.json +22 -0
  1214. package/examples/extensions/working-indicator.ts +123 -0
  1215. package/examples/extensions/working-message-test.ts +25 -0
  1216. package/examples/rpc-extension-ui.ts +632 -0
  1217. package/examples/sdk/01-minimal.ts +26 -0
  1218. package/examples/sdk/02-custom-model.ts +53 -0
  1219. package/examples/sdk/03-custom-prompt.ts +75 -0
  1220. package/examples/sdk/04-skills.ts +55 -0
  1221. package/examples/sdk/05-tools.ts +48 -0
  1222. package/examples/sdk/06-extensions.ts +99 -0
  1223. package/examples/sdk/07-context-files.ts +47 -0
  1224. package/examples/sdk/08-prompt-templates.ts +51 -0
  1225. package/examples/sdk/09-api-keys-and-oauth.ts +52 -0
  1226. package/examples/sdk/10-settings.ts +53 -0
  1227. package/examples/sdk/11-sessions.ts +52 -0
  1228. package/examples/sdk/12-full-control.ts +77 -0
  1229. package/examples/sdk/13-session-runtime.ts +67 -0
  1230. package/examples/sdk/README.md +144 -0
  1231. package/package.json +94 -19
  1232. package/bin/atomic +0 -82
  1233. /package/{LICENSE → dist/builtin/workflows/LICENSE} +0 -0
@@ -0,0 +1,2143 @@
1
+ import { renderCall } from "./render-call.js";
2
+ import { renderResult } from "./render-result.js";
3
+ import type { RenderResultOpts, WorkflowInputEntry, WorkflowToolResult } from "./render-result.js";
4
+ import { renderInputsSchema } from "../shared/render-inputs-schema.js";
5
+ import { WorkflowParametersSchema } from "./workflow-schema.js";
6
+ import { renderRunBanner, renderRunSummary } from "./renderers.js";
7
+ import type { RunEndPayload, RunStartPayload } from "./renderers.js";
8
+ import { store } from "../shared/store.js";
9
+ import { restoreOnSessionStart } from "../shared/persistence-restore.js";
10
+ import type { SessionManager } from "../shared/persistence-restore.js";
11
+ import { installCompactionHook } from "../shared/persistence-compaction-policy.js";
12
+ import {
13
+ killRun,
14
+ killAllRuns,
15
+ resumeRun,
16
+ pauseRun,
17
+ inspectRun,
18
+ } from "../runs/background/status.js";
19
+ import { cancellationRegistry } from "../runs/background/cancellation-registry.js";
20
+ import { registerIntercomParentSession } from "../intercom/intercom-bridge.js";
21
+ import { subscribeIntercomControl } from "../intercom/result-intercom.js";
22
+ import { buildIntercomCallbacks } from "../intercom/intercom-routing.js";
23
+ import {
24
+ installStoreWidget,
25
+ installToolExecutionHooks,
26
+ } from "../tui/store-widget-installer.js";
27
+ import type { WidgetFactory } from "../tui/store-widget-installer.js";
28
+ import { buildGraphOverlayAdapter } from "../tui/overlay-adapter.js";
29
+ import type { OverlayPiSurface } from "../tui/overlay-adapter.js";
30
+ import type { GraphOverlayPort } from "../tui/overlay-adapter.js";
31
+ import { renderSessionList } from "../tui/session-list.js";
32
+ import { selectRunsForPicker } from "../tui/session-picker.js";
33
+
34
+ import { openSessionPicker, openKillConfirm } from "../tui/session-overlays.js";
35
+ import {
36
+ openInlineInputsForm,
37
+ registerInlineFormRenderer,
38
+ } from "../tui/inline-form-overlay.js";
39
+ import {
40
+ registerChatSurfaceRenderer,
41
+ emitChatSurface,
42
+ } from "../tui/chat-surface-message.js";
43
+ import { openInputsPicker } from "../tui/inputs-overlay.js";
44
+ import { deriveGraphTheme } from "../tui/graph-theme.js";
45
+ import { createExtensionRuntime } from "./runtime.js";
46
+ import type { ExtensionRuntime } from "./runtime.js";
47
+ import {
48
+ discoverWorkflows,
49
+ discoverStartupWorkflowsSync,
50
+ } from "./discovery.js";
51
+ import type { DiscoveryResult } from "./discovery.js";
52
+ import {
53
+ loadWorkflowConfig,
54
+ toScopedDiscoveryConfig,
55
+ WORKFLOW_CONFIG_DEFAULTS,
56
+ withWorkflowDefaults,
57
+ } from "./config-loader.js";
58
+ import type { ConfigLoadResult } from "./config-loader.js";
59
+ import type {
60
+ WorkflowPersistencePort,
61
+ WorkflowMcpPort,
62
+ WorkflowRuntimeConfig,
63
+ WorkflowChainStep,
64
+ WorkflowDirectTaskItem,
65
+ WorkflowDetails,
66
+ WorkflowMaxOutput,
67
+ WorkflowModelCatalogPort,
68
+ WorkflowModelInfo,
69
+ } from "../shared/types.js";import { buildRuntimeAdapters } from "./wiring.js";
70
+ import type { PiUISurface } from "./wiring.js";
71
+ import { createStatusWriter } from "./status-writer.js";
72
+ import type { StatusWriter } from "./status-writer.js";
73
+ import { setMcpScope, clearMcpScope } from "./mcp.js";
74
+ import type { PiMcpExtensionAPI, PiEventBus } from "./mcp.js";
75
+ import type { StageSessionRuntime } from "../runs/foreground/stage-runner.js";
76
+ import type { CreateAgentSessionOptions } from "@earendil-works/pi-coding-agent";
77
+
78
+ // ---------------------------------------------------------------------------
79
+ // Minimal ExtensionAPI structural types
80
+ // No `any`; all optional fields use explicit union with undefined.
81
+ // cross-ref: pi docs/skills/authoring-extensions.md (ExtensionAPI shape)
82
+ // ---------------------------------------------------------------------------
83
+
84
+ /** Theme object passed to renderCall/renderResult slots (opaque — not consumed in stubs). */
85
+ export type PiTheme = Record<string, string>;
86
+
87
+ /** Context object passed to renderCall/renderResult slots. */
88
+ export interface PiRenderContext {
89
+ state?: {
90
+ runId?: string;
91
+ stages?: unknown[];
92
+ };
93
+ invalidate?: () => void;
94
+ }
95
+
96
+ /** Options bag passed to renderResult. */
97
+ export interface PiRenderResultOpts extends RenderResultOpts {}
98
+
99
+ export interface PiRenderComponent {
100
+ render(width: number): string[];
101
+ invalidate?: () => void;
102
+ includes(searchString: string): boolean;
103
+ }
104
+
105
+ function textRenderComponent(text: string): PiRenderComponent {
106
+ return {
107
+ render(_width: number): string[] {
108
+ return text.split("\n");
109
+ },
110
+ includes(searchString: string): boolean {
111
+ return text.includes(searchString);
112
+ },
113
+ };
114
+ }
115
+
116
+ /**
117
+ * Completion for a slash-command argument. Matches pi-tui's `AutocompleteItem`.
118
+ * `value` is the text inserted on selection; `label` is the menu display; the
119
+ * optional `description` is the secondary line. Without `value`, pi-tui crashes
120
+ * in `getBestAutocompleteMatchIndex` (`value.startsWith(prefix)`).
121
+ * cross-ref: @earendil-works/pi-tui autocomplete AutocompleteItem
122
+ */
123
+ export interface PiArgumentCompletion {
124
+ value: string;
125
+ label: string;
126
+ description?: string;
127
+ }
128
+
129
+ /**
130
+ * Canonical slash command options for pi.registerCommand(name, options).
131
+ * Mirrors `RegisteredCommand` from pi's `extensibility/extensions/types.ts`
132
+ * minus the `name` field (which is the first arg to registerCommand).
133
+ * cross-ref: research/docs/2026-05-11-pi-coding-agent-reference.md §4.2
134
+ */
135
+ export type PiArgumentCompletionResult = PiArgumentCompletion[] | null;
136
+
137
+ export interface PiCommandOptions {
138
+ description: string;
139
+ handler: (args: string, ctx: PiCommandContext) => Promise<void> | void;
140
+ getArgumentCompletions?: (
141
+ partial: string,
142
+ ) => PiArgumentCompletionResult;
143
+ }
144
+
145
+ /**
146
+ * Context provided to slash command handlers. Aligns with pi's
147
+ * `ExtensionCommandContext` (subset of what we actually consume): the
148
+ * host always supplies `ui` and `ui.notify`, so callers print via
149
+ * `ctx.ui.notify("…", "info")` directly — no wrapper indirection.
150
+ */
151
+ interface PiRuntimeModel {
152
+ readonly provider: string;
153
+ readonly id: string;
154
+ }
155
+
156
+ interface PiRuntimeModelRegistry {
157
+ getAvailable(): PiRuntimeModel[];
158
+ }
159
+
160
+ interface PiModelContext {
161
+ readonly model?: PiRuntimeModel;
162
+ readonly modelRegistry?: PiRuntimeModelRegistry;
163
+ }
164
+
165
+ export interface PiCommandContext extends PiModelContext {
166
+ ui: {
167
+ notify: (message: string, type?: "info" | "warning" | "error") => void;
168
+ } & PiUISurface;
169
+ }
170
+
171
+ /** CLI flag registration options. Mirrors the inline options on `ExtensionAPI.registerFlag`. */
172
+ export interface PiFlagNamedOpts {
173
+ description: string;
174
+ type?: "string" | "boolean";
175
+ default?: unknown;
176
+ }
177
+
178
+ /**
179
+ * Pi's AgentToolResult shape — returned by `execute` and consumed by
180
+ * `renderResult`. `details` carries the original workflow result for the
181
+ * renderer; `content` is what the model sees on tool completion.
182
+ */
183
+ export interface PiAgentToolResult<TDetails> {
184
+ content: Array<
185
+ { type: "text"; text: string } | { type: "image"; [key: string]: unknown }
186
+ >;
187
+ details: TDetails;
188
+ terminate?: boolean;
189
+ }
190
+
191
+ /** Tool registration options aligned with pi's `ToolDefinition`. */
192
+ export interface PiToolOpts<TArgs, TDetails> {
193
+ name: string;
194
+ label: string;
195
+ description: string;
196
+ parameters: unknown; // TypeBox TSchema — pi consumes it opaquely
197
+ /**
198
+ * Pi calls execute positionally: `(toolCallId, params, signal, onUpdate, ctx)`.
199
+ * cross-ref: pi-coding-agent dist/core/extensions/types.d.ts ToolDefinition.execute
200
+ */
201
+ execute: (
202
+ toolCallId: string,
203
+ params: TArgs,
204
+ signal: AbortSignal | undefined,
205
+ onUpdate: ((partial: PiAgentToolResult<TDetails>) => void) | undefined,
206
+ ctx: PiExecuteContext,
207
+ ) => Promise<PiAgentToolResult<TDetails>>;
208
+ /** Pi passes args directly as the first positional arg (not wrapped). */
209
+ renderCall?: (
210
+ args: TArgs,
211
+ theme: PiTheme,
212
+ context: PiRenderContext,
213
+ ) => PiRenderComponent | string;
214
+ /** Pi passes the full AgentToolResult as the first positional arg. */
215
+ renderResult?: (
216
+ result: PiAgentToolResult<TDetails>,
217
+ opts: PiRenderResultOpts,
218
+ theme: PiTheme,
219
+ context: PiRenderContext,
220
+ ) => PiRenderComponent | string;
221
+ }
222
+
223
+ /** Execution context provided to tool execute handlers. */
224
+ export interface PiExecuteContext extends PiModelContext {
225
+ sessionId?: string;
226
+ ui?: PiUISurface;
227
+ hasUI?: boolean;
228
+ sessionManager?: SessionManager & { getSessionFile?: () => string | undefined };
229
+ [key: string]: unknown;
230
+ }
231
+
232
+ /**
233
+ * Structural subset of pi's `ExtensionAPI` (see
234
+ * `packages/coding-agent/src/extensibility/extensions/types.ts`) covering
235
+ * the methods this extension consumes. Fields are optional so test
236
+ * mocks can stub a minimal surface; production runtime supplies all of
237
+ * them.
238
+ */
239
+ export interface ExtensionAPI {
240
+ registerTool?: <TArgs, TResult>(opts: PiToolOpts<TArgs, TResult>) => void;
241
+ /**
242
+ * `pi.registerCommand(name, options)` — sole slash-command registration
243
+ * surface. Mirrors pi's `ExtensionAPI.registerCommand`.
244
+ */
245
+ registerCommand?: (name: string, options: PiCommandOptions) => void;
246
+ registerMessageRenderer?: (
247
+ event: string,
248
+ renderer: (payload: unknown) => string,
249
+ ) => void;
250
+ /**
251
+ * Inject a custom message into the chat history. Used by the inline
252
+ * workflow input form to emit a sticky card under `customType:
253
+ * "workflows:input-form"`. The card stays in scrollback and is
254
+ * re-rendered by the registered renderer on every `tui.requestRender()`.
255
+ */
256
+ sendMessage?: <T = unknown>(
257
+ message: {
258
+ customType: string;
259
+ content?: string;
260
+ display?: boolean;
261
+ details?: T;
262
+ },
263
+ options?: {
264
+ triggerTurn?: boolean;
265
+ deliverAs?: "steer" | "followUp" | "nextTurn";
266
+ },
267
+ ) => void | Promise<void>;
268
+ registerFlag?: (name: string, opts: PiFlagNamedOpts) => void;
269
+ /**
270
+ * Register a keyboard shortcut.
271
+ * Present on pi >= 1.x; absent on older runtimes.
272
+ */
273
+ registerShortcut?: (
274
+ key: string,
275
+ opts: {
276
+ description: string;
277
+ handler: (ctx?: PiCommandContext) => void | Promise<void>;
278
+ },
279
+ ) => void;
280
+ /**
281
+ * Sets the current session name. Present on pi's ExtensionAPI.
282
+ */
283
+ setSessionName?: (name: string) => void | Promise<void>;
284
+ /**
285
+ * pi events bus — used for workflow-scoped MCP events and subagent
286
+ * lifecycle/result routing.
287
+ */
288
+ events?: {
289
+ emit?: (event: string, payload: Record<string, unknown>) => void;
290
+ on?: (event: string, handler: (payload: unknown) => void) => void;
291
+ };
292
+ /**
293
+ * Execute a shell command and return stdout/stderr/exit code.
294
+ * Present on the pi ExtensionAPI.
295
+ */
296
+ exec?: (
297
+ command: string,
298
+ args: string[],
299
+ opts?: { signal?: AbortSignal; timeout?: number },
300
+ ) => Promise<{
301
+ stdout: string;
302
+ stderr: string;
303
+ code: number;
304
+ killed: boolean;
305
+ }>;
306
+ /** Test seam: inject a stub session factory instead of importing the pi SDK at runtime. */
307
+ createAgentSession?: (
308
+ options?: CreateAgentSessionOptions,
309
+ ) => Promise<{ session: StageSessionRuntime }>;
310
+ /** Test/degraded-runtime seam: skip project/global discovery work at startup. */
311
+ disableAsyncDiscovery?: boolean;
312
+ // -------------------------------------------------------------------------
313
+ // Persistence API (§5.6)
314
+ // -------------------------------------------------------------------------
315
+ /** Appends a typed entry to the session transcript. Returns the entry ID. */
316
+ appendEntry?: (
317
+ type: string,
318
+ payload: Record<string, unknown>,
319
+ ) => string | undefined;
320
+ /** Labels an entry for /tree bookmark filtering. */
321
+ setLabel?: (entryId: string, label: string) => void;
322
+ /** Appends a synthetic system/assistant message entry. */
323
+ appendCustomMessageEntry?: (
324
+ content: string,
325
+ meta?: Record<string, unknown>,
326
+ ) => string | undefined;
327
+ // -------------------------------------------------------------------------
328
+ // Lifecycle events (§5.6, §8.1 Phase D)
329
+ // -------------------------------------------------------------------------
330
+ /** Register a listener for a pi lifecycle event (e.g. session_start, session_before_compact). */
331
+ on?: (
332
+ event: string,
333
+ handler: (
334
+ event?: unknown,
335
+ ctx?: PiCommandContext & {
336
+ sessionManager?: SessionManager;
337
+ hasUI?: boolean;
338
+ },
339
+ ) => void | object | Promise<void | object>,
340
+ ) => void;
341
+ // -------------------------------------------------------------------------
342
+ // Session manager (§5.6 restore)
343
+ // -------------------------------------------------------------------------
344
+ sessionManager?: SessionManager;
345
+ ui?: {
346
+ setWidget?: (
347
+ key: string,
348
+ factory: WidgetFactory | undefined,
349
+ opts?: { placement?: string },
350
+ ) => void;
351
+ /**
352
+ * Spawn a custom TUI component (overlay or inline).
353
+ * When overlay: true, the panel floats over existing content.
354
+ * Returns a handle with close() to dismiss, or undefined when unsupported.
355
+ */
356
+ custom?: PiUISurface["custom"];
357
+ } & PiUISurface;
358
+ [key: string]: unknown;
359
+ }
360
+
361
+ // ---------------------------------------------------------------------------
362
+ // Workflow tool argument shape
363
+ // ---------------------------------------------------------------------------
364
+
365
+ export interface WorkflowToolArgs {
366
+ /** Canonical named workflow identifier. */
367
+ workflow?: string;
368
+ inputs?: Record<string, unknown>;
369
+ action?: "run" | "list" | "get" | "status" | "interrupt" | "resume" | "inputs";
370
+ /** Canonical run identifier for status/interrupt/resume. */
371
+ runId?: string;
372
+ /** Direct single-task mode, or root task string when chain is present. */
373
+ task?: WorkflowDirectTaskItem | string;
374
+ /** Direct top-level parallel mode. */
375
+ tasks?: WorkflowDirectTaskItem[];
376
+ /** Direct sequential/parallel chain mode. */
377
+ chain?: WorkflowChainStep[];
378
+ chainName?: string;
379
+ context?: "fresh" | "fork";
380
+ /** Internal host-derived parent session file for context:"fork". */
381
+ forkFromSessionFile?: string;
382
+ concurrency?: number;
383
+ async?: boolean;
384
+ intercom?: {
385
+ enabled?: boolean;
386
+ delivery?: "off" | "notify" | "result" | "control-and-result";
387
+ parentSession?: string;
388
+ notifyOn?: Array<"active_long_running" | "needs_attention" | "completed" | "failed">;
389
+ };
390
+ cwd?: string;
391
+ output?: string | false;
392
+ outputMode?: "inline" | "file-only";
393
+ chainDir?: string;
394
+ maxOutput?: WorkflowMaxOutput;
395
+ artifacts?: boolean;
396
+ sessionDir?: string;
397
+ progress?: boolean;
398
+ worktree?: boolean;
399
+ fallbackModels?: string[];
400
+ }
401
+
402
+ // ---------------------------------------------------------------------------
403
+ // Tool parameter schema
404
+ // ---------------------------------------------------------------------------
405
+
406
+ const workflowParameters = WorkflowParametersSchema;
407
+
408
+ function hasDirectExecutionMode(args: WorkflowToolArgs): boolean {
409
+ return (
410
+ (args.task !== undefined && typeof args.task === "object") ||
411
+ Array.isArray(args.tasks) ||
412
+ Array.isArray(args.chain)
413
+ );
414
+ }
415
+
416
+ function directModeCount(args: WorkflowToolArgs): number {
417
+ return [
418
+ args.task !== undefined && typeof args.task === "object",
419
+ Array.isArray(args.tasks),
420
+ Array.isArray(args.chain),
421
+ ].filter(Boolean).length;
422
+ }
423
+
424
+ function hasNamedExecutionMode(args: WorkflowToolArgs): boolean {
425
+ return (
426
+ typeof args.workflow === "string" && args.workflow.trim().length > 0
427
+ );
428
+ }
429
+
430
+ function directRequestsFork(args: WorkflowToolArgs): boolean {
431
+ if (args.context === "fork") return true;
432
+ if (args.task !== undefined && typeof args.task === "object" && args.task.context === "fork") return true;
433
+ if (args.tasks?.some((task) => task.context === "fork")) return true;
434
+ return args.chain?.some((step) =>
435
+ "parallel" in step
436
+ ? step.parallel.some((task) => task.context === "fork")
437
+ : step.context === "fork",
438
+ ) ?? false;
439
+ }
440
+
441
+ function withForkParentSession(args: WorkflowToolArgs, ctx: PiExecuteContext): WorkflowToolArgs {
442
+ if (!directRequestsFork(args) || args.forkFromSessionFile !== undefined) return args;
443
+ const sessionFile = ctx.sessionManager?.getSessionFile?.();
444
+ return typeof sessionFile === "string" && sessionFile.length > 0
445
+ ? { ...args, forkFromSessionFile: sessionFile }
446
+ : args;
447
+ }
448
+
449
+ function workflowRunResultFromDetails(details: WorkflowDetails): WorkflowToolResult {
450
+ return {
451
+ action: "run",
452
+ name: `direct-${details.mode}`,
453
+ runId: details.runId ?? "",
454
+ status: details.status,
455
+ result: details.output,
456
+ details,
457
+ error: details.error,
458
+ stages: [],
459
+ };
460
+ }
461
+
462
+ function workflowGetResult(runtime: ExtensionRuntime, args: WorkflowToolArgs): WorkflowToolResult {
463
+ const workflow = args.workflow ?? "";
464
+ const def = runtime.registry.get(workflow);
465
+ if (!def) {
466
+ return {
467
+ action: "get",
468
+ workflow,
469
+ error: `Workflow not found: "${workflow}"`,
470
+ };
471
+ }
472
+ const inputs = Object.entries(def.inputs).map(([name, schema]) => ({
473
+ name,
474
+ type: schema.type,
475
+ description: schema.description,
476
+ required: schema.required,
477
+ default: "default" in schema ? schema.default : undefined,
478
+ choices: schema.type === "select" ? schema.choices : undefined,
479
+ }));
480
+ return {
481
+ action: "get",
482
+ workflow: def.normalizedName,
483
+ details: {
484
+ mode: "inspection",
485
+ action: "get",
486
+ status: "completed",
487
+ output: {
488
+ workflow: def.normalizedName,
489
+ name: def.name,
490
+ description: def.description,
491
+ inputs,
492
+ },
493
+ progress: { completed: 0, total: 0 },
494
+ },
495
+ };
496
+ }
497
+
498
+ // ---------------------------------------------------------------------------
499
+ // Tool execute — dispatch with real registry for list/inputs/run (Phase E)
500
+ // + real status/interrupt/resume (Phase D)
501
+ // ---------------------------------------------------------------------------
502
+
503
+ export function makeExecuteWorkflowTool(
504
+ runtime: ExtensionRuntime | ((ctx: PiExecuteContext) => ExtensionRuntime),
505
+ getPersistence: () => WorkflowPersistencePort | undefined,
506
+ ) {
507
+ return async function executeWorkflowTool(
508
+ args: WorkflowToolArgs,
509
+ ctx: PiExecuteContext,
510
+ ): Promise<WorkflowToolResult> {
511
+ const action = args.action ?? "run";
512
+ const runId = args.runId ?? "";
513
+ const activeRuntime =
514
+ typeof runtime === "function" ? runtime(ctx) : runtime;
515
+
516
+ switch (action) {
517
+ case "get":
518
+ return workflowGetResult(activeRuntime, args);
519
+
520
+ case "list":
521
+ case "inputs":
522
+ case "run":
523
+ if (action === "run" && hasDirectExecutionMode(args)) {
524
+ const normalModeCount = directModeCount(args) + (hasNamedExecutionMode(args) ? 1 : 0);
525
+ if (normalModeCount !== 1) {
526
+ throw new Error("Workflow extension: specify exactly one normal execution mode: workflow, task, tasks, or chain");
527
+ }
528
+ const details = await activeRuntime.runDirect(withForkParentSession(args, ctx));
529
+ return workflowRunResultFromDetails(details);
530
+ }
531
+ // Delegate to registry-backed dispatcher.
532
+ // Real errors propagate — no broad catch.
533
+ return activeRuntime.dispatch(args);
534
+
535
+ case "status": {
536
+ // Detail mode — single-run lookup via id.
537
+ const target = args.runId;
538
+ if (target !== undefined) {
539
+ const result = inspectRun(target);
540
+ if (result.ok) {
541
+ return {
542
+ action: "statusDetail",
543
+ runId: result.runId,
544
+ detail: result.detail,
545
+ };
546
+ }
547
+ return {
548
+ action: "statusDetail",
549
+ runId: target,
550
+ error: `run not found: ${target}`,
551
+ };
552
+ }
553
+ // List mode — emit live snapshots; the renderer produces the
554
+ // canonical band + card surface.
555
+ const snapshots = store.runs().filter((r) => r.endedAt === undefined);
556
+ return {
557
+ action: "status",
558
+ snapshots: snapshots.map(
559
+ (s) => JSON.parse(JSON.stringify(s)) as typeof s,
560
+ ),
561
+ };
562
+ }
563
+
564
+ case "interrupt": {
565
+ // Support canonical interrupt-all via runId sentinel.
566
+ if (runId === "--all") {
567
+ const results = killAllRuns({
568
+ cancellation: cancellationRegistry,
569
+ persistence: getPersistence(),
570
+ });
571
+ const killed = results.filter((r) => r.ok).length;
572
+ return {
573
+ action,
574
+ runId: "--all",
575
+ status: killed > 0 ? "killed" : "noop",
576
+ message:
577
+ killed > 0
578
+ ? `Interrupted ${killed} run(s).`
579
+ : "No in-flight runs to interrupt.",
580
+ };
581
+ }
582
+ const result = killRun(runId, {
583
+ cancellation: cancellationRegistry,
584
+ persistence: getPersistence(),
585
+ });
586
+ if (result.ok) {
587
+ return {
588
+ action,
589
+ runId: result.runId,
590
+ status: "killed",
591
+ message: `Run ${result.runId} interrupted (was ${result.previousStatus}).`,
592
+ };
593
+ }
594
+ return {
595
+ action,
596
+ runId,
597
+ status: "noop",
598
+ message:
599
+ result.reason === "not_found"
600
+ ? `Run not found: ${runId}`
601
+ : `Run already ended: ${runId}`,
602
+ };
603
+ }
604
+
605
+ case "resume": {
606
+ const result = resumeRun(runId);
607
+ if (result.ok) {
608
+ return {
609
+ action: "resume",
610
+ runId: result.runId,
611
+ status: "ok",
612
+ message: `Snapshot available: run ${result.runId} (${result.snapshot.name}) \u2014 status: ${result.snapshot.status}, stages: ${result.snapshot.stages.length}`,
613
+ };
614
+ }
615
+ return {
616
+ action: "resume",
617
+ runId,
618
+ status: "noop",
619
+ message: `Run not found: ${runId}`,
620
+ };
621
+ }
622
+
623
+ default: {
624
+ // Exhaustive — all action variants handled above.
625
+ const _exhaustive: never = action;
626
+ throw new Error(`Workflow extension: unknown action "${_exhaustive}"`);
627
+ }
628
+ }
629
+ };
630
+ }
631
+
632
+ // ---------------------------------------------------------------------------
633
+ // Slash command helpers
634
+ // ---------------------------------------------------------------------------
635
+
636
+ /**
637
+ * Local registry of workflow command (name → handler). Populated by
638
+ * `registerWorkflowCommand` alongside the host registration so the
639
+ * `on("input", …)` interceptor below can dispatch our commands directly
640
+ * — bypassing pi's optimistic `startPendingSubmission` flow which
641
+ * fires the `Working… (esc to interrupt)` loader before the host knows
642
+ * the input is a synchronous picker/connect UI, not a streaming turn.
643
+ *
644
+ * See `installInputInterceptor()` for the dispatch path and rationale.
645
+ */
646
+ type WorkflowCommandHandler = PiCommandOptions["handler"];
647
+
648
+ /**
649
+ * Register a slash command with the host AND remember the handler so
650
+ * the input interceptor can dispatch directly.
651
+ *
652
+ * `pi.registerCommand` is the sole supported registration surface
653
+ * (mirrors pi's `ExtensionAPI.registerCommand`). When the host
654
+ * lacks `registerCommand` (degraded runtime — RPC mode, headless, or a
655
+ * mock that didn't stub it) we still populate the registry so the
656
+ * input interceptor can intercept the command text the user typed.
657
+ *
658
+ * We forward to `pi.registerCommand` first so any host-side wrapping
659
+ * (telemetry, logging, sandboxing) of `options.handler` lands in the
660
+ * registry; the input interceptor then dispatches the same callable
661
+ * the host would dispatch from `session.prompt`.
662
+ */
663
+ function registerWorkflowCommand(
664
+ pi: ExtensionAPI,
665
+ name: string,
666
+ options: PiCommandOptions,
667
+ registry: Map<string, WorkflowCommandHandler>,
668
+ ): void {
669
+ pi.registerCommand?.(name, options);
670
+ registry.set(name, options.handler);
671
+ }
672
+
673
+ /**
674
+ * Install an `on("input", …)` interceptor that short-circuits the host
675
+ * submission pipeline for our registered workflow commands.
676
+ *
677
+ * Why this exists
678
+ * ---------------
679
+ * pi's editor `onSubmit` handler unconditionally calls
680
+ * `startPendingSubmission` for any text that isn't a built-in slash /
681
+ * skill / bash / python command — this echoes the message into chat
682
+ * scrollback AND starts the `Working… (esc to interrupt)` loader in
683
+ * `statusContainer` before `session.prompt` even runs. The loader is
684
+ * an optimistic affordance for the agent-streaming case; for our
685
+ * synchronous picker/connect UIs (`/workflow connect`, `/workflow run`,
686
+ * `/workflow pause`, …) it's noise — the
687
+ * spinner sits above the picker until the handler returns.
688
+ *
689
+ * `runner.emitInput` runs BEFORE `startPendingSubmission` (see
690
+ * `packages/coding-agent/src/modes/controllers/input-controller.ts`
691
+ * `setupEditorSubmitHandler`). Returning `{ action: "handled" }` from an
692
+ * `on("input", …)` handler short-circuits the function: the host
693
+ * clears the editor and returns without echoing or starting the
694
+ * loader. We dispatch the command handler ourselves with the same
695
+ * context the host would have passed.
696
+ *
697
+ * Shape note: pi's `InputEventResult` is `{ action: "continue" } |
698
+ * { action: "transform"; text; images? } | { action: "handled" }`. The
699
+ * older `{ handled: true }` shape is silently ignored by the runner
700
+ * (`result?.action === "handled"` check), which lets the loader fire.
701
+ *
702
+ * cross-ref:
703
+ * - pi docs/extensions.md (input event)
704
+ * - pi docs/slash-command-internals.md (#tryExecuteExtensionCommand)
705
+ * - pi packages/coding-agent/src/modes/interactive-mode.ts
706
+ * `startPendingSubmission` / `ensureLoadingAnimation`
707
+ */
708
+ function installInputInterceptor(
709
+ pi: ExtensionAPI,
710
+ commands: Map<string, WorkflowCommandHandler>,
711
+ ): void {
712
+ if (typeof pi.on !== "function") return;
713
+
714
+ pi.on("input", async (event, ctx) => {
715
+ const text = (event as { text?: unknown } | undefined)?.text;
716
+ if (typeof text !== "string") return undefined;
717
+ const trimmed = text.trim();
718
+ if (!trimmed.startsWith("/")) return undefined;
719
+
720
+ // First token (after `/`) is the command name. Whitespace splits
721
+ // command from args; quote handling lives inside the command
722
+ // handler itself (`tokenizeWorkflowArgs`).
723
+ const firstSpace = trimmed.indexOf(" ");
724
+ const name = firstSpace === -1 ? trimmed.slice(1) : trimmed.slice(1, firstSpace);
725
+ const handler = commands.get(name);
726
+ if (!handler) return undefined; // not ours — let host run its normal flow.
727
+
728
+ const args = firstSpace === -1 ? "" : trimmed.slice(firstSpace + 1);
729
+ const commandCtx = ctx as PiCommandContext;
730
+ try {
731
+ await handler(args, commandCtx);
732
+ } catch (err) {
733
+ // Match the host command runner: swallow handler exceptions so a
734
+ // throw never bubbles out and crashes the editor submit pipeline.
735
+ // Surface the failure via `ctx.ui.notify` so the user sees it.
736
+ const message = err instanceof Error ? err.message : String(err);
737
+ commandCtx.ui.notify(`/${name} failed: ${message}`, "error");
738
+ }
739
+ return { action: "handled" };
740
+ });
741
+ }
742
+
743
+
744
+ /**
745
+ * Resolve a user-supplied run identifier (full UUID or unique prefix) to
746
+ * a concrete runId. The widget surfaces an 8-char prefix to keep the
747
+ * status line scannable; users copy that prefix straight into the interrupt
748
+ * slash command, so prefix matching is the expected affordance.
749
+ */
750
+ type RunIdResolution =
751
+ | { kind: "exact"; runId: string }
752
+ | { kind: "ambiguous"; matches: string[] }
753
+ | { kind: "not_found" };
754
+
755
+ function resolveRunIdPrefix(target: string): RunIdResolution {
756
+ const runs = store.runs();
757
+ const exact = runs.find((r) => r.id === target);
758
+ if (exact) return { kind: "exact", runId: exact.id };
759
+
760
+ const prefixed = runs.filter((r) => r.id.startsWith(target));
761
+ if (prefixed.length === 0) return { kind: "not_found" };
762
+ if (prefixed.length === 1) return { kind: "exact", runId: prefixed[0]!.id };
763
+ return { kind: "ambiguous", matches: prefixed.map((r) => r.id) };
764
+ }
765
+
766
+ function overlaySurfaceFromContext(ctx?: {
767
+ ui?: PiUISurface;
768
+ }): OverlayPiSurface | undefined {
769
+ // Only forward `ctx.ui` to the overlay adapter when it actually
770
+ // carries the `custom` mount surface. Inline pickers (replace-editor)
771
+ // hand us a print-only `ui.notify` which would otherwise shadow
772
+ // `pi.ui` inside the adapter and short-circuit the open.
773
+ return typeof ctx?.ui?.custom === "function" ? { ui: ctx.ui } : undefined;
774
+ }
775
+
776
+ /**
777
+ * Strip the clack-style `--yes` / `-y` confirmation skip flag from a token
778
+ * list. Used by `/workflow interrupt` to skip the confirmation overlay.
779
+ */
780
+ export function stripYesFlag(tokens: string[]): { tokens: string[]; yes: boolean } {
781
+ const yes = tokens.some((t) => t === "--yes" || t === "-y");
782
+ return { tokens: tokens.filter((t) => t !== "--yes" && t !== "-y"), yes };
783
+ }
784
+
785
+ /**
786
+ * Shell-aware split for `/workflow <name> [args…]` chat tokens.
787
+ *
788
+ * `prompt="map the codebase"` is one token, not three. Both single and
789
+ * double quotes are honoured; the quote characters themselves are kept
790
+ * inside the token so {@link parseWorkflowArgs} can `JSON.parse` the
791
+ * value and the wrapping quotes coerce it back to a plain string.
792
+ * Backslash-escaping is **not** supported — workflow inputs are short,
793
+ * the picker overlay is always available as a fallback for anything
794
+ * exotic, and the simpler grammar matches what users type in shells.
795
+ *
796
+ * An unterminated quote is treated as if a closing quote sat at EOL —
797
+ * we never throw on user input mid-stream; the parser downstream sees
798
+ * a partial JSON literal and falls back to keeping it as a string.
799
+ */
800
+ export function tokenizeWorkflowArgs(args: string): string[] {
801
+ const tokens: string[] = [];
802
+ let buf = "";
803
+ let quote: '"' | "'" | undefined;
804
+ let hasBuf = false;
805
+ for (let i = 0; i < args.length; i++) {
806
+ const ch = args[i]!;
807
+ if (quote !== undefined) {
808
+ buf += ch;
809
+ if (ch === quote) quote = undefined;
810
+ continue;
811
+ }
812
+ if (ch === '"' || ch === "'") {
813
+ buf += ch;
814
+ hasBuf = true;
815
+ quote = ch;
816
+ continue;
817
+ }
818
+ if (ch === " " || ch === "\t" || ch === "\n" || ch === "\r") {
819
+ if (hasBuf) {
820
+ tokens.push(buf);
821
+ buf = "";
822
+ hasBuf = false;
823
+ }
824
+ continue;
825
+ }
826
+ buf += ch;
827
+ hasBuf = true;
828
+ }
829
+ if (hasBuf) tokens.push(buf);
830
+ return tokens;
831
+ }
832
+
833
+ /**
834
+ * Parse remaining args tokens as key=value pairs.
835
+ * Tokens matching `key=value` are split on the first `=`.
836
+ * Tokens that are standalone valid JSON objects/arrays are merged in.
837
+ * All other tokens are ignored (non-kv positional args not supported).
838
+ */
839
+ export function parseWorkflowArgs(tokens: string[]): Record<string, unknown> {
840
+ const result: Record<string, unknown> = {};
841
+ for (const token of tokens) {
842
+ // Try JSON object/array merge
843
+ if (
844
+ (token.startsWith("{") && token.endsWith("}")) ||
845
+ (token.startsWith("[") && token.endsWith("]"))
846
+ ) {
847
+ try {
848
+ const parsed = JSON.parse(token) as unknown;
849
+ if (
850
+ parsed !== null &&
851
+ typeof parsed === "object" &&
852
+ !Array.isArray(parsed)
853
+ ) {
854
+ Object.assign(result, parsed as Record<string, unknown>);
855
+ }
856
+ continue;
857
+ } catch {
858
+ // not valid JSON — fall through to kv parse
859
+ }
860
+ }
861
+ // key=value
862
+ const eqIdx = token.indexOf("=");
863
+ if (eqIdx > 0) {
864
+ const key = token.slice(0, eqIdx);
865
+ const raw = token.slice(eqIdx + 1);
866
+ // Try to parse value as JSON for typed values (numbers, booleans, objects)
867
+ let value: unknown = raw;
868
+ try {
869
+ value = JSON.parse(raw) as unknown;
870
+ } catch {
871
+ // keep as string
872
+ }
873
+ result[key] = value;
874
+ }
875
+ }
876
+ return result;
877
+ }
878
+
879
+
880
+ // ---------------------------------------------------------------------------
881
+ // Persistence port builder
882
+ // ---------------------------------------------------------------------------
883
+
884
+ /**
885
+ * Build a WorkflowPersistencePort from the pi ExtensionAPI when persistence
886
+ * is enabled. Returns undefined when:
887
+ * - persistRuns is false, OR
888
+ * - pi.appendEntry is absent (older pi runtime without persistence API).
889
+ */
890
+ export function makePersistencePort(
891
+ pi: ExtensionAPI,
892
+ persistRuns: boolean,
893
+ ): WorkflowPersistencePort | undefined {
894
+ if (!persistRuns) return undefined;
895
+ if (typeof pi.appendEntry !== "function") return undefined;
896
+
897
+ const port: WorkflowPersistencePort = {
898
+ appendEntry: (type, payload) => pi.appendEntry!(type, payload),
899
+ };
900
+ if (typeof pi.setLabel === "function") {
901
+ port.setLabel = (entryId, label) => pi.setLabel!(entryId, label);
902
+ }
903
+ if (typeof pi.appendCustomMessageEntry === "function") {
904
+ port.appendCustomMessageEntry = (content, meta) =>
905
+ pi.appendCustomMessageEntry!(content, meta);
906
+ }
907
+ return port;
908
+ }
909
+
910
+ // ---------------------------------------------------------------------------
911
+ // MCP port builder
912
+ // ---------------------------------------------------------------------------
913
+
914
+ /**
915
+ * Build a WorkflowMcpPort from the pi ExtensionAPI when MCP scope gating is
916
+ * supported. Returns undefined when pi.events?.emit is absent (adapter not
917
+ * installed or older runtime without events bus) — scoping becomes a no-op.
918
+ */
919
+ export function makeMcpPort(pi: ExtensionAPI): WorkflowMcpPort | undefined {
920
+ if (typeof pi.events?.emit !== "function") return undefined;
921
+
922
+ // Adapt ExtensionAPI to the minimal PiMcpExtensionAPI shape expected by
923
+ // setMcpScope / clearMcpScope. We only forward events.emit (confirmed above).
924
+ const piForMcp: PiMcpExtensionAPI = {
925
+ events: { emit: pi.events.emit as PiEventBus["emit"] },
926
+ };
927
+
928
+ return {
929
+ setScope(stageId: string, allow: string[] | null, deny: string[] | null) {
930
+ setMcpScope(piForMcp, {
931
+ stageId,
932
+ allow: allow ?? undefined,
933
+ deny: deny ?? undefined,
934
+ });
935
+ },
936
+ clearScope(stageId: string) {
937
+ clearMcpScope(piForMcp, stageId);
938
+ },
939
+ };
940
+ }
941
+
942
+ // ---------------------------------------------------------------------------
943
+ // Factory — the default export consumed by the pi runtime
944
+ // ---------------------------------------------------------------------------
945
+
946
+ function factory(pi: ExtensionAPI): void {
947
+ // -------------------------------------------------------------------------
948
+ // 0. Build StageAdapters from pi runtime surfaces. Stage prompting uses
949
+ // pi's in-process SDK `createAgentSession()` surface; HIL prompts
950
+ // flow through the store-backed background adapter built inside
951
+ // `runDetached()` — they never touch pi.ui.
952
+ // -------------------------------------------------------------------------
953
+ const adapters = buildRuntimeAdapters(pi);
954
+
955
+ // Local registry of workflow command (name → handler). Populated by
956
+ // `registerWorkflowCommand` calls below and consumed by the
957
+ // `pi.on("input", …)` interceptor at the end of the factory — see
958
+ // `installInputInterceptor` for the rationale.
959
+ const workflowCommands = new Map<string, WorkflowCommandHandler>();
960
+
961
+ // Build graph overlay adapter — wraps GraphView + pi.ui.custom.
962
+ // noopOverlay returned when pi.ui?.custom is absent (degraded runtime).
963
+ const overlay: GraphOverlayPort = buildGraphOverlayAdapter(pi, store);
964
+
965
+ // -------------------------------------------------------------------------
966
+ // 1. Create ExtensionRuntime — mutable ref seeded from startup discovery,
967
+ // upgraded to unified async discovery once discoverWorkflows() resolves.
968
+ //
969
+ // runtimeProxy delegates all calls to runtimeRef.current so every
970
+ // registration closure automatically uses the most-current registry without
971
+ // needing to be re-registered.
972
+ // -------------------------------------------------------------------------
973
+ const persistenceRef: { current: WorkflowPersistencePort | undefined } = {
974
+ current: makePersistencePort(pi, WORKFLOW_CONFIG_DEFAULTS.persistRuns),
975
+ };
976
+ const mcpPort: WorkflowMcpPort | undefined = makeMcpPort(pi);
977
+
978
+ /**
979
+ * Mutable ref for the resolved runtime config.
980
+ * Seeded with WORKFLOW_CONFIG_DEFAULTS at startup; replaced after async config load.
981
+ * Injected into every createExtensionRuntime() call so the dispatcher, executor,
982
+ * and detached runner all receive the same resolved tunables.
983
+ */
984
+ const runtimeConfigRef: { current: WorkflowRuntimeConfig } = {
985
+ current: {
986
+ maxDepth: WORKFLOW_CONFIG_DEFAULTS.maxDepth,
987
+ defaultConcurrency: WORKFLOW_CONFIG_DEFAULTS.defaultConcurrency,
988
+ persistRuns: WORKFLOW_CONFIG_DEFAULTS.persistRuns,
989
+ statusFile: WORKFLOW_CONFIG_DEFAULTS.statusFile,
990
+ resumeInFlight: WORKFLOW_CONFIG_DEFAULTS.resumeInFlight,
991
+ },
992
+ };
993
+
994
+ /**
995
+ * Mutable ref for the status writer instance.
996
+ * Replaced (old unsubscribed) each time runtimeConfigRef is updated after
997
+ * async config resolution. Starts as a no-op (statusFile defaults to false).
998
+ */
999
+ let statusWriterRef: StatusWriter = createStatusWriter(
1000
+ store,
1001
+ runtimeConfigRef.current,
1002
+ );
1003
+ let intercomParentSession: string | null = null;
1004
+ const intercomPort = {
1005
+ emit:
1006
+ typeof pi.events?.emit === "function"
1007
+ ? (event: string, payload: Record<string, unknown>) => pi.events!.emit!(event, payload)
1008
+ : undefined,
1009
+ parentSession: () => intercomParentSession ?? undefined,
1010
+ };
1011
+
1012
+ const runtimeRef: { current: ExtensionRuntime } = {
1013
+ current: createExtensionRuntime({
1014
+ registry: discoverStartupWorkflowsSync().registry,
1015
+ adapters,
1016
+ cancellation: cancellationRegistry,
1017
+ persistence: persistenceRef.current,
1018
+ mcp: mcpPort,
1019
+ intercom: intercomPort,
1020
+ config: runtimeConfigRef.current,
1021
+ }),
1022
+ };
1023
+ const discoveryRef: { current: DiscoveryResult | null } = { current: null };
1024
+ const configLoadRef: { current: ConfigLoadResult | null } = { current: null };
1025
+
1026
+ /** Stable proxy — all registrations close over this; delegates to runtimeRef.current. */
1027
+ const runtimeProxy: ExtensionRuntime = {
1028
+ get registry() {
1029
+ return runtimeRef.current.registry;
1030
+ },
1031
+ dispatch(args) {
1032
+ return runtimeRef.current.dispatch(args);
1033
+ },
1034
+ runDirect(args) {
1035
+ return runtimeRef.current.runDirect(args);
1036
+ },
1037
+ };
1038
+
1039
+ function modelFullId(model: PiRuntimeModel): string {
1040
+ return `${String(model.provider)}/${model.id}`;
1041
+ }
1042
+
1043
+ function workflowModelCatalogFromContext(ctx?: PiModelContext): WorkflowModelCatalogPort | undefined {
1044
+ if (ctx?.modelRegistry === undefined && ctx?.model === undefined) return undefined;
1045
+ return {
1046
+ listModels: async (): Promise<readonly WorkflowModelInfo[]> => {
1047
+ const available = ctx.modelRegistry?.getAvailable() ?? (ctx.model === undefined ? [] : [ctx.model]);
1048
+ return available.map((model) => ({
1049
+ provider: String(model.provider),
1050
+ id: model.id,
1051
+ fullId: modelFullId(model),
1052
+ model: model as NonNullable<CreateAgentSessionOptions["model"]>,
1053
+ }));
1054
+ },
1055
+ ...(ctx.model !== undefined
1056
+ ? {
1057
+ currentModel: ctx.model as NonNullable<CreateAgentSessionOptions["model"]>,
1058
+ preferredProvider: String(ctx.model.provider),
1059
+ }
1060
+ : {}),
1061
+ };
1062
+ }
1063
+
1064
+ function runtimeWithModels(models: WorkflowModelCatalogPort | undefined): ExtensionRuntime {
1065
+ if (models === undefined) return runtimeProxy;
1066
+ return createExtensionRuntime({
1067
+ registry: runtimeRef.current.registry,
1068
+ adapters,
1069
+ cancellation: cancellationRegistry,
1070
+ persistence: persistenceRef.current,
1071
+ mcp: mcpPort,
1072
+ intercom: intercomPort,
1073
+ config: runtimeConfigRef.current,
1074
+ models,
1075
+ });
1076
+ }
1077
+
1078
+ // The runtime normally does not depend on per-command UI, but model fallback
1079
+ // resolution uses the live command/tool context when pi exposes modelRegistry.
1080
+ function runtimeForContext(ctx?: ({ ui?: PiUISurface } & PiModelContext)): ExtensionRuntime {
1081
+ return runtimeWithModels(workflowModelCatalogFromContext(ctx));
1082
+ }
1083
+
1084
+ let intercomControlUnsubscribe: (() => void) | null = null;
1085
+
1086
+ const executeWorkflowTool = makeExecuteWorkflowTool(
1087
+ (ctx) => runtimeForContext(ctx),
1088
+ () => persistenceRef.current,
1089
+ );
1090
+ let storeWidgetUnsubscribe: (() => void) | null = null;
1091
+
1092
+ // Start unified async discovery immediately.
1093
+ // On resolve: swap runtime ref so /workflow completions and dispatch see
1094
+ // project-local, user-global, and settings-provided workflows.
1095
+ // Load startup config before discovery so workflow paths and tunables are applied.
1096
+ const discoveryPromise = pi.disableAsyncDiscovery ? Promise.resolve() : loadWorkflowConfig().then(async (configResult) => {
1097
+ configLoadRef.current = configResult;
1098
+
1099
+ // Build scope-aware DiscoveryConfig: global entries → globalWorkflows (resolved
1100
+ // under <homeDir>/.atomic/agent), project entries → projectWorkflows (resolved under
1101
+ // projectRoot). Project keys override global keys. Paths pre-resolved to absolute.
1102
+ const { homedir } = await import("node:os");
1103
+ const hasGlobal = configResult.globalConfig != null;
1104
+ const hasProject = configResult.projectConfig != null;
1105
+ const discoveryConfig =
1106
+ hasGlobal || hasProject
1107
+ ? toScopedDiscoveryConfig(
1108
+ configResult.globalConfig ?? null,
1109
+ configResult.projectConfig ?? null,
1110
+ { projectRoot: process.cwd(), homeDir: homedir() },
1111
+ )
1112
+ : undefined;
1113
+
1114
+ const result = await discoverWorkflows({ config: discoveryConfig });
1115
+ discoveryRef.current = result;
1116
+
1117
+ // Resolve effective config (fills in all defaults) and build WorkflowRuntimeConfig.
1118
+ const effectiveConfig = withWorkflowDefaults(configResult.config ?? {});
1119
+ runtimeConfigRef.current = {
1120
+ maxDepth: effectiveConfig.maxDepth,
1121
+ defaultConcurrency: effectiveConfig.defaultConcurrency,
1122
+ persistRuns: effectiveConfig.persistRuns,
1123
+ statusFile: effectiveConfig.statusFile,
1124
+ resumeInFlight: effectiveConfig.resumeInFlight,
1125
+ };
1126
+
1127
+ // Replace status writer with one that reflects the resolved config.
1128
+ // Unsubscribe the prior (no-op) writer before creating the new one.
1129
+ statusWriterRef.unsubscribe();
1130
+ statusWriterRef = createStatusWriter(store, runtimeConfigRef.current);
1131
+
1132
+ persistenceRef.current = makePersistencePort(
1133
+ pi,
1134
+ effectiveConfig.persistRuns,
1135
+ );
1136
+ runtimeRef.current = createExtensionRuntime({
1137
+ registry: result.registry,
1138
+ adapters,
1139
+ cancellation: cancellationRegistry,
1140
+ persistence: persistenceRef.current,
1141
+ mcp: mcpPort,
1142
+ intercom: intercomPort,
1143
+ config: runtimeConfigRef.current,
1144
+ });
1145
+
1146
+ });
1147
+
1148
+ // -------------------------------------------------------------------------
1149
+ // 1. Register the `workflow` tool
1150
+ // Pi's ToolDefinition.execute is positional: (toolCallId, params, signal,
1151
+ // onUpdate, ctx) → Promise<AgentToolResult<TDetails>>. The internal
1152
+ // `executeWorkflowTool` keeps its (args, ctx) shape for test ergonomics;
1153
+ // we adapt here at the registration boundary only.
1154
+ // cross-ref: pi-coding-agent dist/core/extensions/types.d.ts ToolDefinition
1155
+ // -------------------------------------------------------------------------
1156
+ if (typeof pi.registerTool === "function") {
1157
+ pi.registerTool<WorkflowToolArgs, WorkflowToolResult>({
1158
+ name: "workflow",
1159
+ label: "workflow",
1160
+ description: "Run a defined multi-stage workflow by name.",
1161
+ parameters: workflowParameters,
1162
+ execute: async (_toolCallId, params, _signal, _onUpdate, ctx) => {
1163
+ // Overlay is opt-in via F2 / ctrl+h; do not auto-open from a
1164
+ // tool-call dispatch path.
1165
+ const details = await executeWorkflowTool(params, ctx);
1166
+ return {
1167
+ content: [{ type: "text", text: renderResult(details, {}) }],
1168
+ details,
1169
+ };
1170
+ },
1171
+ renderCall: (args, _theme, _context) =>
1172
+ textRenderComponent(renderCall(args)),
1173
+ renderResult: (result, opts, _theme, _context) =>
1174
+ textRenderComponent(renderResult(result.details, opts)),
1175
+ });
1176
+
1177
+ }
1178
+
1179
+ // -------------------------------------------------------------------------
1180
+ // 2. Register /workflow slash command
1181
+ // -------------------------------------------------------------------------
1182
+ /**
1183
+ * Shared top-level run-control handler.
1184
+ *
1185
+ * connect [runId|prefix] no arg → picker overlay; arg → attach to graph
1186
+ * attach [runId|prefix [stageId]] open the in-place attach pane on a stage
1187
+ * interrupt [runId|prefix|--all] [-y] confirmation overlay unless -y
1188
+ * pause [runId|prefix [stageId]] pause a run or specific stage
1189
+ * resume [runId|prefix [stageId] …] resume paused work or reopen snapshot
1190
+ */
1191
+ async function handleRunControlCommand(
1192
+ action: "connect" | "interrupt" | "attach" | "pause" | "resume",
1193
+ rest: string[],
1194
+ ctx: PiCommandContext,
1195
+ ): Promise<boolean> {
1196
+ const print = (msg: string): void => ctx.ui.notify(msg, "info");
1197
+ const theme = deriveGraphTheme({});
1198
+
1199
+ if (action === "connect") {
1200
+ const target = rest.find((t) => !t.startsWith("--"));
1201
+ if (!target) {
1202
+ // Picker mode — mount the overlay and route the resolved action.
1203
+ const ui = ctx.ui;
1204
+ if (!ui || typeof ui.custom !== "function") {
1205
+ print(
1206
+ `${renderSessionList(store.runs(), { theme, includeAll: false })}\n\nPicker requires a UI surface. Pass a runId: /workflow connect <id>`,
1207
+ );
1208
+ return true;
1209
+ }
1210
+ const result = await openSessionPicker(ui, store, theme, "connect");
1211
+ if (result.kind === "close") return true;
1212
+ if (result.kind === "connect") {
1213
+ overlay.open(result.runId, overlaySurfaceFromContext(ctx));
1214
+ return true;
1215
+ }
1216
+ if (result.kind === "kill") {
1217
+ const run = store.runs().find((r) => r.id === result.runId);
1218
+ if (!run) {
1219
+ print(`Run not found: ${result.runId}`);
1220
+ return true;
1221
+ }
1222
+ const confirmed = await openKillConfirm(ui, run, theme);
1223
+ if (!confirmed) {
1224
+ print(`Cancelled. Run ${result.runId.slice(0, 8)} is still active.`);
1225
+ return true;
1226
+ }
1227
+ const killed = killRun(result.runId, {
1228
+ cancellation: cancellationRegistry,
1229
+ persistence: persistenceRef.current,
1230
+ });
1231
+ print(
1232
+ killed.ok
1233
+ ? `Run ${killed.runId.slice(0, 8)} interrupted.`
1234
+ : `Run ${result.runId.slice(0, 8)} already ended.`,
1235
+ );
1236
+ return true;
1237
+ }
1238
+ return true;
1239
+ }
1240
+ const resolved = resolveRunIdPrefix(target);
1241
+ if (resolved.kind === "not_found") {
1242
+ print(`Run not found: ${target}\n\n${renderSessionList(store.runs(), { theme, includeAll: true })}`);
1243
+ return true;
1244
+ }
1245
+ if (resolved.kind === "ambiguous") {
1246
+ print(
1247
+ `Ambiguous run prefix "${target}" matches: ${resolved.matches
1248
+ .map((id) => id.slice(0, 12))
1249
+ .join(", ")}`,
1250
+ );
1251
+ return true;
1252
+ }
1253
+ overlay.open(resolved.runId, overlaySurfaceFromContext(ctx));
1254
+ print(`Attached to ${resolved.runId.slice(0, 8)}. Press "h" or ctrl+d to hide, "q" to interrupt, esc to close.`);
1255
+ return true;
1256
+ }
1257
+
1258
+ if (action === "interrupt") {
1259
+ const { tokens: interruptArgs, yes } = stripYesFlag(rest);
1260
+ let target = interruptArgs.find((t) => !t.startsWith("--"));
1261
+ const wantsAll = interruptArgs.includes("--all");
1262
+ if (!target && !wantsAll) {
1263
+ target = store.activeRunId() ?? undefined;
1264
+ if (!target) {
1265
+ print("No in-flight runs to interrupt.");
1266
+ return true;
1267
+ }
1268
+ }
1269
+ if (wantsAll) {
1270
+ const inFlight = store.runs().filter((r) => r.endedAt === undefined);
1271
+ if (inFlight.length === 0) {
1272
+ print("No in-flight runs to interrupt.");
1273
+ return true;
1274
+ }
1275
+ if (!yes && ctx.ui && typeof ctx.ui.confirm === "function") {
1276
+ const ok = await ctx.ui.confirm(
1277
+ `Interrupt all ${inFlight.length} in-flight workflow runs?`,
1278
+ `Aborts: ${inFlight.map((r) => `${r.name} (${r.id.slice(0, 8)})`).join(", ")}`,
1279
+ );
1280
+ if (!ok) {
1281
+ print("Cancelled.");
1282
+ return true;
1283
+ }
1284
+ }
1285
+ const results = killAllRuns({
1286
+ cancellation: cancellationRegistry,
1287
+ persistence: persistenceRef.current,
1288
+ });
1289
+ const killed = results.filter((r) => r.ok).length;
1290
+ print(killed > 0 ? `Interrupted ${killed} run(s).` : "No in-flight runs to interrupt.");
1291
+ return true;
1292
+ }
1293
+ const resolved = resolveRunIdPrefix(target!);
1294
+ if (resolved.kind === "not_found") {
1295
+ print(`Run not found: ${target}`);
1296
+ return true;
1297
+ }
1298
+ if (resolved.kind === "ambiguous") {
1299
+ print(
1300
+ `Ambiguous run prefix "${target}" matches multiple runs: ${resolved.matches
1301
+ .map((id) => id.slice(0, 12))
1302
+ .join(", ")}`,
1303
+ );
1304
+ return true;
1305
+ }
1306
+ const run = store.runs().find((r) => r.id === resolved.runId);
1307
+ if (!yes && run && run.endedAt === undefined && ctx.ui) {
1308
+ const confirmed = await openKillConfirm(ctx.ui, run, theme);
1309
+ if (!confirmed) {
1310
+ print(`Cancelled. Run ${resolved.runId.slice(0, 8)} is still active.`);
1311
+ return true;
1312
+ }
1313
+ }
1314
+ const result = killRun(resolved.runId, {
1315
+ cancellation: cancellationRegistry,
1316
+ persistence: persistenceRef.current,
1317
+ });
1318
+ if (result.ok) {
1319
+ print(`Run ${result.runId.slice(0, 8)} interrupted (was ${result.previousStatus}).`);
1320
+ } else {
1321
+ print(
1322
+ result.reason === "not_found"
1323
+ ? `Run not found: ${target}`
1324
+ : `Run already ended: ${target}`,
1325
+ );
1326
+ }
1327
+ return true;
1328
+ }
1329
+
1330
+ if (action === "attach") {
1331
+ const target = rest[0];
1332
+ const stageTarget = rest[1];
1333
+ let runId: string;
1334
+ if (!target) {
1335
+ const ui = ctx.ui;
1336
+ if (!ui || typeof ui.custom !== "function") {
1337
+ print(`${renderSessionList(store.runs(), { theme, includeAll: false })}\n\nPicker requires a UI surface. Pass a runId: /workflow attach <id> [stageId]`);
1338
+ return true;
1339
+ }
1340
+ const picked = await openSessionPicker(ui, store, theme, "connect");
1341
+ if (picked.kind === "close") return true;
1342
+ if (picked.kind !== "connect") {
1343
+ // The picker may have surfaced interrupt from the `x` shortcut.
1344
+ // Forward through the existing interrupt flow for clarity.
1345
+ if (picked.kind === "kill") {
1346
+ return handleRunControlCommand("interrupt", [picked.runId, "-y"], ctx);
1347
+ }
1348
+ return true;
1349
+ }
1350
+ runId = picked.runId;
1351
+ } else {
1352
+ const resolved = resolveRunIdPrefix(target);
1353
+ if (resolved.kind === "not_found") {
1354
+ print(`Run not found: ${target}`);
1355
+ return true;
1356
+ }
1357
+ if (resolved.kind === "ambiguous") {
1358
+ print(`Ambiguous run prefix "${target}" matches: ${resolved.matches.map((id) => id.slice(0, 12)).join(", ")}`);
1359
+ return true;
1360
+ }
1361
+ runId = resolved.runId;
1362
+ }
1363
+ const run = store.runs().find((r) => r.id === runId);
1364
+ let stageId: string | undefined;
1365
+ if (stageTarget && run) {
1366
+ const exact = run.stages.find((s) => s.id === stageTarget);
1367
+ const prefix = exact ?? run.stages.find((s) => s.id.startsWith(stageTarget));
1368
+ const byName = prefix ?? run.stages.find((s) => s.name === stageTarget);
1369
+ if (!byName) {
1370
+ print(`Stage not found in run ${runId.slice(0, 8)}: ${stageTarget}`);
1371
+ return true;
1372
+ }
1373
+ stageId = byName.id;
1374
+ }
1375
+ overlay.open(runId, overlaySurfaceFromContext(ctx), stageId);
1376
+ print(
1377
+ stageId
1378
+ ? `Attached to ${runId.slice(0, 8)} stage ${stageId.slice(0, 8)}. Ctrl+D returns to graph, Escape closes.`
1379
+ : `Attached to ${runId.slice(0, 8)}. Press ↵ on a node to chat, Ctrl+D to detach.`,
1380
+ );
1381
+ return true;
1382
+ }
1383
+
1384
+ if (action === "pause") {
1385
+ const target = rest[0];
1386
+ const stageTarget = rest[1];
1387
+ let runId: string;
1388
+ if (!target) {
1389
+ const ui = ctx.ui;
1390
+ if (!ui || typeof ui.custom !== "function") {
1391
+ const active = store.runs().filter((r) => r.endedAt === undefined);
1392
+ if (active.length === 0) {
1393
+ print("No active runs to pause.");
1394
+ return true;
1395
+ }
1396
+ print(
1397
+ `Picker requires a UI surface. Active runs:\n${active.map((r) => ` ${r.id.slice(0, 8)} ${r.name}`).join("\n")}\n\nUsage: /workflow pause <runId> [stageId]`,
1398
+ );
1399
+ return true;
1400
+ }
1401
+ const picked = await openSessionPicker(ui, store, theme, "pause");
1402
+ if (picked.kind !== "pause") return true;
1403
+ runId = picked.runId;
1404
+ } else {
1405
+ const resolved = resolveRunIdPrefix(target);
1406
+ if (resolved.kind === "not_found") {
1407
+ print(`Run not found: ${target}`);
1408
+ return true;
1409
+ }
1410
+ if (resolved.kind === "ambiguous") {
1411
+ print(`Ambiguous run prefix "${target}" matches: ${resolved.matches.map((id) => id.slice(0, 12)).join(", ")}`);
1412
+ return true;
1413
+ }
1414
+ runId = resolved.runId;
1415
+ }
1416
+ let stageId: string | undefined;
1417
+ if (stageTarget) {
1418
+ const run = store.runs().find((r) => r.id === runId);
1419
+ const stage = run?.stages.find((s) => s.id === stageTarget || s.id.startsWith(stageTarget) || s.name === stageTarget);
1420
+ if (!stage) {
1421
+ print(`Stage not found in run ${runId.slice(0, 8)}: ${stageTarget}`);
1422
+ return true;
1423
+ }
1424
+ stageId = stage.id;
1425
+ }
1426
+ const result = pauseRun(runId, { stageId });
1427
+ if (!result.ok) {
1428
+ const why =
1429
+ result.reason === "not_found"
1430
+ ? `Run not found: ${runId.slice(0, 8)}`
1431
+ : result.reason === "already_ended"
1432
+ ? `Run ${runId.slice(0, 8)} already ended.`
1433
+ : result.reason === "no_active_stages"
1434
+ ? `No pausable stages on run ${runId.slice(0, 8)}.`
1435
+ : `Stage not found: ${stageTarget ?? "(unknown)"}`;
1436
+ print(why);
1437
+ return true;
1438
+ }
1439
+ // Open the orchestrator overlay (graph for run-level pause, stage
1440
+ // chat when a stage was named). This mirrors connect/attach/resume:
1441
+ // the full-screen overlay hides Pi's "Working… (esc to interrupt)"
1442
+ // spinner, which otherwise stays visible because the host session
1443
+ // is still streaming whatever was happening before the pause hit.
1444
+ if (typeof ctx.ui?.custom === "function") {
1445
+ overlay.open(runId, overlaySurfaceFromContext(ctx), stageId);
1446
+ }
1447
+ print(
1448
+ result.paused.length === 0
1449
+ ? `No stages were paused on run ${runId.slice(0, 8)}.`
1450
+ : `Paused ${result.paused.length} stage(s) on run ${runId.slice(0, 8)}: ${result.paused.map((s) => s.name).join(", ")}`,
1451
+ );
1452
+ return true;
1453
+ }
1454
+
1455
+ if (action === "resume") {
1456
+ const target = rest[0];
1457
+ const stageTarget = rest[1];
1458
+ const message = rest.slice(2).join(" ").trim() || undefined;
1459
+ let runId: string;
1460
+ if (!target) {
1461
+ const ui = ctx.ui;
1462
+ if (!ui || typeof ui.custom !== "function") {
1463
+ print(`Usage: /workflow resume <runId> [stageId] [message…]`);
1464
+ return true;
1465
+ }
1466
+ const picked = await openSessionPicker(ui, store, theme, "resume");
1467
+ if (picked.kind !== "resume") return true;
1468
+ runId = picked.runId;
1469
+ } else {
1470
+ const resolved = resolveRunIdPrefix(target);
1471
+ if (resolved.kind === "not_found") {
1472
+ print(`Run not found: ${target}`);
1473
+ return true;
1474
+ }
1475
+ if (resolved.kind === "ambiguous") {
1476
+ print(`Ambiguous run prefix "${target}" matches: ${resolved.matches.map((id) => id.slice(0, 12)).join(", ")}`);
1477
+ return true;
1478
+ }
1479
+ runId = resolved.runId;
1480
+ }
1481
+ let stageId: string | undefined;
1482
+ const run = store.runs().find((r) => r.id === runId);
1483
+ if (stageTarget) {
1484
+ const stage = run?.stages.find((s) => s.id === stageTarget || s.id.startsWith(stageTarget) || s.name === stageTarget);
1485
+ if (!stage) {
1486
+ print(`Stage not found in run ${runId.slice(0, 8)}: ${stageTarget}`);
1487
+ return true;
1488
+ }
1489
+ stageId = stage.id;
1490
+ }
1491
+ const isPaused =
1492
+ run?.status === "paused" || (run?.stages.some((s) => s.status === "paused") ?? false);
1493
+ const result = resumeRun(runId, { stageId, message });
1494
+ if (!result.ok) {
1495
+ print(`Run not found: ${runId.slice(0, 8)}`);
1496
+ return true;
1497
+ }
1498
+ if (!isPaused) {
1499
+ // Non-paused fallback: reopen the orchestrator overlay as before.
1500
+ overlay.open(result.runId, overlaySurfaceFromContext(ctx));
1501
+ print(
1502
+ `Snapshot available: run ${result.runId} (${result.snapshot.name}) \u2014 status: ${result.snapshot.status}, stages: ${result.snapshot.stages.length}`,
1503
+ );
1504
+ return true;
1505
+ }
1506
+ // Paused live resume: when no message was provided and the picker
1507
+ // is available, open the attached chat so the user can talk to
1508
+ // the freshly-resumed stage.
1509
+ if (!message && stageId && ctx.ui?.custom) {
1510
+ overlay.open(runId, overlaySurfaceFromContext(ctx), stageId);
1511
+ }
1512
+ print(
1513
+ result.resumed.length === 0
1514
+ ? `No paused stages on run ${runId.slice(0, 8)}.`
1515
+ : `Resumed ${result.resumed.length} stage(s) on run ${runId.slice(0, 8)}${message ? ` with message: "${message}"` : ""}.`,
1516
+ );
1517
+ return true;
1518
+ }
1519
+
1520
+ return false;
1521
+ }
1522
+
1523
+ registerWorkflowCommand(pi, "workflow", {
1524
+ description:
1525
+ "Run or inspect pi workflows. Usage: /workflow <name> [key=value…] | /workflow [list|status|connect|attach|interrupt|pause|resume|inputs] [args]",
1526
+ handler: async (args: string, ctx: PiCommandContext) => {
1527
+ const print = (msg: string): void => ctx.ui.notify(msg, "info");
1528
+ // Quote-aware split so `prompt="map the codebase"` stays a single
1529
+ // token. Plain `.split(/\s+/)` would mangle quoted multi-word values
1530
+ // into `prompt="map`, `the`, `codebase"` — the dispatch confirm then
1531
+ // renders `prompt=""map"` (see ui/qa-current-render-2.png).
1532
+ const parts = tokenizeWorkflowArgs(args);
1533
+ const subcommand = parts[0] ?? "";
1534
+
1535
+ // -----------------------------------------------------------------------
1536
+ // connect — open the orchestrator pane (picker if no id).
1537
+ // attach — open the in-place attach pane on a stage (or pick run).
1538
+ // pause — pause a run or specific stage.
1539
+ // -----------------------------------------------------------------------
1540
+ if (subcommand === "connect") {
1541
+ await handleRunControlCommand("connect", parts.slice(1), ctx);
1542
+ return;
1543
+ }
1544
+ if (subcommand === "attach") {
1545
+ await handleRunControlCommand("attach", parts.slice(1), ctx);
1546
+ return;
1547
+ }
1548
+ if (subcommand === "pause") {
1549
+ await handleRunControlCommand("pause", parts.slice(1), ctx);
1550
+ return;
1551
+ }
1552
+
1553
+ // -----------------------------------------------------------------------
1554
+ // list (default when no subcommand) — render the workflow catalogue
1555
+ // via the same renderer used by the LLM tool path.
1556
+ // -----------------------------------------------------------------------
1557
+ if (!subcommand || subcommand === "list") {
1558
+ const items = runtimeProxy.registry.all().map((def) => ({
1559
+ name: def.normalizedName,
1560
+ description: def.description,
1561
+ inputs: Object.entries(def.inputs).map(([iname, schema]) => ({
1562
+ name: iname,
1563
+ required: schema.required === true,
1564
+ })),
1565
+ }));
1566
+ emitChatSurface(pi, { kind: "list", entries: items });
1567
+ return;
1568
+ }
1569
+
1570
+ // -----------------------------------------------------------------------
1571
+ // status — band-header rich list, or per-run detail when an id is
1572
+ // supplied. `/workflow status` lists everything in-flight (`--all`
1573
+ // includes ended runs older than an hour); `/workflow status <id>`
1574
+ // drills into a single run via the inspectRun detail block.
1575
+ // -----------------------------------------------------------------------
1576
+ if (subcommand === "status") {
1577
+ const target = parts[1];
1578
+ if (target && !target.startsWith("--")) {
1579
+ const resolved = resolveRunIdPrefix(target);
1580
+ if (resolved.kind === "not_found") {
1581
+ print(`Run not found: ${target}`);
1582
+ return;
1583
+ }
1584
+ if (resolved.kind === "ambiguous") {
1585
+ print(
1586
+ `Ambiguous run prefix "${target}" matches: ${resolved.matches
1587
+ .map((id) => id.slice(0, 12))
1588
+ .join(", ")}`,
1589
+ );
1590
+ return;
1591
+ }
1592
+ const inspected = inspectRun(resolved.runId);
1593
+ if (!inspected.ok) {
1594
+ print(`Run not found: ${target}`);
1595
+ return;
1596
+ }
1597
+ emitChatSurface(pi, { kind: "detail", detail: inspected.detail });
1598
+ return;
1599
+ }
1600
+ // Mirror renderSessionList's filter: keep `--all` semantics, then
1601
+ // hand the already-filtered snapshot to the chat-surface renderer.
1602
+ const includeAll = parts.includes("--all");
1603
+ const rows = selectRunsForPicker(store.runs(), "", includeAll, Date.now());
1604
+ emitChatSurface(pi, { kind: "status", runs: rows.map((r) => r.run) });
1605
+ return;
1606
+ }
1607
+
1608
+ // -----------------------------------------------------------------------
1609
+ // interrupt — top-level chat fast path (no confirmation overlay).
1610
+ // -----------------------------------------------------------------------
1611
+ if (subcommand === "interrupt") {
1612
+ // The top-level chat command is the fast interrupt path surfaced by the
1613
+ // widget hint (`/workflow interrupt <id>`). The user's explicit slash
1614
+ // command should abort immediately, even when a confirm surface is
1615
+ // unavailable or would steal focus from the running workflow.
1616
+ const interruptArgs = parts.slice(1);
1617
+ const hasYes = interruptArgs.some((t) => t === "--yes" || t === "-y");
1618
+ await handleRunControlCommand(
1619
+ "interrupt",
1620
+ hasYes ? interruptArgs : [...interruptArgs, "-y"],
1621
+ ctx,
1622
+ );
1623
+ return;
1624
+ }
1625
+
1626
+ // -----------------------------------------------------------------------
1627
+ // resume — non-paused runs reopen the orchestrator pane (legacy
1628
+ // behaviour); paused runs resume live work through the registry.
1629
+ // -----------------------------------------------------------------------
1630
+ if (subcommand === "resume") {
1631
+ await handleRunControlCommand("resume", parts.slice(1), ctx);
1632
+ return;
1633
+ }
1634
+
1635
+ // -----------------------------------------------------------------------
1636
+ // inputs — pretty-printed via theme; falls back to plain in non-TTY tests.
1637
+ // -----------------------------------------------------------------------
1638
+ if (subcommand === "inputs") {
1639
+ const workflowName = parts[1] ?? "";
1640
+ if (!workflowName) {
1641
+ print("Usage: /workflow inputs <name>");
1642
+ return;
1643
+ }
1644
+ const result = await runtimeForContext(ctx).dispatch({
1645
+ workflow: workflowName,
1646
+ inputs: {},
1647
+ action: "inputs",
1648
+ });
1649
+ if (result.action === "inputs" && "inputs" in result) {
1650
+ const r = result as Extract<WorkflowToolResult, { action: "inputs" }>;
1651
+ if (r.error) {
1652
+ const available = runtimeProxy.registry.names();
1653
+ print(
1654
+ `${r.error}\nAvailable: ${available.length > 0 ? available.join(", ") : "(none)"}`,
1655
+ );
1656
+ } else {
1657
+ print(renderInputsSchema(workflowName, r.inputs, { theme: deriveGraphTheme({}) }));
1658
+ }
1659
+ }
1660
+ return;
1661
+ }
1662
+
1663
+ // -----------------------------------------------------------------------
1664
+ // Workflow name dispatch — workflows always run as background tasks.
1665
+ // The chat editor remains usable; HIL prompts surface through the graph
1666
+ // viewer overlay (F2 / `/workflow connect`).
1667
+ // -----------------------------------------------------------------------
1668
+ const workflowName = subcommand;
1669
+ const inputTokens = parts.slice(1);
1670
+
1671
+ if (inputTokens.includes("--help")) {
1672
+ const helpResult = await runtimeForContext(ctx).dispatch({
1673
+ workflow: workflowName,
1674
+ inputs: {},
1675
+ action: "inputs",
1676
+ });
1677
+ if (helpResult.action === "inputs" && "inputs" in helpResult) {
1678
+ const r = helpResult as Extract<
1679
+ WorkflowToolResult,
1680
+ { action: "inputs" }
1681
+ >;
1682
+ if (r.error) {
1683
+ const available = runtimeProxy.registry.names();
1684
+ print(
1685
+ `${r.error}\nAvailable: ${available.length > 0 ? available.join(", ") : "(none)"}`,
1686
+ );
1687
+ } else {
1688
+ print(renderInputsSchema(workflowName, r.inputs, { theme: deriveGraphTheme({}) }));
1689
+ }
1690
+ }
1691
+ return;
1692
+ }
1693
+
1694
+ const inputs = parseWorkflowArgs(inputTokens);
1695
+ // -----------------------------------------------------------------------
1696
+ // Interactive argument picker.
1697
+ //
1698
+ // Triggers when:
1699
+ // - the workflow has at least one declared input (zero-input
1700
+ // workflows go straight to dispatch — there's nothing to ask),
1701
+ // - the user did not pass `--no-picker`,
1702
+ // - an interactive TUI surface is available,
1703
+ // - AND either no key=value was supplied or one of the required
1704
+ // inputs is still missing after parsing.
1705
+ //
1706
+ // The picker is seeded with whatever the user *did* type, so a
1707
+ // partial invocation like `/workflow gen-spec research_doc=notes.md`
1708
+ // pre-fills that field and focuses the next unfilled required one.
1709
+ // -----------------------------------------------------------------------
1710
+ const wantsPickerSkip = inputTokens.includes("--no-picker");
1711
+ let mergedInputs = inputs;
1712
+ // Track whether the inputs picker actually showed a UI to the user.
1713
+ // We use this below to mount the orchestrator overlay on dispatch
1714
+ // success — same UX as `/workflow connect|attach|pause|resume`,
1715
+ // which all cover Pi's `⠴ Working… (esc to interrupt)` spinner
1716
+ // with the full-screen overlay instead of leaving it visible in
1717
+ // the chat while the workflow runs in the background.
1718
+ let pickerWasShown = false;
1719
+ // Prefer the sticky inline form when the host can install a custom
1720
+ // editor. If the host rejects that editor contract at runtime, fall
1721
+ // back to the supported overlay picker rather than surfacing the host
1722
+ // exception as a workflow command error.
1723
+ const canOpenPicker =
1724
+ !wantsPickerSkip &&
1725
+ (typeof ctx.ui?.setEditorComponent === "function" ||
1726
+ typeof ctx.ui?.custom === "function");
1727
+ if (canOpenPicker) {
1728
+ const schemaResult = await runtimeForContext(ctx).dispatch({
1729
+ workflow: workflowName,
1730
+ inputs: {},
1731
+ action: "inputs",
1732
+ });
1733
+ const schema =
1734
+ schemaResult.action === "inputs" && "inputs" in schemaResult
1735
+ ? (schemaResult as Extract<WorkflowToolResult, { action: "inputs" }>)
1736
+ : undefined;
1737
+ const fields = schema?.inputs ?? [];
1738
+ const hasFields = fields.length > 0;
1739
+ const missingRequired = fields.some(
1740
+ (f: WorkflowInputEntry) =>
1741
+ f.required === true &&
1742
+ (inputs[f.name] === undefined ||
1743
+ (typeof inputs[f.name] === "string" &&
1744
+ (inputs[f.name] as string).trim() === "")),
1745
+ );
1746
+ const noTokensAtAll = inputTokens.length === 0;
1747
+ if (hasFields && (noTokensAtAll || missingRequired)) {
1748
+ pickerWasShown = true;
1749
+ const pickerTheme = deriveGraphTheme({});
1750
+ let pickerResult =
1751
+ typeof ctx.ui?.setEditorComponent === "function"
1752
+ ? await openInlineInputsForm(pi, ctx, {
1753
+ workflowName,
1754
+ fields,
1755
+ prefilled: inputs,
1756
+ theme: pickerTheme,
1757
+ })
1758
+ : { kind: "unsupported" as const };
1759
+ if (
1760
+ pickerResult.kind === "unsupported" &&
1761
+ typeof ctx.ui?.custom === "function"
1762
+ ) {
1763
+ pickerResult = await openInputsPicker(ctx.ui, {
1764
+ workflowName,
1765
+ fields,
1766
+ prefilled: inputs,
1767
+ theme: pickerTheme,
1768
+ });
1769
+ }
1770
+ if (pickerResult.kind === "cancel") {
1771
+ print(`Cancelled. /workflow ${workflowName} not started.`);
1772
+ return;
1773
+ }
1774
+ if (pickerResult.kind === "run") {
1775
+ mergedInputs = pickerResult.values;
1776
+ }
1777
+ }
1778
+ }
1779
+
1780
+ const result = await runtimeForContext(ctx).dispatch({
1781
+ workflow: workflowName,
1782
+ inputs: mergedInputs,
1783
+ action: "run",
1784
+ });
1785
+ if (result.action === "run" && "runId" in result) {
1786
+ const r = result as Extract<
1787
+ WorkflowToolResult,
1788
+ { action: "run"; runId: string }
1789
+ >;
1790
+ if (r.status === "failed" && r.runId === "") {
1791
+ const available = runtimeProxy.registry.names();
1792
+ print(
1793
+ `Workflow not found: ${workflowName}\nAvailable: ${available.length > 0 ? available.join(", ") : "(none)"}`,
1794
+ );
1795
+ } else if (r.status === "failed") {
1796
+ print(
1797
+ `Workflow "${workflowName}" failed: ${r.error ?? "unknown error"}`,
1798
+ );
1799
+ } else {
1800
+ // Always-background — the run is alive, the chat is free.
1801
+ // Route via emitChatSurface so the band+card chrome receives the
1802
+ // real chat content width via pi-tui's Component contract
1803
+ // (registered renderer returns `{ render(width): string[] }`),
1804
+ // not a `process.stdout.columns - 2` heuristic.
1805
+ emitChatSurface(pi, {
1806
+ kind: "dispatch",
1807
+ workflowName,
1808
+ runId: r.runId,
1809
+ inputs: mergedInputs,
1810
+ });
1811
+ // When the user reached this path via the inputs picker (i.e.
1812
+ // they didn't pre-supply all required args), open the
1813
+ // orchestrator overlay. The full-screen overlay covers the
1814
+ // chat statusContainer so Pi's working spinner is not left
1815
+ // visible behind the dispatch card. Direct invocations with
1816
+ // complete args remain opt-in via F2 / `/workflow connect`.
1817
+ if (pickerWasShown && typeof ctx.ui?.custom === "function") {
1818
+ overlay.open(r.runId, overlaySurfaceFromContext(ctx));
1819
+ }
1820
+ }
1821
+ }
1822
+ return;
1823
+ },
1824
+ getArgumentCompletions: (
1825
+ partial: string,
1826
+ ): PiArgumentCompletionResult => {
1827
+ const completeToken = (
1828
+ argumentText: string,
1829
+ candidates: PiArgumentCompletion[],
1830
+ ): PiArgumentCompletionResult => {
1831
+ const tokenStart = /\s$/.test(argumentText)
1832
+ ? argumentText.length
1833
+ : Math.max(argumentText.lastIndexOf(" "), argumentText.lastIndexOf("\t")) + 1;
1834
+ const head = argumentText.slice(0, tokenStart);
1835
+ const token = argumentText.slice(tokenStart);
1836
+ const filtered = candidates
1837
+ .filter((candidate) => candidate.value.startsWith(token))
1838
+ .map((candidate) => ({
1839
+ ...candidate,
1840
+ value: `${head}${candidate.value}`,
1841
+ }));
1842
+ return filtered.length > 0 ? filtered : null;
1843
+ };
1844
+
1845
+ const workflowNameItems = (): PiArgumentCompletion[] =>
1846
+ runtimeProxy.registry.names().map((name) => ({
1847
+ value: `${name} `,
1848
+ label: name,
1849
+ description: `Run workflow: ${name}`,
1850
+ }));
1851
+
1852
+ const runIdItems = (): PiArgumentCompletion[] =>
1853
+ store.runs().map((run) => ({
1854
+ value: `${run.id} `,
1855
+ label: run.id.slice(0, 8),
1856
+ description: `${run.name} — ${run.status}`,
1857
+ }));
1858
+
1859
+ const adminCompletions: PiArgumentCompletion[] = [
1860
+ {
1861
+ value: "connect ",
1862
+ label: "connect",
1863
+ description: "Attach to a run (picker if no id)",
1864
+ },
1865
+ {
1866
+ value: "attach ",
1867
+ label: "attach",
1868
+ description: "Open the in-place attach pane on a node",
1869
+ },
1870
+ {
1871
+ value: "list ",
1872
+ label: "list",
1873
+ description: "List registered workflows",
1874
+ },
1875
+ {
1876
+ value: "status ",
1877
+ label: "status",
1878
+ description: "List in-flight runs",
1879
+ },
1880
+ { value: "interrupt ", label: "interrupt", description: "Interrupt a run" },
1881
+ { value: "pause ", label: "pause", description: "Pause a run or stage" },
1882
+ {
1883
+ value: "resume ",
1884
+ label: "resume",
1885
+ description: "Re-open overlay for a run",
1886
+ },
1887
+ {
1888
+ value: "inputs ",
1889
+ label: "inputs",
1890
+ description: "Show a workflow's input schema",
1891
+ },
1892
+ ];
1893
+
1894
+ const parts = partial.trim().split(/\s+/).filter(Boolean);
1895
+ const subcommand = parts[0] ?? "";
1896
+ if (!partial.includes(" ")) {
1897
+ return completeToken(partial, [...adminCompletions, ...workflowNameItems()]);
1898
+ }
1899
+
1900
+ if (subcommand === "inputs") {
1901
+ return completeToken(partial, workflowNameItems());
1902
+ }
1903
+
1904
+ if (subcommand === "status") {
1905
+ return completeToken(partial, [
1906
+ { value: "--all ", label: "--all", description: "Include recently ended runs" },
1907
+ ...runIdItems(),
1908
+ ]);
1909
+ }
1910
+
1911
+ if (subcommand === "connect") {
1912
+ return completeToken(partial, runIdItems());
1913
+ }
1914
+
1915
+ if (subcommand === "resume") {
1916
+ return completeToken(partial, runIdItems());
1917
+ }
1918
+
1919
+ if (subcommand === "attach" || subcommand === "pause") {
1920
+ return completeToken(partial, runIdItems());
1921
+ }
1922
+
1923
+ if (subcommand === "interrupt") {
1924
+ return completeToken(partial, [
1925
+ { value: "--all ", label: "--all", description: "Interrupt all in-flight runs" },
1926
+ { value: "--yes ", label: "--yes", description: "Skip confirmation" },
1927
+ { value: "-y ", label: "-y", description: "Skip confirmation" },
1928
+ ...runIdItems(),
1929
+ ]);
1930
+ }
1931
+
1932
+ // `partial` ends with whitespace and no subcommand was typed yet
1933
+ // (e.g. `/workflow `). pi's autocomplete is asking what to suggest
1934
+ // after the trailing space; offer the same admin + workflow-name
1935
+ // menu as the no-space branch above. Skipping this guard would call
1936
+ // `registry.get("")`, which throws TypeError from normalizeWorkflowName.
1937
+ if (!subcommand) {
1938
+ return completeToken(partial, [...adminCompletions, ...workflowNameItems()]);
1939
+ }
1940
+
1941
+ const workflow = runtimeProxy.registry.get(subcommand);
1942
+ if (!workflow) return null;
1943
+
1944
+ const tokenStart = /\s$/.test(partial)
1945
+ ? partial.length
1946
+ : Math.max(partial.lastIndexOf(" "), partial.lastIndexOf("\t")) + 1;
1947
+ const token = partial.slice(tokenStart);
1948
+ const equalsIndex = token.indexOf("=");
1949
+ if (equalsIndex > 0) {
1950
+ const inputName = token.slice(0, equalsIndex);
1951
+ const schema = workflow.inputs[inputName];
1952
+ if (schema?.type === "select") {
1953
+ return completeToken(
1954
+ partial,
1955
+ schema.choices.map((choice) => ({
1956
+ value: `${inputName}=${choice} `,
1957
+ label: choice,
1958
+ description: inputName,
1959
+ })),
1960
+ );
1961
+ }
1962
+ if (schema?.type === "boolean") {
1963
+ return completeToken(partial, [
1964
+ { value: `${inputName}=true `, label: "true", description: inputName },
1965
+ { value: `${inputName}=false `, label: "false", description: inputName },
1966
+ ]);
1967
+ }
1968
+ return null;
1969
+ }
1970
+
1971
+ const inputCompletions: PiArgumentCompletion[] = Object.entries(workflow.inputs)
1972
+ .map(([name, schema]) => ({
1973
+ value: `${name}=`,
1974
+ label: name,
1975
+ description: schema.description,
1976
+ }));
1977
+ return completeToken(partial, [
1978
+ { value: "--no-picker ", label: "--no-picker", description: "Skip interactive input picker" },
1979
+ { value: "--help ", label: "--help", description: "Show this workflow's input schema" },
1980
+ ...inputCompletions,
1981
+ ]);
1982
+ },
1983
+ }, workflowCommands);
1984
+
1985
+ // -------------------------------------------------------------------------
1986
+ // 3. Register message renderers for lifecycle events (§5.6)
1987
+ // -------------------------------------------------------------------------
1988
+ // Chat-scroll renderers are deliberately limited to run-level events
1989
+ // (start + end). Per-stage chatter is owned by the orchestrator pane —
1990
+ // duplicating it into chat scroll just creates visual noise and pushes
1991
+ // older chat content out of view every time a stage transitions.
1992
+ if (typeof pi.registerMessageRenderer === "function") {
1993
+ pi.registerMessageRenderer("workflow.run.start", (payload) =>
1994
+ renderRunBanner(payload as RunStartPayload),
1995
+ );
1996
+ pi.registerMessageRenderer("workflow.run.end", (payload) =>
1997
+ renderRunSummary(payload as RunEndPayload),
1998
+ );
1999
+ // Inline workflow-input form (Option C in the design conversation):
2000
+ // a sticky chat-history card driven by a custom EditorComponent. The
2001
+ // renderer reads form state from the module-level store keyed by
2002
+ // `details.formId`. Registered once; openInlineInputsForm() emits the
2003
+ // card via pi.sendMessage on each invocation.
2004
+ registerInlineFormRenderer(pi, deriveGraphTheme({}));
2005
+
2006
+ // Chat-scroll surfaces for /workflow run|list|status|status <id>. Bypasses
2007
+ // the default `notify`/`Text(paddingX=1)` path so band+card chrome
2008
+ // receives the *real* chat content width instead of a `cols - 2` heuristic.
2009
+ // See src/tui/chat-surface-message.ts for the contract.
2010
+ registerChatSurfaceRenderer(pi, deriveGraphTheme({}));
2011
+ }
2012
+
2013
+ // -------------------------------------------------------------------------
2014
+ // 4. Persistence: session_start restore + session_before_compact hook (§5.6, Phase D)
2015
+ // -------------------------------------------------------------------------
2016
+ if (typeof pi.on === "function") {
2017
+ pi.on("session_start", async (_event, ctx) => {
2018
+ // Workflow lifecycle is scoped to the originating chat session.
2019
+ // A new session inherits a clean store; any leftover runs from a
2020
+ // previous session in the same pi process are killed (subprocess
2021
+ // aborted) and dropped. `restoreOnSessionStart` below then loads
2022
+ // *this* session's persisted runs from disk.
2023
+ killAllRuns({
2024
+ store,
2025
+ cancellation: cancellationRegistry,
2026
+ persistence: persistenceRef.current,
2027
+ });
2028
+ store.clear();
2029
+
2030
+ // pi-intercom session naming lives here so we don't trip the
2031
+ // loader's "Action methods cannot be called during extension
2032
+ // loading" guard.
2033
+ intercomParentSession = registerIntercomParentSession(pi);
2034
+
2035
+ // Ensure config+discovery are ready before restoring in-flight runs —
2036
+ // tunables must be resolved first.
2037
+ await discoveryPromise;
2038
+ if (ctx?.ui) {
2039
+ storeWidgetUnsubscribe?.();
2040
+ storeWidgetUnsubscribe = installStoreWidget({ ui: ctx.ui }, store);
2041
+ }
2042
+
2043
+ const sessionManager = ctx?.sessionManager ?? pi.sessionManager;
2044
+ if (sessionManager) {
2045
+ const cfg = configLoadRef.current?.config;
2046
+ restoreOnSessionStart(
2047
+ sessionManager,
2048
+ {
2049
+ resumeInFlight: cfg?.resumeInFlight ?? "ask",
2050
+ persistRuns: cfg?.persistRuns ?? true,
2051
+ },
2052
+ store,
2053
+ );
2054
+ }
2055
+ });
2056
+
2057
+ installCompactionHook(pi, store);
2058
+ pi.on("session_shutdown", () => {
2059
+ // Tie workflow lifecycle to the chat: when the chat ends, every
2060
+ // in-flight workflow is killed so we don't leave subprocesses
2061
+ // burning tokens with no UI to surface their progress.
2062
+ intercomControlUnsubscribe?.();
2063
+ intercomControlUnsubscribe = null;
2064
+ killAllRuns({
2065
+ store,
2066
+ cancellation: cancellationRegistry,
2067
+ persistence: persistenceRef.current,
2068
+ });
2069
+ storeWidgetUnsubscribe?.();
2070
+ storeWidgetUnsubscribe = null;
2071
+ });
2072
+ }
2073
+
2074
+ storeWidgetUnsubscribe = installStoreWidget(pi, store);
2075
+ installToolExecutionHooks(pi, store);
2076
+
2077
+ // -------------------------------------------------------------------------
2078
+ // 5. Register F2 keyboard shortcut — open graph overlay for active run.
2079
+ // Falls back to noop when pi.registerShortcut is absent (degraded runtime).
2080
+ // Existing API shape: (key, { description, handler }).
2081
+ //
2082
+ // Note: the historical `ctrl+h` toggle was removed when workflow runs
2083
+ // became background-by-default — a global toggle is no longer the
2084
+ // primary way to manage visibility. Inside the pane, press `h` to
2085
+ // hide (calls setHidden(true) on the overlay handle); re-open via
2086
+ // `F2` or `/workflow connect <id>`.
2087
+ // -------------------------------------------------------------------------
2088
+ if (typeof pi.registerShortcut === "function") {
2089
+ // Prefer the in-flight run; if nothing's active, fall back to the
2090
+ // most recently observed run so users can still review what just
2091
+ // finished without typing `/workflow resume <id>`.
2092
+ const openPane = (ctx?: PiCommandContext): void => {
2093
+ const activeRunId = store.activeRunId();
2094
+ const fallback = activeRunId ?? store.runs().at(-1)?.id ?? null;
2095
+ overlay.open(fallback, overlaySurfaceFromContext(ctx));
2096
+ };
2097
+
2098
+ pi.registerShortcut("F2", {
2099
+ description: "Open workflow orchestrator pane",
2100
+ handler: openPane,
2101
+ });
2102
+ }
2103
+
2104
+ // -------------------------------------------------------------------------
2105
+ // 6. Register sibling integrations (Phase G — §5.8, §5.9, §5.10)
2106
+ // All registration calls are guarded; no throw when sibling is absent.
2107
+ // Note: registerIntercomParentSession (pi-intercom session naming) calls
2108
+ // pi.setSessionName which is an action method — see session_start handler
2109
+ // above for that registration.
2110
+ // -------------------------------------------------------------------------
2111
+
2112
+ // pi-intercom: route subagent:control-intercom events to overlay/store callbacks.
2113
+ // buildIntercomCallbacks wires store.recordNotice, pi.ui.confirm (when present),
2114
+ // and pi.events.emit (when present) so escalations are never silently dropped.
2115
+ intercomControlUnsubscribe = subscribeIntercomControl(
2116
+ pi,
2117
+ buildIntercomCallbacks({
2118
+ store,
2119
+ emit:
2120
+ typeof pi.events?.emit === "function"
2121
+ ? (event, payload) => pi.events!.emit!(event, payload)
2122
+ : undefined,
2123
+ confirm:
2124
+ typeof pi.ui?.confirm === "function"
2125
+ ? (title, message) => pi.ui!.confirm!(title, message)
2126
+ : undefined,
2127
+ }),
2128
+ );
2129
+
2130
+ // -------------------------------------------------------------------------
2131
+ // 7. Suppress pi's optimistic "Working… (esc to interrupt)" loader
2132
+ // for our slash commands. Workflow commands are synchronous picker /
2133
+ // connect / inspect UIs, not streaming turns — the loader is noise
2134
+ // that pads chrome above the picker. The `on("input")` hook fires
2135
+ // BEFORE `startPendingSubmission`, so returning `{ action: "handled" }`
2136
+ // short-circuits the host before the loader starts. We dispatch the
2137
+ // registered handler ourselves. See `installInputInterceptor` for
2138
+ // the full rationale and host pipeline reference.
2139
+ // -------------------------------------------------------------------------
2140
+ installInputInterceptor(pi, workflowCommands);
2141
+ }
2142
+
2143
+ export default factory;