@esso0428/pi-subagents 0.17.16 → 0.17.18

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 (359) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/ROADMAP.md +87 -0
  3. package/docs/post-0.17.6-agents-roster-viewer-spec.md +42 -0
  4. package/docs/post-0.17.6-durable-history-spec.md +41 -0
  5. package/docs/post-0.17.6-feature-specs.md +50 -0
  6. package/docs/post-0.17.6-nested-agents-spec.md +38 -0
  7. package/docs/post-0.17.6-recovery-shutdown-spec.md +46 -0
  8. package/docs/post-0.17.6-ui-latency-baseline-spec.md +46 -0
  9. package/docs/post-0.17.6-workflow-rpc-lifecycle-spec.md +54 -0
  10. package/package.json +1 -1
  11. package/src/agent-history.ts +2 -54
  12. package/src/agent-manager.ts +406 -1288
  13. package/src/agent-runner.ts +27 -251
  14. package/src/agent-types.ts +32 -188
  15. package/src/cross-extension-rpc.ts +20 -96
  16. package/src/custom-agents.ts +13 -170
  17. package/src/index.ts +480 -1920
  18. package/src/invocation-config.ts +3 -118
  19. package/src/model-resolver.ts +0 -18
  20. package/src/output-file.ts +6 -61
  21. package/src/prompts.ts +2 -45
  22. package/src/schedule.ts +14 -35
  23. package/src/settings.ts +2 -301
  24. package/src/status-note.ts +1 -66
  25. package/src/types.ts +10 -177
  26. package/src/ui/agent-widget.ts +57 -278
  27. package/src/ui/conversation-blocks.ts +0 -6
  28. package/src/ui/conversation-timeline.ts +25 -139
  29. package/src/ui/conversation-viewer.ts +48 -212
  30. package/src/ui/schedule-menu.ts +8 -9
  31. package/src/usage.ts +2 -109
  32. package/src/worktree.ts +55 -69
  33. package/dist/abortable.d.ts +0 -13
  34. package/dist/abortable.d.ts.map +0 -1
  35. package/dist/abortable.js +0 -43
  36. package/dist/abortable.js.map +0 -1
  37. package/dist/agent-color.d.ts +0 -36
  38. package/dist/agent-color.d.ts.map +0 -1
  39. package/dist/agent-color.js +0 -124
  40. package/dist/agent-color.js.map +0 -1
  41. package/dist/agent-file-toggle.d.ts +0 -126
  42. package/dist/agent-file-toggle.d.ts.map +0 -1
  43. package/dist/agent-file-toggle.js +0 -259
  44. package/dist/agent-file-toggle.js.map +0 -1
  45. package/dist/agent-history-list.d.ts +0 -19
  46. package/dist/agent-history-list.d.ts.map +0 -1
  47. package/dist/agent-history-list.js +0 -69
  48. package/dist/agent-history-list.js.map +0 -1
  49. package/dist/agent-history.d.ts +0 -35
  50. package/dist/agent-history.d.ts.map +0 -1
  51. package/dist/agent-history.js +0 -188
  52. package/dist/agent-history.js.map +0 -1
  53. package/dist/agent-manager.d.ts +0 -503
  54. package/dist/agent-manager.d.ts.map +0 -1
  55. package/dist/agent-manager.js +0 -1572
  56. package/dist/agent-manager.js.map +0 -1
  57. package/dist/agent-recovery.d.ts +0 -37
  58. package/dist/agent-recovery.d.ts.map +0 -1
  59. package/dist/agent-recovery.js +0 -171
  60. package/dist/agent-recovery.js.map +0 -1
  61. package/dist/agent-runner.d.ts +0 -303
  62. package/dist/agent-runner.d.ts.map +0 -1
  63. package/dist/agent-runner.js +0 -1003
  64. package/dist/agent-runner.js.map +0 -1
  65. package/dist/agent-types.d.ts +0 -120
  66. package/dist/agent-types.d.ts.map +0 -1
  67. package/dist/agent-types.js +0 -301
  68. package/dist/agent-types.js.map +0 -1
  69. package/dist/child-context.d.ts +0 -3
  70. package/dist/child-context.d.ts.map +0 -1
  71. package/dist/child-context.js +0 -13
  72. package/dist/child-context.js.map +0 -1
  73. package/dist/context.d.ts +0 -13
  74. package/dist/context.d.ts.map +0 -1
  75. package/dist/context.js +0 -57
  76. package/dist/context.js.map +0 -1
  77. package/dist/cross-extension-rpc.d.ts +0 -67
  78. package/dist/cross-extension-rpc.d.ts.map +0 -1
  79. package/dist/cross-extension-rpc.js +0 -139
  80. package/dist/cross-extension-rpc.js.map +0 -1
  81. package/dist/custom-agents.d.ts +0 -55
  82. package/dist/custom-agents.d.ts.map +0 -1
  83. package/dist/custom-agents.js +0 -309
  84. package/dist/custom-agents.js.map +0 -1
  85. package/dist/default-agents.d.ts +0 -8
  86. package/dist/default-agents.d.ts.map +0 -1
  87. package/dist/default-agents.js +0 -123
  88. package/dist/default-agents.js.map +0 -1
  89. package/dist/enabled-models.d.ts +0 -50
  90. package/dist/enabled-models.d.ts.map +0 -1
  91. package/dist/enabled-models.js +0 -146
  92. package/dist/enabled-models.js.map +0 -1
  93. package/dist/env.d.ts +0 -7
  94. package/dist/env.d.ts.map +0 -1
  95. package/dist/env.js +0 -29
  96. package/dist/env.js.map +0 -1
  97. package/dist/group-join.d.ts +0 -33
  98. package/dist/group-join.d.ts.map +0 -1
  99. package/dist/group-join.js +0 -117
  100. package/dist/group-join.js.map +0 -1
  101. package/dist/index.d.ts +0 -51
  102. package/dist/index.d.ts.map +0 -1
  103. package/dist/index.js +0 -3687
  104. package/dist/index.js.map +0 -1
  105. package/dist/invocation-config.d.ts +0 -108
  106. package/dist/invocation-config.d.ts.map +0 -1
  107. package/dist/invocation-config.js +0 -84
  108. package/dist/invocation-config.js.map +0 -1
  109. package/dist/memory.d.ts +0 -54
  110. package/dist/memory.d.ts.map +0 -1
  111. package/dist/memory.js +0 -166
  112. package/dist/memory.js.map +0 -1
  113. package/dist/mention-clone.d.ts +0 -88
  114. package/dist/mention-clone.d.ts.map +0 -1
  115. package/dist/mention-clone.js +0 -154
  116. package/dist/mention-clone.js.map +0 -1
  117. package/dist/mention.d.ts +0 -82
  118. package/dist/mention.d.ts.map +0 -1
  119. package/dist/mention.js +0 -132
  120. package/dist/mention.js.map +0 -1
  121. package/dist/model-resolver.d.ts +0 -37
  122. package/dist/model-resolver.d.ts.map +0 -1
  123. package/dist/model-resolver.js +0 -96
  124. package/dist/model-resolver.js.map +0 -1
  125. package/dist/model-scope.d.ts +0 -50
  126. package/dist/model-scope.d.ts.map +0 -1
  127. package/dist/model-scope.js +0 -49
  128. package/dist/model-scope.js.map +0 -1
  129. package/dist/nested-tools.d.ts +0 -57
  130. package/dist/nested-tools.d.ts.map +0 -1
  131. package/dist/nested-tools.js +0 -301
  132. package/dist/nested-tools.js.map +0 -1
  133. package/dist/nico-overrides.d.ts +0 -54
  134. package/dist/nico-overrides.d.ts.map +0 -1
  135. package/dist/nico-overrides.js +0 -170
  136. package/dist/nico-overrides.js.map +0 -1
  137. package/dist/output-file.d.ts +0 -44
  138. package/dist/output-file.d.ts.map +0 -1
  139. package/dist/output-file.js +0 -156
  140. package/dist/output-file.js.map +0 -1
  141. package/dist/prompts.d.ts +0 -56
  142. package/dist/prompts.d.ts.map +0 -1
  143. package/dist/prompts.js +0 -92
  144. package/dist/prompts.js.map +0 -1
  145. package/dist/schedule-store.d.ts +0 -39
  146. package/dist/schedule-store.d.ts.map +0 -1
  147. package/dist/schedule-store.js +0 -156
  148. package/dist/schedule-store.js.map +0 -1
  149. package/dist/schedule.d.ts +0 -110
  150. package/dist/schedule.d.ts.map +0 -1
  151. package/dist/schedule.js +0 -360
  152. package/dist/schedule.js.map +0 -1
  153. package/dist/settings.d.ts +0 -354
  154. package/dist/settings.d.ts.map +0 -1
  155. package/dist/settings.js +0 -247
  156. package/dist/settings.js.map +0 -1
  157. package/dist/skill-loader.d.ts +0 -25
  158. package/dist/skill-loader.d.ts.map +0 -1
  159. package/dist/skill-loader.js +0 -94
  160. package/dist/skill-loader.js.map +0 -1
  161. package/dist/status-note.d.ts +0 -62
  162. package/dist/status-note.d.ts.map +0 -1
  163. package/dist/status-note.js +0 -86
  164. package/dist/status-note.js.map +0 -1
  165. package/dist/structured-output.d.ts +0 -62
  166. package/dist/structured-output.d.ts.map +0 -1
  167. package/dist/structured-output.js +0 -113
  168. package/dist/structured-output.js.map +0 -1
  169. package/dist/types.d.ts +0 -372
  170. package/dist/types.d.ts.map +0 -1
  171. package/dist/types.js +0 -6
  172. package/dist/types.js.map +0 -1
  173. package/dist/ui/agent-mention.d.ts +0 -83
  174. package/dist/ui/agent-mention.d.ts.map +0 -1
  175. package/dist/ui/agent-mention.js +0 -188
  176. package/dist/ui/agent-mention.js.map +0 -1
  177. package/dist/ui/agent-widget.d.ts +0 -241
  178. package/dist/ui/agent-widget.d.ts.map +0 -1
  179. package/dist/ui/agent-widget.js +0 -992
  180. package/dist/ui/agent-widget.js.map +0 -1
  181. package/dist/ui/ccstyle/diff/ansi-utils.d.ts +0 -11
  182. package/dist/ui/ccstyle/diff/ansi-utils.d.ts.map +0 -1
  183. package/dist/ui/ccstyle/diff/ansi-utils.js +0 -145
  184. package/dist/ui/ccstyle/diff/ansi-utils.js.map +0 -1
  185. package/dist/ui/ccstyle/diff/diff-presentation.d.ts +0 -12
  186. package/dist/ui/ccstyle/diff/diff-presentation.d.ts.map +0 -1
  187. package/dist/ui/ccstyle/diff/diff-presentation.js +0 -48
  188. package/dist/ui/ccstyle/diff/diff-presentation.js.map +0 -1
  189. package/dist/ui/ccstyle/diff/diff-renderer.d.ts +0 -46
  190. package/dist/ui/ccstyle/diff/diff-renderer.d.ts.map +0 -1
  191. package/dist/ui/ccstyle/diff/diff-renderer.js +0 -2049
  192. package/dist/ui/ccstyle/diff/diff-renderer.js.map +0 -1
  193. package/dist/ui/ccstyle/diff/line-width-safety.d.ts +0 -12
  194. package/dist/ui/ccstyle/diff/line-width-safety.d.ts.map +0 -1
  195. package/dist/ui/ccstyle/diff/line-width-safety.js +0 -58
  196. package/dist/ui/ccstyle/diff/line-width-safety.js.map +0 -1
  197. package/dist/ui/ccstyle/diff/render-utils.d.ts +0 -6
  198. package/dist/ui/ccstyle/diff/render-utils.d.ts.map +0 -1
  199. package/dist/ui/ccstyle/diff/render-utils.js +0 -25
  200. package/dist/ui/ccstyle/diff/render-utils.js.map +0 -1
  201. package/dist/ui/ccstyle/diff/shiki-highlight.d.ts +0 -19
  202. package/dist/ui/ccstyle/diff/shiki-highlight.d.ts.map +0 -1
  203. package/dist/ui/ccstyle/diff/shiki-highlight.js +0 -85
  204. package/dist/ui/ccstyle/diff/shiki-highlight.js.map +0 -1
  205. package/dist/ui/ccstyle/diff/types.d.ts +0 -22
  206. package/dist/ui/ccstyle/diff/types.d.ts.map +0 -1
  207. package/dist/ui/ccstyle/diff/types.js +0 -10
  208. package/dist/ui/ccstyle/diff/types.js.map +0 -1
  209. package/dist/ui/ccstyle/diff/write-display-utils.d.ts +0 -2
  210. package/dist/ui/ccstyle/diff/write-display-utils.d.ts.map +0 -1
  211. package/dist/ui/ccstyle/diff/write-display-utils.js +0 -12
  212. package/dist/ui/ccstyle/diff/write-display-utils.js.map +0 -1
  213. package/dist/ui/ccstyle/tool-renderer.d.ts +0 -17
  214. package/dist/ui/ccstyle/tool-renderer.d.ts.map +0 -1
  215. package/dist/ui/ccstyle/tool-renderer.js +0 -74
  216. package/dist/ui/ccstyle/tool-renderer.js.map +0 -1
  217. package/dist/ui/ccstyle/tool-result.d.ts +0 -44
  218. package/dist/ui/ccstyle/tool-result.d.ts.map +0 -1
  219. package/dist/ui/ccstyle/tool-result.js +0 -423
  220. package/dist/ui/ccstyle/tool-result.js.map +0 -1
  221. package/dist/ui/conversation-blocks.d.ts +0 -46
  222. package/dist/ui/conversation-blocks.d.ts.map +0 -1
  223. package/dist/ui/conversation-blocks.js +0 -313
  224. package/dist/ui/conversation-blocks.js.map +0 -1
  225. package/dist/ui/conversation-nvim.d.ts +0 -8
  226. package/dist/ui/conversation-nvim.d.ts.map +0 -1
  227. package/dist/ui/conversation-nvim.js +0 -117
  228. package/dist/ui/conversation-nvim.js.map +0 -1
  229. package/dist/ui/conversation-role.d.ts +0 -13
  230. package/dist/ui/conversation-role.d.ts.map +0 -1
  231. package/dist/ui/conversation-role.js +0 -39
  232. package/dist/ui/conversation-role.js.map +0 -1
  233. package/dist/ui/conversation-search.d.ts +0 -39
  234. package/dist/ui/conversation-search.d.ts.map +0 -1
  235. package/dist/ui/conversation-search.js +0 -124
  236. package/dist/ui/conversation-search.js.map +0 -1
  237. package/dist/ui/conversation-timeline.d.ts +0 -102
  238. package/dist/ui/conversation-timeline.d.ts.map +0 -1
  239. package/dist/ui/conversation-timeline.js +0 -555
  240. package/dist/ui/conversation-timeline.js.map +0 -1
  241. package/dist/ui/conversation-viewer.d.ts +0 -138
  242. package/dist/ui/conversation-viewer.d.ts.map +0 -1
  243. package/dist/ui/conversation-viewer.js +0 -1175
  244. package/dist/ui/conversation-viewer.js.map +0 -1
  245. package/dist/ui/schedule-menu.d.ts +0 -17
  246. package/dist/ui/schedule-menu.d.ts.map +0 -1
  247. package/dist/ui/schedule-menu.js +0 -95
  248. package/dist/ui/schedule-menu.js.map +0 -1
  249. package/dist/ui/select-item.d.ts +0 -28
  250. package/dist/ui/select-item.d.ts.map +0 -1
  251. package/dist/ui/select-item.js +0 -35
  252. package/dist/ui/select-item.js.map +0 -1
  253. package/dist/ui/viewer-keys.d.ts +0 -21
  254. package/dist/ui/viewer-keys.d.ts.map +0 -1
  255. package/dist/ui/viewer-keys.js +0 -18
  256. package/dist/ui/viewer-keys.js.map +0 -1
  257. package/dist/ui/workflow-card.d.ts +0 -176
  258. package/dist/ui/workflow-card.d.ts.map +0 -1
  259. package/dist/ui/workflow-card.js +0 -333
  260. package/dist/ui/workflow-card.js.map +0 -1
  261. package/dist/ui/workflow-dialog.d.ts +0 -306
  262. package/dist/ui/workflow-dialog.d.ts.map +0 -1
  263. package/dist/ui/workflow-dialog.js +0 -844
  264. package/dist/ui/workflow-dialog.js.map +0 -1
  265. package/dist/ui/workflow-menu.d.ts +0 -42
  266. package/dist/ui/workflow-menu.d.ts.map +0 -1
  267. package/dist/ui/workflow-menu.js +0 -127
  268. package/dist/ui/workflow-menu.js.map +0 -1
  269. package/dist/usage.d.ts +0 -136
  270. package/dist/usage.d.ts.map +0 -1
  271. package/dist/usage.js +0 -121
  272. package/dist/usage.js.map +0 -1
  273. package/dist/workflow/collisions.d.ts +0 -96
  274. package/dist/workflow/collisions.d.ts.map +0 -1
  275. package/dist/workflow/collisions.js +0 -89
  276. package/dist/workflow/collisions.js.map +0 -1
  277. package/dist/workflow/entry.d.ts +0 -33
  278. package/dist/workflow/entry.d.ts.map +0 -1
  279. package/dist/workflow/entry.js +0 -30
  280. package/dist/workflow/entry.js.map +0 -1
  281. package/dist/workflow/host.d.ts +0 -63
  282. package/dist/workflow/host.d.ts.map +0 -1
  283. package/dist/workflow/host.js +0 -363
  284. package/dist/workflow/host.js.map +0 -1
  285. package/dist/workflow/journal.d.ts +0 -98
  286. package/dist/workflow/journal.d.ts.map +0 -1
  287. package/dist/workflow/journal.js +0 -121
  288. package/dist/workflow/journal.js.map +0 -1
  289. package/dist/workflow/json-schema.d.ts +0 -52
  290. package/dist/workflow/json-schema.d.ts.map +0 -1
  291. package/dist/workflow/json-schema.js +0 -112
  292. package/dist/workflow/json-schema.js.map +0 -1
  293. package/dist/workflow/meta.d.ts +0 -68
  294. package/dist/workflow/meta.d.ts.map +0 -1
  295. package/dist/workflow/meta.js +0 -318
  296. package/dist/workflow/meta.js.map +0 -1
  297. package/dist/workflow/progress.d.ts +0 -225
  298. package/dist/workflow/progress.d.ts.map +0 -1
  299. package/dist/workflow/progress.js +0 -362
  300. package/dist/workflow/progress.js.map +0 -1
  301. package/dist/workflow/runtime.d.ts +0 -335
  302. package/dist/workflow/runtime.d.ts.map +0 -1
  303. package/dist/workflow/runtime.js +0 -831
  304. package/dist/workflow/runtime.js.map +0 -1
  305. package/dist/workflow/saved.d.ts +0 -91
  306. package/dist/workflow/saved.d.ts.map +0 -1
  307. package/dist/workflow/saved.js +0 -204
  308. package/dist/workflow/saved.js.map +0 -1
  309. package/dist/workflow/task.d.ts +0 -137
  310. package/dist/workflow/task.d.ts.map +0 -1
  311. package/dist/workflow/task.js +0 -208
  312. package/dist/workflow/task.js.map +0 -1
  313. package/dist/workflow/tool-description.d.ts +0 -39
  314. package/dist/workflow/tool-description.d.ts.map +0 -1
  315. package/dist/workflow/tool-description.js +0 -200
  316. package/dist/workflow/tool-description.js.map +0 -1
  317. package/dist/workflow/worker-source.d.ts +0 -48
  318. package/dist/workflow/worker-source.d.ts.map +0 -1
  319. package/dist/workflow/worker-source.js +0 -779
  320. package/dist/workflow/worker-source.js.map +0 -1
  321. package/dist/worktree.d.ts +0 -53
  322. package/dist/worktree.d.ts.map +0 -1
  323. package/dist/worktree.js +0 -165
  324. package/dist/worktree.js.map +0 -1
  325. package/dist/write-execution.d.ts +0 -42
  326. package/dist/write-execution.d.ts.map +0 -1
  327. package/dist/write-execution.js +0 -138
  328. package/dist/write-execution.js.map +0 -1
  329. package/dist/xml.d.ts +0 -11
  330. package/dist/xml.d.ts.map +0 -1
  331. package/dist/xml.js +0 -13
  332. package/dist/xml.js.map +0 -1
  333. package/src/abortable.ts +0 -43
  334. package/src/agent-color.ts +0 -161
  335. package/src/agent-file-toggle.ts +0 -269
  336. package/src/child-context.ts +0 -15
  337. package/src/mention-clone.ts +0 -196
  338. package/src/mention.ts +0 -141
  339. package/src/model-scope.ts +0 -70
  340. package/src/nested-tools.ts +0 -424
  341. package/src/structured-output.ts +0 -130
  342. package/src/ui/agent-mention.ts +0 -216
  343. package/src/ui/select-item.ts +0 -45
  344. package/src/ui/workflow-card.ts +0 -470
  345. package/src/ui/workflow-dialog.ts +0 -1115
  346. package/src/ui/workflow-menu.ts +0 -166
  347. package/src/workflow/collisions.ts +0 -123
  348. package/src/workflow/entry.ts +0 -47
  349. package/src/workflow/host.ts +0 -403
  350. package/src/workflow/journal.ts +0 -164
  351. package/src/workflow/json-schema.ts +0 -128
  352. package/src/workflow/meta.ts +0 -325
  353. package/src/workflow/progress.ts +0 -550
  354. package/src/workflow/runtime.ts +0 -1219
  355. package/src/workflow/saved.ts +0 -217
  356. package/src/workflow/task.ts +0 -302
  357. package/src/workflow/tool-description.ts +0 -200
  358. package/src/workflow/worker-source.ts +0 -781
  359. package/src/xml.ts +0 -13
@@ -1,166 +0,0 @@
1
- /**
2
- * workflow-menu.ts — `/agents → Workflows`, and the run inspector behind it.
3
- *
4
- * The same shape `schedule-menu.ts` has for `/agents → Scheduled jobs`: the
5
- * submenu and the overlay it opens live here, and everything they need arrives
6
- * as {@link WorkflowMenuDeps} rather than through a closure.
7
- *
8
- * Lives in the agents menu rather than as a top-level `/workflows` command: a
9
- * second command name would only add
10
- * a collision surface (pi renames duplicate commands to `/workflows:1` and
11
- * `/workflows:2`, which breaks the bare name for both).
12
- */
13
-
14
- import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
15
- import type { AgentRecord } from "../types.js";
16
- import { pauseWorkflowTask, resumeWorkflowTask, type WorkflowTask } from "../workflow/task.js";
17
- import { WorkflowDialog } from "./workflow-dialog.js";
18
-
19
- /** Everything the menu and the inspector need from the extension around them. */
20
- export interface WorkflowMenuDeps {
21
- /**
22
- * Live runs by id, read on every use rather than snapshotted: a run that
23
- * settled and was swept between render and keypress must be a no-op, not a
24
- * crash.
25
- */
26
- tasks: ReadonlyMap<string, WorkflowTask>;
27
- /** The record behind an agent id, or undefined once it has been swept. */
28
- getRecord(id: string): AgentRecord | undefined;
29
- /** The conversation overlay `c` opens on an agent row. */
30
- viewAgentConversation(ctx: ExtensionCommandContext, record: AgentRecord): Promise<void>;
31
- }
32
-
33
- /**
34
- * Open the inspector for a workflow run.
35
- *
36
- * All six controls are wired: `onKill` aborts the run's controller, while
37
- * pause/resume and per-agent skip/retry go through `task.control`, the handle
38
- * `runWorkflow` hands back. `onOpenAgent` is the odd one out — it opens the
39
- * child's conversation rather than changing the run. The dialog derives its key
40
- * hints from the actions it is handed, so the footer advertises exactly what
41
- * works — see `WorkflowDialogActions`.
42
- */
43
- export async function showWorkflowDialog(
44
- ctx: ExtensionCommandContext,
45
- task: WorkflowTask,
46
- deps: WorkflowMenuDeps,
47
- ): Promise<void> {
48
- // Use an overlay like the conversation viewer. Inline, the frame would render
49
- // into the conversation and stay in the scrollback after it closed.
50
- const { VIEWPORT_HEIGHT_PCT } = await import("./conversation-viewer.js");
51
- /**
52
- * This dialog's own overlay, so `c` can hide it while the conversation is
53
- * up. Overlays stack, so the viewer would render *over* it either way —
54
- * but the two frames size themselves to different content, and the taller
55
- * one's edges show around the shorter. Hidden, there is nothing to peek
56
- * out, and un-hiding puts the focus back on the dialog when the viewer
57
- * closes.
58
- */
59
- let overlay: { setHidden(hidden: boolean): void } | undefined;
60
- await ctx.ui.custom<undefined>(
61
- (tui, theme, _keybindings, done) =>
62
- new WorkflowDialog(
63
- tui,
64
- // Re-read on every render: the run is in the background, so the
65
- // dialog has to follow it rather than snapshot it at open time.
66
- () => ({
67
- progress: task.workflowProgress,
68
- task: {
69
- status: task.status,
70
- workflowName: task.workflowName,
71
- startTime: task.startTime,
72
- endTime: task.endTime,
73
- totalPausedMs: task.totalPausedMs,
74
- },
75
- meta: task.meta,
76
- agentCount: task.agentCount,
77
- }),
78
- theme,
79
- done,
80
- {
81
- onKill: () => {
82
- if (task.abortController.signal.aborted) return;
83
- task.abortController.abort();
84
- ctx.ui.notify(`Stopped workflow "${task.meta?.name ?? task.id}".`, "info");
85
- },
86
- onPause: () => {
87
- if (pauseWorkflowTask(task)) {
88
- // Named rather than implied: "paused" on a run whose agents are
89
- // still finishing reads as a stronger promise than it is.
90
- ctx.ui.notify("Paused — running agents finish, no new ones start.", "info");
91
- }
92
- },
93
- onResume: () => {
94
- if (resumeWorkflowTask(task)) ctx.ui.notify("Resumed.", "info");
95
- },
96
- onSkipAgent: index => {
97
- if (task.control?.skip(index) !== true) {
98
- ctx.ui.notify("Nothing to skip — that agent has already finished.", "info");
99
- }
100
- },
101
- onRetryAgent: index => {
102
- if (task.control?.retry(index) !== true) {
103
- // The window is exactly "while it is running": before that
104
- // there is nothing to stop, after it the script has its answer.
105
- ctx.ui.notify("Only a running agent can be retried.", "info");
106
- }
107
- },
108
- onOpenAgent: recordId => {
109
- const record = deps.getRecord(recordId);
110
- // A run's children are records like any other, so they are swept
111
- // ten minutes after they finish — the row outlives the
112
- // conversation it points at, and saying why beats an overlay that
113
- // opens empty.
114
- if (record === undefined) {
115
- ctx.ui.notify("No conversation left — agent records are dropped ten minutes after they finish.", "info");
116
- return;
117
- }
118
- overlay?.setHidden(true);
119
- // Caught before the `finally`, so a viewer that fails to open
120
- // still un-hides the dialog and cannot surface as an unhandled
121
- // rejection out of a detached promise.
122
- void deps.viewAgentConversation(ctx, record)
123
- .catch(err => ctx.ui.notify(
124
- `Could not open the conversation: ${err instanceof Error ? err.message : String(err)}`,
125
- "warning",
126
- ))
127
- .finally(() => overlay?.setHidden(false));
128
- },
129
- },
130
- ),
131
- {
132
- overlay: true,
133
- overlayOptions: { anchor: "center", width: "90%", maxHeight: `${VIEWPORT_HEIGHT_PCT}%` },
134
- onHandle: handle => { overlay = handle; },
135
- },
136
- );
137
- }
138
-
139
- /** `/agents → Workflows` — list this session's runs, open one. */
140
- export async function showWorkflowsMenu(
141
- ctx: ExtensionCommandContext,
142
- deps: WorkflowMenuDeps,
143
- ): Promise<void> {
144
- const tasks = [...deps.tasks.values()].sort((a, b) => b.startTime - a.startTime);
145
- if (tasks.length === 0) {
146
- ctx.ui.notify("No workflows in this session.", "info");
147
- return;
148
- }
149
- if (tasks.length === 1) {
150
- await showWorkflowDialog(ctx, tasks[0], deps);
151
- return;
152
- }
153
- // More than one: pick first. Newest at the top, since that is almost
154
- // always the one being asked about. `select` deals in plain strings and
155
- // hands back the string, so the label has to be unique or `indexOf` maps
156
- // the second run of a workflow onto the first — the run id makes it so.
157
- const labels = tasks.map(
158
- task =>
159
- `${task.meta?.name ?? task.id} — ${task.status}, ${task.agentCount} agent${
160
- task.agentCount === 1 ? "" : "s"
161
- } · ${task.id}`,
162
- );
163
- const picked = await ctx.ui.select("Workflows", labels);
164
- const index = picked !== undefined ? labels.indexOf(picked) : -1;
165
- if (index >= 0) await showWorkflowDialog(ctx, tasks[index], deps);
166
- }
@@ -1,123 +0,0 @@
1
- /**
2
- * collisions.ts — deciding what to do when another extension already offers a
3
- * workflow tool.
4
- *
5
- * Workflows are on by default, so this extension can be the *second*
6
- * orchestrator in a session rather than the only one. Two workflow tools in one
7
- * spec is worse than either alone: the model has to guess which to call, and
8
- * pays for both descriptions to find out. The other extension was installed
9
- * deliberately; a default of ours should not compete with it.
10
- *
11
- * ## What counts as a conflict
12
- *
13
- * An exact name match against {@link FOREIGN_WORKFLOW_TOOL_NAMES}, from a tool
14
- * that is not ours. Exact and not a substring on purpose: `Workflow` is a
15
- * common word in tool names that have nothing to do with orchestration
16
- * (`github_workflow_run`, `list_workflows`), and silently disabling the feature
17
- * against one of those would be a bug nobody could see.
18
- *
19
- * Two shapes, both decided here:
20
- *
21
- * 1. **A foreign tool took our name.** Registration is first-wins across
22
- * extensions (`getAllRegisteredTools` skips a name it already has), and the
23
- * winner also overwrites a built-in of the same name. Nothing throws, and
24
- * there is no tool-conflict diagnostic the way there is for shortcuts. Ours
25
- * never reached the registry, so there is nothing to withdraw — but the rest
26
- * of the feature (the menu, the CLI flag) is still live and would drive a
27
- * tool the model cannot call. It comes down with it.
28
- * 2. **A foreign tool sits beside ours** under a different name, typically
29
- * Claude Code's bare `Workflow`. Both are registered and both are offered.
30
- * That one the caller can actually withdraw — `withdraw` says so.
31
- *
32
- * Only one direction of case 1 is detectable. If ours registered first, the
33
- * other extension's tool is the one dropped, and pi exposes no way to see a
34
- * tool that lost — the registry keeps winners only.
35
- *
36
- * Split from the acting half deliberately: everything here is a pure function
37
- * of the tool list, so the policy can be tested without a host that can be made
38
- * to register a competing extension. The caller owns `getAllTools`, the notify
39
- * and the `setActiveTools` — see `resolveWorkflowCollisions` in index.ts.
40
- */
41
-
42
- import { SUBAGENT_TOOL_NAMES } from "../agent-runner.js";
43
-
44
- /**
45
- * Tool names that mean "another extension already orchestrates subagents".
46
- *
47
- * Our own name, because pi resolves a duplicate registration silently, and
48
- * Claude Code's bare `Workflow`, because a port of that tool is what a second
49
- * workflow extension most likely calls itself. Lowercase `workflow` is the same
50
- * tool by pi convention: it is what `@quintinshaw/pi-dynamic-workflows`
51
- * registers, and the match here is exact, so the case has to be listed by hand.
52
- */
53
- export const FOREIGN_WORKFLOW_TOOL_NAMES: ReadonlySet<string> = new Set([
54
- SUBAGENT_TOOL_NAMES.WORKFLOW,
55
- "Workflow",
56
- "workflow",
57
- ]);
58
-
59
- /** The fields of a registered tool this decision reads. */
60
- export interface RegisteredToolInfo {
61
- name: string;
62
- description?: string;
63
- sourceInfo?: { source?: string };
64
- }
65
-
66
- export type WorkflowCollision =
67
- /** Nobody else is offering one. Carry on. */
68
- | { kind: "none" }
69
- /**
70
- * A foreign tool took our name, but the user pinned `workflowsEnabled: true`.
71
- * Nothing changes — pi has already dropped our registration — but it is worth
72
- * reporting, because pi resolved it silently.
73
- */
74
- | { kind: "report"; message: string }
75
- /**
76
- * Stand down for this session. `withdraw` is false in case 1, where ours
77
- * never reached the registry and there is nothing to take out of the active
78
- * set.
79
- */
80
- | { kind: "standDown"; message: string; withdraw: boolean };
81
-
82
- /**
83
- * Decide, from the registered tools alone.
84
- *
85
- * `ownDescription` identifies our own registration: this extension does not
86
- * know its install path, and the description is the one field that is certainly
87
- * ours. `pinned` is an explicit `workflowsEnabled` — a default yields to
88
- * evidence, a choice does not.
89
- */
90
- export function decideWorkflowCollision(input: {
91
- tools: readonly RegisteredToolInfo[];
92
- ownDescription: string;
93
- pinned: boolean;
94
- }): WorkflowCollision {
95
- const foreign = input.tools.find(
96
- tool => FOREIGN_WORKFLOW_TOOL_NAMES.has(tool.name) && tool.description !== input.ownDescription,
97
- );
98
- if (foreign === undefined) return { kind: "none" };
99
-
100
- const source = foreign.sourceInfo?.source ?? "unknown source";
101
- const tookOurName = foreign.name === SUBAGENT_TOOL_NAMES.WORKFLOW;
102
-
103
- if (input.pinned) {
104
- if (!tookOurName) return { kind: "none" };
105
- return {
106
- kind: "report",
107
- message:
108
- `Another extension (${source}) already registers a "${SUBAGENT_TOOL_NAMES.WORKFLOW}" tool. ` +
109
- "Pi keeps the first registration, so this extension's workflow tool is not offered to the " +
110
- "model. Disable one of the two.",
111
- };
112
- }
113
-
114
- return {
115
- kind: "standDown",
116
- message:
117
- `Another extension (${source}) already provides a "${foreign.name}" tool, so this extension's ` +
118
- "workflows are disabled for this session to avoid offering the model two orchestrators. " +
119
- 'Set `"workflowsEnabled": true` in .pi/subagents.json to keep both.',
120
- // Case 1: ours never reached the registry, so there is nothing to withdraw.
121
- withdraw: !tookOurName,
122
- };
123
- }
@@ -1,47 +0,0 @@
1
- /**
2
- * entry.ts — what a finished workflow leaves behind in the session transcript.
3
- *
4
- * A workflow started from `--subagents-workflow-file` has no tool call to hang
5
- * its result card on, so it appends a custom session entry instead. That entry
6
- * has to survive a reload, which is why this is a plain-JSON snapshot rather
7
- * than the live {@link WorkflowTask}: the task holds an `AbortController`, the
8
- * script source and the run's control handle, none of which belongs in a
9
- * session file.
10
- *
11
- * Deliberately free of any renderer import. The card this data renders through
12
- * lives in `ui/workflow-card.ts` (`renderWorkflowEntryCard`), so the shape a
13
- * session file stores does not depend on the code that draws it.
14
- */
15
-
16
- import type { WorkflowMeta } from "./meta.js";
17
- import type { WorkflowEntry, WorkflowRunStatus } from "./progress.js";
18
- import type { WorkflowTask } from "./task.js";
19
-
20
- /** `customType` of the session entry a flag-launched workflow renders through. */
21
- export const WORKFLOW_ENTRY_TYPE = "subagents:workflow";
22
-
23
- /** The persisted snapshot of a settled run. */
24
- export interface WorkflowEntryData {
25
- name: string;
26
- status: WorkflowRunStatus;
27
- startTime: number;
28
- endTime?: number;
29
- progress: WorkflowEntry[];
30
- agentCount: number;
31
- totalTokens: number;
32
- meta?: WorkflowMeta;
33
- }
34
-
35
- /** Snapshot a settled task for {@link WORKFLOW_ENTRY_TYPE}. */
36
- export function workflowEntryData(task: WorkflowTask): WorkflowEntryData {
37
- return {
38
- name: task.workflowName ?? task.id,
39
- status: task.status,
40
- startTime: task.startTime,
41
- endTime: task.endTime,
42
- progress: task.workflowProgress,
43
- agentCount: task.agentCount,
44
- totalTokens: task.totalTokens,
45
- ...(task.meta !== undefined ? { meta: task.meta } : {}),
46
- };
47
- }