@gotgenes/pi-subagents 18.0.1 → 18.0.3

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 (268) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/docs/architecture/architecture.md +165 -203
  3. package/docs/architecture/history/phase-19-implement-ui-decisions.md +282 -0
  4. package/package.json +6 -7
  5. package/src/config/default-agents.ts +3 -0
  6. package/src/lifecycle/subagent.ts +25 -14
  7. package/src/observation/notification.ts +23 -10
  8. package/src/observation/subagent-events-observer.ts +1 -3
  9. package/src/runtime.ts +2 -1
  10. package/src/service/service-adapter.ts +20 -17
  11. package/src/session/model-resolver.ts +31 -30
  12. package/src/tools/agent-tool.ts +17 -13
  13. package/src/tools/get-result-report.ts +60 -0
  14. package/src/tools/get-result-tool.ts +25 -40
  15. package/src/tools/helpers.ts +21 -5
  16. package/src/tools/spawn-config.ts +5 -5
  17. package/src/tools/steer-tool.ts +37 -27
  18. package/src/types.ts +4 -1
  19. package/src/ui/session-navigator.ts +0 -2
  20. package/.prettierignore +0 -5
  21. package/AGENTS.md +0 -7
  22. package/docs/plans/0048-implement-subagents-api.md +0 -304
  23. package/docs/plans/0049-remove-group-join-output-file-rpc.md +0 -180
  24. package/docs/plans/0051-update-adr-0001-hard-fork.md +0 -77
  25. package/docs/plans/0052-remove-scheduled-subagents.md +0 -133
  26. package/docs/plans/0053-extract-model-resolution-from-execute.md +0 -181
  27. package/docs/plans/0054-decompose-index-into-modules.md +0 -302
  28. package/docs/plans/0057-structured-debug-logging.md +0 -154
  29. package/docs/plans/0061-session-format-transcript.md +0 -284
  30. package/docs/plans/0066-replace-as-any-with-sdk-types.md +0 -215
  31. package/docs/plans/0069-create-subagent-runtime.md +0 -345
  32. package/docs/plans/0070-extract-event-handlers.md +0 -306
  33. package/docs/plans/0071-extract-session-config-assembler.md +0 -362
  34. package/docs/plans/0072-inject-agent-manager-collaborators.md +0 -329
  35. package/docs/plans/0076-inject-cwd-into-agent-manager.md +0 -102
  36. package/docs/plans/0077-inject-project-agents-dir.md +0 -115
  37. package/docs/plans/0080-consolidate-agent-config-lookup.md +0 -247
  38. package/docs/plans/0084-extract-git-worktree-manager.md +0 -142
  39. package/docs/plans/0087-evolve-subagent-runtime-methods.md +0 -240
  40. package/docs/plans/0098-extract-agent-record-state-machine.md +0 -435
  41. package/docs/plans/0099-replace-ctx-with-parent-snapshot.md +0 -488
  42. package/docs/plans/0100-replace-callback-threading-with-session-subscription.md +0 -454
  43. package/docs/plans/0102-consolidate-test-record-factory.md +0 -176
  44. package/docs/plans/0108-extract-agent-type-registry.md +0 -322
  45. package/docs/plans/0109-extract-settings-manager.md +0 -276
  46. package/docs/plans/0110-agent-activity-tracker.md +0 -297
  47. package/docs/plans/0111-split-agent-record-lifecycle.md +0 -582
  48. package/docs/plans/0112-replace-agent-manager-callbacks.md +0 -241
  49. package/docs/plans/0113-disambiguate-spawn-options.md +0 -155
  50. package/docs/plans/0114-narrow-agent-tool-menu-deps.md +0 -279
  51. package/docs/plans/0115-decompose-agent-tool.md +0 -337
  52. package/docs/plans/0116-type-housekeeping.md +0 -351
  53. package/docs/plans/0118-settings-manager-apply-methods.md +0 -271
  54. package/docs/plans/0123-remove-vi-fn-cast-smell.md +0 -179
  55. package/docs/plans/0131-consolidate-shared-test-fixtures.md +0 -207
  56. package/docs/plans/0132-inject-io-into-session-config.md +0 -219
  57. package/docs/plans/0133-inject-sdk-boundary-into-agent-runner.md +0 -373
  58. package/docs/plans/0134-reduce-as-any-casts.md +0 -366
  59. package/docs/plans/0135-extract-display-helpers.md +0 -182
  60. package/docs/plans/0136-decompose-agent-menu.md +0 -300
  61. package/docs/plans/0144-consolidate-observation-model.md +0 -263
  62. package/docs/plans/0145-decompose-execute-push-ctx-to-boundary.md +0 -290
  63. package/docs/plans/0146-narrow-ui-context.md +0 -319
  64. package/docs/plans/0147-inject-wrap-text-into-conversation-viewer.md +0 -166
  65. package/docs/plans/0148-split-agent-widget-rendering.md +0 -255
  66. package/docs/plans/0152-add-prompt-snippet.md +0 -91
  67. package/docs/plans/0164-reorganize-into-domain-directories.md +0 -409
  68. package/docs/plans/0165-decompose-resolved-spawn-config.md +0 -157
  69. package/docs/plans/0166-extract-parent-session-info.md +0 -231
  70. package/docs/plans/0167-narrow-runner-io.md +0 -150
  71. package/docs/plans/0168-extract-tool-filter-config.md +0 -173
  72. package/docs/plans/0169-extract-run-context-from-run-options.md +0 -194
  73. package/docs/plans/0170-reduce-build-content-lines-complexity.md +0 -225
  74. package/docs/plans/0171-reduce-render-result-complexity.md +0 -200
  75. package/docs/plans/0172-extract-turn-formatting.md +0 -206
  76. package/docs/plans/0180-reorder-append-prompt-for-kv-cache.md +0 -100
  77. package/docs/plans/0185-remove-persistent-agent-memory.md +0 -161
  78. package/docs/plans/0188-replace-any-casts-with-sdk-types.md +0 -162
  79. package/docs/plans/0192-define-session-context-interface.md +0 -107
  80. package/docs/plans/0193-runtime-owns-context-queries.md +0 -245
  81. package/docs/plans/0194-align-tool-interfaces-for-structural-typing.md +0 -139
  82. package/docs/plans/0195-convert-tool-factories-to-classes.md +0 -264
  83. package/docs/plans/0196-convert-runner-menu-to-classes.md +0 -268
  84. package/docs/plans/0205-decompose-render-widget-lines.md +0 -140
  85. package/docs/plans/0206-decompose-show-agent-detail.md +0 -211
  86. package/docs/plans/0207-decompose-agent-widget-update.md +0 -242
  87. package/docs/plans/0208-extract-shared-test-fixtures.md +0 -298
  88. package/docs/plans/0214-convert-remaining-closure-factories-to-classes.md +0 -261
  89. package/docs/plans/0215-decompose-build-parent-context.md +0 -166
  90. package/docs/plans/0216-decompose-start-agent.md +0 -255
  91. package/docs/plans/0217-extract-overwrite-guard.md +0 -176
  92. package/docs/plans/0218-push-sdk-boundary-in-settings.md +0 -172
  93. package/docs/plans/0219-reduce-test-duplication-top-3-clone-families.md +0 -162
  94. package/docs/plans/0227-evolve-agent-record-into-agent.md +0 -322
  95. package/docs/plans/0228-async-start-agent-dissolve-run-handle.md +0 -288
  96. package/docs/plans/0229-agent-born-complete.md +0 -564
  97. package/docs/plans/0230-extract-concurrency-queue.md +0 -265
  98. package/docs/plans/0231-push-exec-registry-to-runner.md +0 -245
  99. package/docs/plans/0232-agent-resume-internal-observer-lifecycle.md +0 -180
  100. package/docs/plans/0237-remove-disallowed-tools.md +0 -180
  101. package/docs/plans/0238-remove-extensions-filtering.md +0 -191
  102. package/docs/plans/0239-collapse-filter-active-tools.md +0 -217
  103. package/docs/plans/0242-rename-agent-tool-to-subagent.md +0 -165
  104. package/docs/plans/0256-extract-worktree-isolation.md +0 -256
  105. package/docs/plans/0257-extract-child-session-factory.md +0 -285
  106. package/docs/plans/0262-add-workspace-provider-seam.md +0 -264
  107. package/docs/plans/0264-remove-extension-lifecycle-control.md +0 -277
  108. package/docs/plans/0265-born-complete-subagent-session.md +0 -333
  109. package/docs/plans/0270-type-consumable-public-surface.md +0 -204
  110. package/docs/plans/0272-export-workspace-collaborator-types.md +0 -147
  111. package/docs/plans/0277-encapsulate-agent-session.md +0 -304
  112. package/docs/plans/0280-rename-agent-to-subagent.md +0 -197
  113. package/docs/plans/0360-custom-agents-default-append.md +0 -132
  114. package/docs/plans/0373-extract-subagent-state.md +0 -250
  115. package/docs/plans/0374-encapsulate-subagent-start-notification.md +0 -268
  116. package/docs/plans/0375-extract-run-listener-workspace-bracket.md +0 -300
  117. package/docs/plans/0376-extract-manager-observer.md +0 -232
  118. package/docs/plans/0377-split-widget-delegation-from-runtime.md +0 -254
  119. package/docs/plans/0378-consolidate-lifecycle-test-fixtures.md +0 -243
  120. package/docs/plans/0379-consolidate-ui-tools-test-fixtures.md +0 -335
  121. package/docs/plans/0380-extract-layered-settings-loader.md +0 -223
  122. package/docs/plans/0381-replace-concurrency-queue-with-limiter.md +0 -267
  123. package/docs/plans/0400-include-parent-prompt-in-replace-mode.md +0 -199
  124. package/docs/plans/0403-abort-subagents-on-interrupt.md +0 -180
  125. package/docs/plans/0412-unify-session-mock-builders.md +0 -146
  126. package/docs/plans/0420-fold-run-metrics-live-activity-onto-record.md +0 -228
  127. package/docs/plans/0421-migrate-activity-readers-to-record-getters.md +0 -309
  128. package/docs/plans/0422-delete-activity-tracker-ui-observer.md +0 -204
  129. package/docs/plans/0423-widget-self-drive-from-lifecycle.md +0 -264
  130. package/docs/plans/0424-drop-widget-dep-from-subagent-tool.md +0 -166
  131. package/docs/plans/0425-reconcile-subagent-events-contract.md +0 -144
  132. package/docs/plans/0426-consolidate-residual-test-clone-families.md +0 -235
  133. package/docs/plans/0427-reconsider-ui-direction.md +0 -212
  134. package/docs/plans/0441-remove-agent-definition-management-subtree.md +0 -180
  135. package/docs/plans/0442-dissolve-agents-conversation-viewer.md +0 -195
  136. package/docs/plans/0443-consolidate-remaining-test-clone-families.md +0 -268
  137. package/docs/plans/0444-shrink-widget-to-background-agents.md +0 -156
  138. package/docs/plans/0445-native-session-navigation.md +0 -365
  139. package/docs/plans/0446-spike-session-navigation-entry-criteria.md +0 -171
  140. package/docs/plans/0447-extract-subagents-settings-command.md +0 -220
  141. package/docs/plans/0448-block-disabled-agent-spawn.md +0 -207
  142. package/docs/plans/0462-navigation-renderer-tui-components.md +0 -338
  143. package/docs/plans/0463-file-snapshot-source-evicted-agents.md +0 -306
  144. package/docs/plans/0470-refresh-readme-command-surface.md +0 -159
  145. package/docs/retro/0048-implement-subagents-api.md +0 -44
  146. package/docs/retro/0049-remove-group-join-output-file-rpc.md +0 -49
  147. package/docs/retro/0051-update-adr-0001-hard-fork.md +0 -39
  148. package/docs/retro/0053-extract-model-resolution-from-execute.md +0 -40
  149. package/docs/retro/0054-decompose-index-into-modules.md +0 -53
  150. package/docs/retro/0057-structured-debug-logging.md +0 -77
  151. package/docs/retro/0061-session-format-transcript.md +0 -41
  152. package/docs/retro/0066-replace-as-any-with-sdk-types.md +0 -44
  153. package/docs/retro/0069-create-subagent-runtime.md +0 -43
  154. package/docs/retro/0070-extract-event-handlers.md +0 -49
  155. package/docs/retro/0071-extract-session-config-assembler.md +0 -60
  156. package/docs/retro/0072-inject-agent-manager-collaborators.md +0 -46
  157. package/docs/retro/0076-inject-cwd-into-agent-manager.md +0 -35
  158. package/docs/retro/0077-inject-project-agents-dir.md +0 -33
  159. package/docs/retro/0080-consolidate-agent-config-lookup.md +0 -35
  160. package/docs/retro/0084-extract-git-worktree-manager.md +0 -37
  161. package/docs/retro/0087-evolve-subagent-runtime-methods.md +0 -42
  162. package/docs/retro/0098-extract-agent-record-state-machine.md +0 -46
  163. package/docs/retro/0099-replace-ctx-with-parent-snapshot.md +0 -37
  164. package/docs/retro/0100-replace-callback-threading-with-session-subscription.md +0 -36
  165. package/docs/retro/0102-consolidate-test-record-factory.md +0 -30
  166. package/docs/retro/0108-extract-agent-type-registry.md +0 -41
  167. package/docs/retro/0109-extract-settings-manager.md +0 -55
  168. package/docs/retro/0110-agent-activity-tracker.md +0 -44
  169. package/docs/retro/0111-split-agent-record-lifecycle.md +0 -61
  170. package/docs/retro/0112-replace-agent-manager-callbacks.md +0 -35
  171. package/docs/retro/0113-disambiguate-spawn-options.md +0 -29
  172. package/docs/retro/0114-narrow-agent-tool-menu-deps.md +0 -38
  173. package/docs/retro/0115-decompose-agent-tool.md +0 -51
  174. package/docs/retro/0116-type-housekeeping.md +0 -42
  175. package/docs/retro/0118-settings-manager-apply-methods.md +0 -40
  176. package/docs/retro/0123-remove-vi-fn-cast-smell.md +0 -49
  177. package/docs/retro/0131-consolidate-shared-test-fixtures.md +0 -46
  178. package/docs/retro/0132-inject-io-into-session-config.md +0 -33
  179. package/docs/retro/0133-inject-sdk-boundary-into-agent-runner.md +0 -45
  180. package/docs/retro/0134-reduce-as-any-casts.md +0 -56
  181. package/docs/retro/0135-extract-display-helpers.md +0 -38
  182. package/docs/retro/0136-decompose-agent-menu.md +0 -43
  183. package/docs/retro/0144-consolidate-observation-model.md +0 -39
  184. package/docs/retro/0145-decompose-execute-push-ctx-to-boundary.md +0 -56
  185. package/docs/retro/0146-narrow-ui-context.md +0 -70
  186. package/docs/retro/0147-inject-wrap-text-into-conversation-viewer.md +0 -90
  187. package/docs/retro/0148-split-agent-widget-rendering.md +0 -39
  188. package/docs/retro/0152-add-prompt-snippet.md +0 -34
  189. package/docs/retro/0164-reorganize-into-domain-directories.md +0 -82
  190. package/docs/retro/0165-decompose-resolved-spawn-config.md +0 -78
  191. package/docs/retro/0166-extract-parent-session-info.md +0 -66
  192. package/docs/retro/0167-narrow-runner-io.md +0 -63
  193. package/docs/retro/0168-extract-tool-filter-config.md +0 -76
  194. package/docs/retro/0169-extract-run-context-from-run-options.md +0 -68
  195. package/docs/retro/0170-reduce-build-content-lines-complexity.md +0 -72
  196. package/docs/retro/0171-reduce-render-result-complexity.md +0 -77
  197. package/docs/retro/0172-extract-turn-formatting.md +0 -80
  198. package/docs/retro/0180-reorder-append-prompt-for-kv-cache.md +0 -62
  199. package/docs/retro/0185-remove-persistent-agent-memory.md +0 -73
  200. package/docs/retro/0188-replace-any-casts-with-sdk-types.md +0 -69
  201. package/docs/retro/0192-define-session-context-interface.md +0 -59
  202. package/docs/retro/0193-runtime-owns-context-queries.md +0 -75
  203. package/docs/retro/0194-align-tool-interfaces-for-structural-typing.md +0 -62
  204. package/docs/retro/0195-convert-tool-factories-to-classes.md +0 -84
  205. package/docs/retro/0196-convert-runner-menu-to-classes.md +0 -73
  206. package/docs/retro/0205-decompose-render-widget-lines.md +0 -64
  207. package/docs/retro/0206-decompose-show-agent-detail.md +0 -67
  208. package/docs/retro/0207-decompose-agent-widget-update.md +0 -92
  209. package/docs/retro/0208-extract-shared-test-fixtures.md +0 -102
  210. package/docs/retro/0214-convert-remaining-closure-factories-to-classes.md +0 -66
  211. package/docs/retro/0215-decompose-build-parent-context.md +0 -61
  212. package/docs/retro/0216-decompose-start-agent.md +0 -80
  213. package/docs/retro/0217-extract-overwrite-guard.md +0 -63
  214. package/docs/retro/0218-push-sdk-boundary-in-settings.md +0 -72
  215. package/docs/retro/0219-reduce-test-duplication-top-3-clone-families.md +0 -64
  216. package/docs/retro/0227-evolve-agent-record-into-agent.md +0 -80
  217. package/docs/retro/0228-async-start-agent-dissolve-run-handle.md +0 -80
  218. package/docs/retro/0229-agent-born-complete.md +0 -89
  219. package/docs/retro/0230-extract-concurrency-queue.md +0 -38
  220. package/docs/retro/0231-push-exec-registry-to-runner.md +0 -71
  221. package/docs/retro/0232-agent-resume-internal-observer-lifecycle.md +0 -109
  222. package/docs/retro/0237-remove-disallowed-tools.md +0 -78
  223. package/docs/retro/0238-remove-extensions-filtering.md +0 -72
  224. package/docs/retro/0239-collapse-filter-active-tools.md +0 -70
  225. package/docs/retro/0242-rename-agent-tool-to-subagent.md +0 -82
  226. package/docs/retro/0256-extract-worktree-isolation.md +0 -89
  227. package/docs/retro/0257-extract-child-session-factory.md +0 -33
  228. package/docs/retro/0262-add-workspace-provider-seam.md +0 -89
  229. package/docs/retro/0264-remove-extension-lifecycle-control.md +0 -91
  230. package/docs/retro/0265-born-complete-subagent-session.md +0 -97
  231. package/docs/retro/0270-type-consumable-public-surface.md +0 -108
  232. package/docs/retro/0272-export-workspace-collaborator-types.md +0 -38
  233. package/docs/retro/0277-encapsulate-agent-session.md +0 -80
  234. package/docs/retro/0280-rename-agent-to-subagent.md +0 -96
  235. package/docs/retro/0360-custom-agents-default-append.md +0 -81
  236. package/docs/retro/0373-extract-subagent-state.md +0 -94
  237. package/docs/retro/0374-encapsulate-subagent-start-notification.md +0 -171
  238. package/docs/retro/0375-extract-run-listener-workspace-bracket.md +0 -104
  239. package/docs/retro/0376-extract-manager-observer.md +0 -81
  240. package/docs/retro/0377-split-widget-delegation-from-runtime.md +0 -105
  241. package/docs/retro/0378-consolidate-lifecycle-test-fixtures.md +0 -100
  242. package/docs/retro/0379-consolidate-ui-tools-test-fixtures.md +0 -52
  243. package/docs/retro/0380-extract-layered-settings-loader.md +0 -97
  244. package/docs/retro/0381-replace-concurrency-queue-with-limiter.md +0 -95
  245. package/docs/retro/0400-include-parent-prompt-in-replace-mode.md +0 -84
  246. package/docs/retro/0403-abort-subagents-on-interrupt.md +0 -90
  247. package/docs/retro/0412-unify-session-mock-builders.md +0 -80
  248. package/docs/retro/0420-fold-run-metrics-live-activity-onto-record.md +0 -90
  249. package/docs/retro/0421-migrate-activity-readers-to-record-getters.md +0 -105
  250. package/docs/retro/0422-delete-activity-tracker-ui-observer.md +0 -97
  251. package/docs/retro/0423-widget-self-drive-from-lifecycle.md +0 -112
  252. package/docs/retro/0424-drop-widget-dep-from-subagent-tool.md +0 -89
  253. package/docs/retro/0425-reconcile-subagent-events-contract.md +0 -101
  254. package/docs/retro/0426-consolidate-residual-test-clone-families.md +0 -100
  255. package/docs/retro/0427-reconsider-ui-direction.md +0 -102
  256. package/docs/retro/0441-remove-agent-definition-management-subtree.md +0 -97
  257. package/docs/retro/0442-dissolve-agents-conversation-viewer.md +0 -108
  258. package/docs/retro/0443-consolidate-remaining-test-clone-families.md +0 -28
  259. package/docs/retro/0444-shrink-widget-to-background-agents.md +0 -81
  260. package/docs/retro/0445-native-session-navigation.md +0 -122
  261. package/docs/retro/0446-spike-session-navigation-entry-criteria.md +0 -99
  262. package/docs/retro/0447-extract-subagents-settings-command.md +0 -91
  263. package/docs/retro/0448-block-disabled-agent-spawn.md +0 -75
  264. package/docs/retro/0462-navigation-renderer-tui-components.md +0 -105
  265. package/docs/retro/0463-file-snapshot-source-evicted-agents.md +0 -103
  266. package/docs/retro/0470-refresh-readme-command-surface.md +0 -40
  267. package/src/observation/notification-state.ts +0 -27
  268. package/vitest.config.ts +0 -14
@@ -1,133 +0,0 @@
1
- ---
2
- issue: 52
3
- issue_title: "feat: remove in-process scheduled subagents"
4
- ---
5
-
6
- # Remove in-process scheduled subagents
7
-
8
- ## Problem Statement
9
-
10
- The scheduling subsystem reimplements OS-level cron inside a process that is not designed to be a long-lived daemon.
11
- System cron (or launchd) invoking `pi` directly is strictly superior: it survives crashes and reboots, is inspectable via `crontab -l`, and adds zero lines of code to this extension.
12
- The current implementation weighs ~610 source lines plus ~820 test lines, a `croner` dependency, PID-locked file persistence, and scheduler lifecycle wiring scattered across `index.ts`.
13
-
14
- ## Goals
15
-
16
- - Delete the three scheduling source files (`schedule.ts`, `schedule-store.ts`, `ui/schedule-menu.ts`).
17
- - Delete the three scheduling test files (`schedule.test.ts`, `schedule-store.test.ts`, `schedule-e2e.test.ts`).
18
- - Remove all scheduler wiring from `index.ts` (~200 lines of imports, lifecycle hooks, tool-schema gates, and menu routing).
19
- - Remove `ScheduledSubagent` and `ScheduleStoreData` interfaces from `types.ts`.
20
- - Remove `schedulingEnabled` from `SubagentsSettings`, `SettingsAppliers`, and related sanitize/apply logic in `settings.ts`.
21
- - Remove the `croner` dependency from `package.json`.
22
- - Update `README.md` (remove "Scheduling" section and events-table rows) and package `AGENTS.md` (remove scheduling modules from architecture diagram and tables).
23
- - This is a **breaking change** (`feat!:`) — the `schedule` parameter is removed from the `Agent` tool, and the `subagents:scheduled` / `subagents:scheduler_ready` events are no longer emitted.
24
-
25
- ## Non-Goals
26
-
27
- - Removing `bypassQueue` from `SpawnOptions` in `agent-manager.ts` — it remains useful for cross-extension RPC callers.
28
- - Removing other subsystems slated for removal in the architecture doc (output-file, cross-extension-rpc, group-join) — those are separate issues.
29
- - Providing a migration path or compatibility shim — no known consumers depend on the scheduling events.
30
-
31
- ## Background
32
-
33
- The architecture doc (`docs/architecture/architecture.md`) already marks `schedule.ts`, `schedule-store.ts`, and `ui/schedule-menu.ts` as `← removing`.
34
- This issue executes that plan.
35
-
36
- The scheduling code touches `index.ts` in several distinct regions:
37
-
38
- 1. Imports (lines 27–28, 46)
39
- 2. Scheduler instance creation and `startScheduler()` helper (lines 445–462)
40
- 3. Lifecycle hooks: `session_start`, `session_before_switch`, `session_shutdown` (lines 470–496)
41
- 4. The `schedule` tool-schema param shape, conditional inclusion, and guideline string (lines 621–640, 666, 719)
42
- 5. Schedule execution path in the Agent tool handler (lines 880–918)
43
- 6. `/agents` menu: "Scheduled jobs" entry and routing (lines 1297–1327)
44
- 7. `/agents → Settings → Scheduling` toggle (lines 1855–1867)
45
-
46
- The `settings.ts` module has `schedulingEnabled` woven into `SubagentsSettings`, `SettingsAppliers`, `sanitize()`, and `applySettings()`.
47
-
48
- `types.ts` carries `ScheduledSubagent` (30 lines) and `ScheduleStoreData` (5 lines) — both are only consumed by the scheduling subsystem.
49
-
50
- ## Design Overview
51
-
52
- This is a pure deletion change with no new abstractions.
53
- The approach is inside-out: delete leaf modules first (no dependents), then remove references from the wiring layer (`index.ts`, `settings.ts`, `types.ts`), then clean up docs.
54
-
55
- The `bypassQueue` option on `SpawnOptions` stays — its JSDoc comment mentioning "scheduler" should be updated to a generic description since the scheduler is the only current user but the option is architecturally useful for any caller that needs to skip the concurrency queue.
56
-
57
- ## Module-Level Changes
58
-
59
- ### Delete
60
-
61
- | File | Lines |
62
- | ----------------------------- | ----- |
63
- | `src/schedule.ts` | 365 |
64
- | `src/schedule-store.ts` | 143 |
65
- | `src/ui/schedule-menu.ts` | 104 |
66
- | `test/schedule.test.ts` | 429 |
67
- | `test/schedule-store.test.ts` | 154 |
68
- | `test/schedule-e2e.test.ts` | 237 |
69
-
70
- ### Modify
71
-
72
- | File | Change |
73
- | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
74
- | `src/index.ts` | Remove scheduler imports, instance creation, `startScheduler()`, lifecycle hooks, `scheduleParamShape`/`scheduleParam`/`scheduleGuideline`, schedule execution path in Agent handler, "Scheduled jobs" menu entry + routing, "Scheduling" settings toggle. |
75
- | `src/types.ts` | Remove `ScheduledSubagent` interface and `ScheduleStoreData` interface. |
76
- | `src/settings.ts` | Remove `schedulingEnabled` from `SubagentsSettings` and `SettingsAppliers`. Remove sanitize clause and `applySettings` clause for `schedulingEnabled`. |
77
- | `src/agent-manager.ts` | Update `bypassQueue` JSDoc to remove scheduler-specific language. |
78
- | `package.json` | Remove `"croner": "^10.0.1"` from dependencies. |
79
- | `README.md` | Remove "Scheduling" feature bullet, "Scheduling" subsection (lines 66–96), and `subagents:scheduled` / `subagents:scheduler_ready` rows from the events table. |
80
- | `.pi/skills/package-pi-subagents/SKILL.md` | Remove `schedule.ts`, `schedule-store.ts`, `ui/schedule-menu.ts` from the architecture diagram and module tables. Update `index.ts` description to drop scheduler mention. (`packages/pi-subagents/AGENTS.md` is a stub — the architecture content lives in the skill file.) |
81
-
82
- ## Test Impact Analysis
83
-
84
- 1. No new unit tests are needed — this is pure deletion.
85
- 2. All three scheduling test files (`schedule.test.ts`, `schedule-store.test.ts`, `schedule-e2e.test.ts`) become entirely redundant and are deleted.
86
- 3. Existing tests for `agent-manager`, `agent-runner`, `settings`, and other modules stay as-is.
87
- The `settings.test.ts` file (if it exists) may need minor updates to remove `schedulingEnabled` from fixture data.
88
-
89
- ## TDD Order
90
-
91
- Since this is a removal (not a feature), the order is deletion-first with a single validation pass.
92
-
93
- 1. **Delete scheduling source files.**
94
- Delete `src/schedule.ts`, `src/schedule-store.ts`, `src/ui/schedule-menu.ts`.
95
- Delete `test/schedule.test.ts`, `test/schedule-store.test.ts`, `test/schedule-e2e.test.ts`.
96
- Commit: `feat!: remove scheduled subagents source and tests`
97
-
98
- 2. **Remove scheduler wiring from `index.ts`.**
99
- Remove imports, scheduler instance, `startScheduler()`, lifecycle hooks, schedule-related tool schema params and guideline, schedule execution path in Agent handler, "Scheduled jobs" menu entry/routing, and "Scheduling" settings toggle.
100
- Commit: `feat!: remove scheduler wiring from index.ts`
101
-
102
- 3. **Clean up types and settings.**
103
- Remove `ScheduledSubagent` and `ScheduleStoreData` from `types.ts`.
104
- Remove `schedulingEnabled` from `SubagentsSettings`, `SettingsAppliers`, `sanitize()`, and `applySettings()` in `settings.ts`.
105
- Update `bypassQueue` JSDoc in `agent-manager.ts`.
106
- Commit: `feat!: remove scheduling types and settings`
107
-
108
- 4. **Remove `croner` dependency.**
109
- Remove from `package.json`, run `pnpm install` to update lockfile.
110
- Commit: `build: remove croner dependency`
111
-
112
- 5. **Verify all tests pass.**
113
- Run `pnpm vitest run` in the package.
114
- Fix any test fixtures that reference `schedulingEnabled` or scheduling types.
115
- Commit (if fixes needed): `test: remove scheduling references from test fixtures`
116
-
117
- 6. **Update documentation.**
118
- Update `README.md`: remove scheduling feature bullet, "Scheduling" subsection, and event-table rows.
119
- Update package `AGENTS.md`: remove scheduling modules from architecture diagram and module tables, update `index.ts` description.
120
- Commit: `docs: remove scheduling from README and AGENTS`
121
-
122
- ## Risks and Mitigations
123
-
124
- | Risk | Mitigation |
125
- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
126
- | Missed scheduling reference causes compile error | `grep -rn 'schedule\|Schedule\|croner' src/` after each step to catch stragglers. TypeScript `noEmit` check catches import errors. |
127
- | Test fixtures reference `schedulingEnabled` | Step 5 explicitly scans for and fixes these. |
128
- | `bypassQueue` removal mistakenly included | Explicitly excluded in Non-Goals; plan preserves the option and only updates its JSDoc. |
129
- | Breaking change not communicated | `feat!:` commit prefix triggers a major version bump via release-please. |
130
-
131
- ## Open Questions
132
-
133
- None — the issue scope is fully specified and the architecture doc already ratified this removal.
@@ -1,181 +0,0 @@
1
- ---
2
- issue: 53
3
- issue_title: "refactor: extract model resolution from Agent.execute"
4
- ---
5
-
6
- # Extract model resolution from Agent.execute
7
-
8
- ## Problem Statement
9
-
10
- The `Agent` tool's `execute` callback in `index.ts` contains inline model-resolution logic (~lines 660–670) that determines which model an agent runs with.
11
- This block checks `resolvedConfig.modelInput`, calls `resolveModel()`, distinguishes error strings from resolved model instances, and silently falls back to the parent model for config-specified models that fail resolution.
12
- The logic is not independently testable — it is only exercised through integration-level agent spawning.
13
-
14
- A second, simpler call site in `getModelLabel()` (~line 1043) also calls `resolveModel()` inline but only checks whether the model resolves; it does not need the same fallback semantics.
15
-
16
- ## Goals
17
-
18
- - Extract the inline model-resolution block from `Agent.execute` into a named, unit-testable function in `model-resolver.ts`.
19
- - Keep the existing `resolveModel()` function unchanged — the new function composes it.
20
- - No behavior change: model-resolution priority and fallback semantics remain identical.
21
-
22
- ## Non-Goals
23
-
24
- - Changing the `resolveModel()` fuzzy-matching algorithm.
25
- - Refactoring the `getModelLabel()` call site (~line 1043) — it has different semantics (display-only, no fallback) and does not benefit from the same extraction.
26
- - Refactoring `service-adapter.ts` model resolution — it already uses a clean injected-dependency pattern.
27
- - Changing any public API surface.
28
-
29
- ## Background
30
-
31
- ### Existing modules
32
-
33
- | Module | Role |
34
- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
35
- | `model-resolver.ts` | Exports `resolveModel(input, registry)` — returns a `Model` on success or an error string on failure. |
36
- | `invocation-config.ts` | Exports `resolveAgentInvocationConfig()` — merges tool params with agent config. Returns `modelInput` (the raw string) and `modelFromParams` (whether the string came from tool params vs. agent config). |
37
- | `service-adapter.ts` | Already receives `resolveModel` as a dependency via `AdapterDeps`. Its model resolution is simpler (always throw on failure). |
38
- | `index.ts` | `Agent.execute` contains the inline block. Uses both `modelInput` and `modelFromParams` to decide: (a) return error to user if params-specified model fails, or (b) silently fall back to parent model if config-specified model fails. |
39
-
40
- ### Relevant constraint from AGENTS.md
41
-
42
- > Keep modules focused and composable (one concern per file).
43
-
44
- The new function belongs in `model-resolver.ts` alongside `resolveModel()` since it composes the latter with invocation-level fallback policy.
45
-
46
- ## Design Overview
47
-
48
- ### New function signature
49
-
50
- ```typescript
51
- interface ModelResolutionResult {
52
- model: unknown;
53
- error?: undefined;
54
- }
55
-
56
- interface ModelResolutionError {
57
- model?: undefined;
58
- error: string;
59
- }
60
-
61
- type ModelResolution = ModelResolutionResult | ModelResolutionError;
62
-
63
- function resolveInvocationModel(
64
- parentModel: unknown,
65
- modelInput: string | undefined,
66
- modelFromParams: boolean,
67
- registry: ModelRegistry,
68
- ): ModelResolution;
69
- ```
70
-
71
- ### Decision model
72
-
73
- The function encapsulates the existing three-branch logic:
74
-
75
- 1. **No `modelInput`** → return `{ model: parentModel }` (inherit parent).
76
- 2. **`modelInput` resolves** → return `{ model: resolved }`.
77
- 3. **`modelInput` fails to resolve**:
78
- - If `modelFromParams` (user typed it) → return `{ error: errorMessage }` so the caller can surface it.
79
- - If `!modelFromParams` (agent config specified it) → return `{ model: parentModel }` (silent fallback).
80
-
81
- ### Result shape rationale
82
-
83
- A discriminated union (`ModelResolution`) with `model` and `error` fields avoids the existing `typeof resolved === "string"` type-narrowing smell.
84
- The caller in `index.ts` becomes:
85
-
86
- ```typescript
87
- const resolution = resolveInvocationModel(
88
- ctx.model,
89
- resolvedConfig.modelInput,
90
- resolvedConfig.modelFromParams,
91
- ctx.modelRegistry,
92
- );
93
- if (resolution.error) return textResult(resolution.error);
94
- const model = resolution.model;
95
- ```
96
-
97
- ### Edge cases
98
-
99
- - `modelInput` is `undefined` → short-circuit, return parent model.
100
- - `modelInput` is an empty string → delegates to `resolveModel()`, which currently matches vacuously (documented in existing tests); no change in behavior.
101
-
102
- ## Module-Level Changes
103
-
104
- ### `src/model-resolver.ts`
105
-
106
- - Add `ModelResolutionResult`, `ModelResolutionError`, and `ModelResolution` type exports.
107
- - Add `resolveInvocationModel()` export.
108
- - No changes to existing `resolveModel()`, `ModelEntry`, or `ModelRegistry`.
109
-
110
- ### `src/index.ts`
111
-
112
- - Update import to include `resolveInvocationModel`.
113
- - Replace the inline model-resolution block in `Agent.execute` (~lines 660–670) with a call to `resolveInvocationModel()` and a check on the result.
114
- - Remove the now-unused destructuring of `modelFromParams` from `resolvedConfig` at the call site (it is consumed internally by `resolveInvocationModel` via the parameter).
115
-
116
- ### `test/model-resolver.test.ts`
117
-
118
- - Add a new `describe("resolveInvocationModel")` block with tests covering all three branches plus edge cases.
119
-
120
- ## Test Impact Analysis
121
-
122
- ### New unit tests enabled
123
-
124
- The extraction enables direct testing of the three-branch fallback logic (inherit, resolve, fallback-on-config-failure) that was previously only exercisable through full agent spawning.
125
- Specifically:
126
-
127
- - Parent model inheritance when no `modelInput` is provided.
128
- - Successful resolution returns the resolved model.
129
- - User-specified model failure returns an error.
130
- - Config-specified model failure silently falls back to parent.
131
-
132
- ### Existing tests that stay as-is
133
-
134
- - All existing `resolveModel` tests in `test/model-resolver.test.ts` — they test the lower-level function which is unchanged.
135
- - Integration-level tests in `test/agent-runner.test.ts` and `test/agent-manager.test.ts` — they exercise model usage through the full agent lifecycle.
136
- - `test/invocation-config.test.ts` — unchanged module.
137
- - `test/service-adapter.test.ts` — uses its own injected `resolveModel` dependency, unaffected.
138
-
139
- ### Tests that become redundant
140
-
141
- None.
142
- The inline block was not directly tested anywhere — it was only reached through integration paths that test much more than model resolution.
143
-
144
- ## TDD Order
145
-
146
- 1. **Red → Green: parent model inheritance.**
147
- Test: `resolveInvocationModel` returns `{ model: parentModel }` when `modelInput` is `undefined`.
148
- Commit: `test: add resolveInvocationModel tests for parent model inheritance`
149
-
150
- 2. **Red → Green: successful model resolution.**
151
- Test: returns `{ model: resolvedModel }` when `resolveModel` succeeds (both params-specified and config-specified).
152
- Commit: `test: add resolveInvocationModel tests for successful resolution`
153
-
154
- 3. **Red → Green: user-specified model failure.**
155
- Test: returns `{ error: message }` when `modelFromParams` is `true` and `resolveModel` returns an error string.
156
- Commit: `test: add resolveInvocationModel tests for param model failure`
157
-
158
- 4. **Red → Green: config-specified model silent fallback.**
159
- Test: returns `{ model: parentModel }` when `modelFromParams` is `false` and `resolveModel` returns an error string.
160
- Commit: `test: add resolveInvocationModel tests for config model fallback`
161
-
162
- 5. **Green: implement `resolveInvocationModel` in `model-resolver.ts`.**
163
- All four test cases go green.
164
- Commit: `feat: add resolveInvocationModel to model-resolver`
165
-
166
- 6. **Refactor: replace inline block in `index.ts`.**
167
- Replace the inline model-resolution block in `Agent.execute` with a call to `resolveInvocationModel`.
168
- Run full test suite to confirm no regressions.
169
- Commit: `refactor: use resolveInvocationModel in Agent.execute (#53)`
170
-
171
- ## Risks and Mitigations
172
-
173
- | Risk | Mitigation |
174
- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
175
- | Subtle behavior difference in the extracted function vs. the inline block | TDD steps 1–4 encode the exact current semantics; step 6 is a pure mechanical substitution. |
176
- | `resolveModel` return type is `any \| string` — fragile narrowing | The new function encapsulates the `typeof` check behind a discriminated union, reducing but not eliminating the `any`. Fixing the `any` is out of scope (would require Pi SDK model type changes). |
177
- | Second call site (`getModelLabel`) might seem like it should also use the new function | Explicitly listed as a non-goal — it has display-only semantics with no fallback behavior. |
178
-
179
- ## Open Questions
180
-
181
- None — the extraction is mechanical and the issue's acceptance criteria are unambiguous.
@@ -1,302 +0,0 @@
1
- ---
2
- issue: 54
3
- issue_title: "refactor: decompose src/index.ts into tool + menu modules"
4
- ---
5
-
6
- # Decompose index.ts into tool and menu modules
7
-
8
- ## Problem Statement
9
-
10
- `src/index.ts` is 1,619 lines — the single largest file in the codebase.
11
- It currently holds the extension entrypoint, all three tool definitions (with full execute callbacks and render functions), the custom message renderer, the entire `/agents` interactive menu with all sub-menus, the notification/nudge system, widget and lifecycle wiring, and ~130 lines of helper functions.
12
- None of this code is independently testable — it is all nested inside a single default export closure.
13
-
14
- ## Goals
15
-
16
- - Extract each tool definition into its own module under `src/tools/`.
17
- - Extract the `/agents` menu and all sub-handlers into `src/ui/agent-menu.ts`.
18
- - Extract the notification message renderer into `src/renderer.ts`.
19
- - Extract the completion notification system into `src/notification.ts`.
20
- - Extract shared pure helpers into `src/tools/helpers.ts`.
21
- - Reduce `index.ts` to a thin wire-up (~120–150 lines) that imports and assembles pieces.
22
- - Enable unit testing of each extracted module via narrow dependency interfaces.
23
- - No behavior change — pure extraction refactoring.
24
-
25
- ## Non-Goals
26
-
27
- - Refactoring `agent-manager.ts`, `agent-runner.ts`, or other already-separate modules.
28
- - Adding new features or changing tool behavior.
29
- - Writing exhaustive test suites for every extracted module — establish foundational coverage, not completeness.
30
- - Changing any public API surface (`service.ts` exports, `SubagentsService` interface).
31
-
32
- ## Background
33
-
34
- ### Current structure
35
-
36
- Everything lives inside one `export default function (pi: ExtensionAPI)` closure.
37
- State (`agentActivity`, `pendingNudges`, `widget`, `manager`, `currentCtx`) is declared as closure variables.
38
- Helper functions, tool definitions, menu handlers, and lifecycle hooks are all defined in the same scope.
39
- The only existing test files cover modules that were already separate (`agent-manager.test.ts`, `agent-runner.test.ts`, etc.) — there is no `index.test.ts`.
40
-
41
- ### Architecture reference
42
-
43
- The SKILL's module dependency graph already shows `tools` and `ui/` as conceptual sub-trees under `index.ts`:
44
-
45
- ```text
46
- index.ts ──wires──> agent-manager.ts
47
- ├── tools (Agent, get_subagent_result, steer_subagent)
48
- ├── ui/
49
- │ ├── agent-widget.ts
50
- │ └── conversation-viewer.ts
51
- └── ...
52
- ```
53
-
54
- This plan makes that conceptual structure physical.
55
-
56
- ### Relevant constraints from AGENTS.md
57
-
58
- - Keep modules focused and composable (one concern per file).
59
- - Prefer small, reversible changes.
60
- - Keep Pi SDK imports out of business-logic modules — tool modules are at the SDK boundary and may import SDK types; pure helpers must not.
61
- - Narrow interfaces per consumer — do not pass a shared dependency bag when a function only uses a subset.
62
-
63
- ### Helper usage trace
64
-
65
- Traced every helper function in `index.ts` to determine where it belongs:
66
-
67
- | Helper | Used by | Destination |
68
- | -------------------------- | --------------------------------------------------------- | --------------------- |
69
- | `textResult` | All three tools | `tools/helpers.ts` |
70
- | `formatLifetimeTokens` | All three tools + completion callback | `tools/helpers.ts` |
71
- | `getModelLabelFromConfig` | `buildTypeListText` (agent tool) + `getModelLabel` (menu) | `tools/helpers.ts` |
72
- | `createActivityTracker` | Agent tool execute (foreground + background) | `tools/agent-tool.ts` |
73
- | `buildDetails` | Agent tool execute | `tools/agent-tool.ts` |
74
- | `getStatusNote` | Agent tool execute | `tools/agent-tool.ts` |
75
- | `escapeXml` | `formatTaskNotification` | `notification.ts` |
76
- | `getStatusLabel` | `formatTaskNotification` | `notification.ts` |
77
- | `formatTaskNotification` | `emitIndividualNudge` | `notification.ts` |
78
- | `buildNotificationDetails` | `emitIndividualNudge` | `notification.ts` |
79
- | `buildEventData` | Completion callback | `notification.ts` |
80
-
81
- ## Design Overview
82
-
83
- ### Extraction strategy
84
-
85
- Each module exports a **factory function** that receives narrow dependencies and returns the tool definition, handler, or system object.
86
- This follows the established pattern in the codebase (`createSubagentsService` in `service-adapter.ts` already uses this approach).
87
- Factory functions keep state scoped to the instance (matching the current closure scope) and make dependencies explicit for testing.
88
-
89
- ### New module tree
90
-
91
- ```text
92
- src/
93
- ├── index.ts ← thin wire-up (~120-150 lines)
94
- ├── renderer.ts ← notification message renderer
95
- ├── notification.ts ← completion notification system
96
- ├── tools/
97
- │ ├── helpers.ts ← shared pure helpers (textResult, formatLifetimeTokens, etc.)
98
- │ ├── agent-tool.ts ← Agent tool definition + agent-specific helpers
99
- │ ├── get-result-tool.ts ← get_subagent_result tool definition
100
- │ └── steer-tool.ts ← steer_subagent tool definition
101
- ├── ui/
102
- │ ├── agent-menu.ts ← /agents menu + all sub-handlers (NEW)
103
- │ ├── agent-widget.ts (existing, unchanged)
104
- │ └── conversation-viewer.ts (existing, unchanged)
105
- └── ... (other existing modules unchanged)
106
- ```
107
-
108
- ### Dependency design
109
-
110
- Each factory receives only the methods it calls — not the full `AgentManager`, `AgentWidget`, or `ExtensionAPI`.
111
- Example narrow interface for the get-result tool:
112
-
113
- ```typescript
114
- interface GetResultDeps {
115
- getRecord: (id: string) => AgentRecord | undefined;
116
- cancelNudge: (key: string) => void;
117
- agentActivity: ReadonlyMap<string, AgentActivity>;
118
- }
119
- ```
120
-
121
- The Agent tool has more dependencies but they remain enumerable — each one maps to a specific method or value the execute callback calls.
122
-
123
- ### Notification system
124
-
125
- The nudge/notification helpers (`scheduleNudge`, `cancelNudge`, `emitIndividualNudge`, `sendIndividualNudge`) and their associated formatters (`formatTaskNotification`, `buildNotificationDetails`, `buildEventData`, `escapeXml`, `getStatusLabel`) form a cohesive unit.
126
- They move to `notification.ts` as a factory:
127
-
128
- ```typescript
129
- export function createNotificationSystem(deps: NotificationDeps): NotificationSystem;
130
-
131
- interface NotificationSystem {
132
- cancelNudge: (key: string) => void;
133
- sendCompletion: (record: AgentRecord) => void;
134
- cleanupCompleted: (id: string) => void;
135
- buildEventData: (record: AgentRecord) => object;
136
- dispose: () => void;
137
- }
138
- ```
139
-
140
- The completion callback in `index.ts` becomes a thin orchestrator (~15 lines) that calls `notifications.buildEventData()`, emits lifecycle events, persists the record, and delegates to `notifications.sendCompletion()`.
141
-
142
- ### What remains in index.ts
143
-
144
- After all extractions, `index.ts` retains only:
145
-
146
- 1. Imports and default export declaration.
147
- 2. `reloadCustomAgents` helper and initial load call.
148
- 3. `agentActivity` map creation.
149
- 4. `createNotificationSystem()` call.
150
- 5. `AgentManager` construction with completion/started/compacted callbacks (~20 lines).
151
- 6. Service creation and publishing.
152
- 7. Lifecycle hooks (`session_start`, `session_before_switch`, `session_shutdown`).
153
- 8. Widget creation and `tool_execution_start` handler.
154
- 9. `buildTypeListText` computation.
155
- 10. Settings application.
156
- 11. Three `pi.registerTool()` calls (importing factories).
157
- 12. `pi.registerCommand("agents", ...)` call.
158
-
159
- ## Module-Level Changes
160
-
161
- ### `src/tools/helpers.ts` (new)
162
-
163
- - `textResult(msg, details?)` — tool execute return value builder.
164
- - `formatLifetimeTokens(record)` — format lifetime token total.
165
- - `getModelLabelFromConfig(model)` — strip provider prefix and date suffix from model string.
166
-
167
- ### `src/renderer.ts` (new)
168
-
169
- - `registerNotificationRenderer(registerFn)` — accepts `pi.registerMessageRenderer` and registers the `"subagent-notification"` renderer.
170
- - Contains the full `renderOne` formatting logic currently inline in the `registerMessageRenderer` callback.
171
-
172
- ### `src/notification.ts` (new)
173
-
174
- - `createNotificationSystem(deps)` factory — returns `NotificationSystem`.
175
- - Contains: `scheduleNudge`, `cancelNudge`, `emitIndividualNudge`, `sendIndividualNudge`, `formatTaskNotification`, `buildNotificationDetails`, `buildEventData`, `escapeXml`, `getStatusLabel`.
176
- - Deps interface: narrow accessors for `sendMessage`, `agentActivity`, `widget.markFinished`, `widget.update`.
177
-
178
- ### `src/tools/agent-tool.ts` (new)
179
-
180
- - `createAgentTool(deps)` factory — returns the tool definition config object.
181
- - Contains: `renderCall`, `renderResult`, `execute`, plus agent-tool-specific helpers (`createActivityTracker`, `buildDetails`, `getStatusNote`).
182
- - Deps interface: narrow accessors for manager spawn/wait, widget lifecycle, activity map, event emission, output file wiring, type list text, and `reloadCustomAgents`.
183
-
184
- ### `src/tools/get-result-tool.ts` (new)
185
-
186
- - `createGetResultTool(deps)` factory — returns the tool definition config object.
187
- - Deps: `getRecord`, `cancelNudge`, `agentActivity`.
188
-
189
- ### `src/tools/steer-tool.ts` (new)
190
-
191
- - `createSteerTool(deps)` factory — returns the tool definition config object.
192
- - Deps: `getRecord`, `emitEvent`.
193
-
194
- ### `src/ui/agent-menu.ts` (new)
195
-
196
- - `createAgentsMenuHandler(deps)` factory — returns the `/agents` command handler.
197
- - Contains all menu functions: `showAgentsMenu`, `showAllAgentsList`, `showRunningAgents`, `viewAgentConversation`, `showAgentDetail`, `ejectAgent`, `disableAgent`, `enableAgent`, `showCreateWizard`, `showGenerateWizard`, `showManualWizard`, `showSettings`, `notifyApplied`, `findAgentFile`, `getModelLabel`.
198
- - Deps: manager list/get methods, `reloadCustomAgents`, `agentActivity`, settings snapshot/save functions, event emission, and `pi` (for generate wizard spawning).
199
-
200
- ### `src/index.ts` (modified — shrinks from ~1,619 to ~120–150 lines)
201
-
202
- - Remove all helper function definitions.
203
- - Remove all tool definitions.
204
- - Remove all menu handler functions.
205
- - Remove renderer registration logic.
206
- - Remove nudge/notification helpers.
207
- - Add imports from new modules.
208
- - Wire everything together: create deps, call factories, register tools/commands/lifecycle hooks.
209
-
210
- ## Test Impact Analysis
211
-
212
- ### New unit tests enabled by extraction
213
-
214
- The decomposition enables direct testing of code that was previously locked inside the closure:
215
-
216
- - `test/tools/helpers.test.ts` — `textResult`, `formatLifetimeTokens`, `getModelLabelFromConfig` with edge cases (zero tokens, empty model strings).
217
- - `test/renderer.test.ts` — notification renderer formatting for each status (completed, error, stopped, steered, aborted) in collapsed and expanded modes.
218
- - `test/notification.test.ts` — nudge scheduling/cancellation timing, `buildEventData` shape, `formatTaskNotification` XML output, `buildNotificationDetails` field mapping.
219
- - `test/tools/get-result-tool.test.ts` — execute paths: agent not found, wait-for-completion, result-consumed suppression, verbose conversation inclusion.
220
- - `test/tools/steer-tool.test.ts` — execute paths: agent not found, not running, session not ready (queued steer), successful steer.
221
- - `test/tools/agent-tool.test.ts` — execute paths: foreground completion, background launch, resume, unknown type fallback, model resolution error.
222
- - `test/ui/agent-menu.test.ts` — menu navigation, settings mutation, eject/disable/enable flows with mock UI context.
223
-
224
- ### Existing tests that become redundant
225
-
226
- None.
227
- There are no existing tests for `index.ts` — the extraction creates test coverage where none existed.
228
-
229
- ### Existing tests that stay as-is
230
-
231
- All 21 existing test files are unaffected.
232
- They test modules (`agent-manager`, `agent-runner`, `model-resolver`, `invocation-config`, `service-adapter`, etc.) that are not touched by this refactoring.
233
-
234
- ## TDD Order
235
-
236
- Each step is a self-contained extraction + test cycle.
237
- The existing test suite (362+ tests) runs after each step as a regression safety net.
238
-
239
- 1. **Extract `src/tools/helpers.ts` — shared pure helpers.**
240
- Move `textResult`, `formatLifetimeTokens`, `getModelLabelFromConfig` to new module.
241
- Update `index.ts` imports.
242
- Write `test/tools/helpers.test.ts` covering each function.
243
- Commit: `refactor: extract shared tool helpers to tools/helpers`
244
-
245
- 2. **Extract `src/renderer.ts` — notification message renderer.**
246
- Move renderer callback to `registerNotificationRenderer` export.
247
- Update `index.ts` to call the new function.
248
- Write `test/renderer.test.ts` covering status-dependent formatting.
249
- Commit: `refactor: extract notification renderer to renderer module`
250
-
251
- 3. **Extract `src/notification.ts` — completion notification system.**
252
- Move nudge system + formatters to `createNotificationSystem` factory.
253
- Update `index.ts` completion callback to use the notification system.
254
- Write `test/notification.test.ts` covering nudge timing and event data.
255
- Commit: `refactor: extract notification system to notification module`
256
-
257
- 4. **Extract `src/tools/get-result-tool.ts` — get_subagent_result tool.**
258
- Move tool definition to `createGetResultTool` factory with narrow deps.
259
- Update `index.ts` to call factory and register.
260
- Write `test/tools/get-result-tool.test.ts` covering execute paths.
261
- Commit: `refactor: extract get_subagent_result tool`
262
-
263
- 5. **Extract `src/tools/steer-tool.ts` — steer_subagent tool.**
264
- Move tool definition to `createSteerTool` factory with narrow deps.
265
- Update `index.ts`.
266
- Write `test/tools/steer-tool.test.ts` covering execute paths.
267
- Commit: `refactor: extract steer_subagent tool`
268
-
269
- 6. **Extract `src/tools/agent-tool.ts` — Agent tool.**
270
- Move tool definition + agent-specific helpers (`createActivityTracker`, `buildDetails`, `getStatusNote`) to `createAgentTool` factory.
271
- Update `index.ts`.
272
- Write `test/tools/agent-tool.test.ts` covering foreground, background, resume, and error paths.
273
- Commit: `refactor: extract Agent tool`
274
-
275
- 7. **Extract `src/ui/agent-menu.ts` — /agents menu handlers.**
276
- Move all menu functions to `createAgentsMenuHandler` factory.
277
- Update `index.ts` to register command with factory result.
278
- Write `test/ui/agent-menu.test.ts` covering key menu navigation flows.
279
- Commit: `refactor: extract /agents menu handlers`
280
-
281
- 8. **Final index.ts cleanup.**
282
- Remove any dead imports or vestigial code.
283
- Verify index.ts is ~120–150 lines of pure wire-up.
284
- Run `pnpm run check` (typecheck) and full test suite.
285
- Commit: `refactor: slim index.ts to wire-up entrypoint (#54)`
286
-
287
- ## Risks and Mitigations
288
-
289
- | Risk | Mitigation |
290
- | ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
291
- | Closure variable access breaks after extraction — helpers currently close over shared maps (`agentActivity`, `pendingNudges`) | Factory pattern replaces closure access with explicit dependency injection; each factory's deps interface enumerates exactly what it needs. |
292
- | Narrow dep interfaces diverge from the real objects — test mocks pass but runtime breaks | Run `pnpm run check` (typecheck) after each extraction step; the factory call sites in `index.ts` provide real objects whose types must satisfy the narrow interfaces. |
293
- | Large number of extraction steps creates merge-conflict risk with parallel PRs | Steps are ordered leaf-first so earlier commits don't touch files later steps modify. Each step is independently committable and revertable. |
294
- | Agent tool factory has many deps (~8–10) — risks becoming a dependency bag | Deps are individual functions and values, not a monolithic object. Each dep maps to exactly one method call in execute. If the count feels excessive during implementation, group by concern (spawn, widget, events) into 2–3 sub-interfaces. |
295
- | `buildTypeListText` is called at init time and captures agent types — extraction might change when it runs | `buildTypeListText` stays in `index.ts` as wire-up code (called once, result passed to agent tool factory). Timing is unchanged. |
296
-
297
- ## Open Questions
298
-
299
- - Should the notification module also own the lifecycle event emission (`subagents:completed`, `subagents:failed`, `subagents:started`, `subagents:compacted`), or should those stay in the completion callback in `index.ts`?
300
- Defer until step 3 — the answer depends on whether the completion callback shrinks enough to justify the move.
301
- - Should `buildTypeListText` move into `agent-tool.ts` or stay as wire-up in `index.ts`?
302
- Defer until step 6 — evaluate once the agent tool factory interface is concrete.