@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,373 +0,0 @@
1
- ---
2
- issue: 133
3
- issue_title: "Inject SDK boundary into `agent-runner`"
4
- ---
5
-
6
- # Inject SDK boundary into agent-runner
7
-
8
- ## Problem Statement
9
-
10
- `agent-runner.ts` directly imports five Pi SDK symbols (`createAgentSession`, `DefaultResourceLoader`, `getAgentDir`, `SessionManager`, `SettingsManager`) and two sibling modules (`detectEnv`, `deriveSubagentSessionDir`).
11
- It also imports four functions (`preloadSkills`, `buildMemoryBlock`, `buildReadOnlyMemoryBlock`, `buildAgentPrompt`) solely to construct the `AssemblerIO` object introduced in #132.
12
- This forces `agent-runner.test.ts` to use 7 `vi.mock()` calls, a `vi.hoisted()` block with 5+ mock factories, and a `beforeEach` that manually resets 6+ mocks.
13
- Tests verify internal call patterns ("defaultResourceLoaderCtor was called with `noContextFiles: true`") rather than behavioral outcomes, making any internal restructuring break multiple tests without changing observable behavior.
14
- The same 7-mock pattern is duplicated in `agent-runner-extension-tools.test.ts`.
15
-
16
- ## Goals
17
-
18
- - Define a `RunnerIO` interface bundling all SDK and IO collaborators used by `runAgent()`.
19
- - Add `io: RunnerIO` as a parameter to `runAgent()`.
20
- - Provide a `createAgentRunner(io: RunnerIO): AgentRunner` factory so the `AgentRunner` interface and `AgentManager` remain unchanged.
21
- - Replace direct SDK and sibling-module imports in `runAgent()` with calls through `io`.
22
- - Update the wiring in `index.ts` to construct a real `RunnerIO` and use `createAgentRunner()`.
23
- - Eliminate all 7 `vi.mock()` calls in `agent-runner.test.ts`.
24
- - Eliminate all 7 `vi.mock()` calls in `agent-runner-extension-tools.test.ts`.
25
- - Shift test assertions toward behavioral outcomes (turn limits enforced, tool filtering correct, response text collected).
26
-
27
- ## Non-Goals
28
-
29
- - Changing `resumeAgent` — it receives an already-created `AgentSession` and has no SDK/IO deps to inject.
30
- - Injecting `assembleSessionConfig` itself — the function is pure (after #132) and stays as a direct import; only its `AssemblerIO` collaborators move into `RunnerIO`.
31
- - Injecting `getMemoryToolNames` / `getReadOnlyMemoryToolNames` — these are pure utility functions with no IO; they remain as direct imports in `session-config.ts`.
32
- - Refactoring `filterActiveTools` or the turn-limit logic — out of scope.
33
- - Consolidating shared test fixtures (#131) — independent work.
34
-
35
- ## Background
36
-
37
- ### Prerequisite
38
-
39
- Issue #132 (inject IO into session-config) is closed.
40
- `assembleSessionConfig` now receives an `AssemblerIO` parameter and no longer imports IO functions directly.
41
- However, `agent-runner.ts` still imports those four functions to construct the `AssemblerIO` object, and the SDK factories remain as direct imports.
42
-
43
- ### Current vi.mock inventory in agent-runner.test.ts
44
-
45
- | # | Module | Symbols mocked | Why mocked |
46
- | --- | --------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------- |
47
- | 1 | `@earendil-works/pi-coding-agent` | `createAgentSession`, `DefaultResourceLoader`, `getAgentDir`, `SessionManager`, `SettingsManager` | SDK constructors and factories |
48
- | 2 | `../src/agent-types.js` | `getMemoryToolNames`, `getReadOnlyMemoryToolNames` | Pure functions used by session-config |
49
- | 3 | `../src/env.js` | `detectEnv` | Async IO (shell exec) |
50
- | 4 | `../src/prompts.js` | `buildAgentPrompt` | Relayed to AssemblerIO |
51
- | 5 | `../src/memory.js` | `buildMemoryBlock`, `buildReadOnlyMemoryBlock` | Relayed to AssemblerIO |
52
- | 6 | `../src/skill-loader.js` | `preloadSkills` | Relayed to AssemblerIO |
53
- | 7 | `../src/session-dir.js` | `deriveSubagentSessionDir` | Path derivation |
54
-
55
- `agent-runner-extension-tools.test.ts` has an identical set.
56
-
57
- ### Established DI patterns
58
-
59
- - `AgentManager` already receives `AgentRunner` via constructor injection — the same boundary this issue pushes down one layer.
60
- - `AssemblerIO` (#132) bundles four IO collaborators into a single injectable interface.
61
- - `AgentManagerLike` in `service-adapter.ts` defines a narrow interface for the concrete `AgentManager` class, avoiding coupling to the concrete type.
62
-
63
- ### Architecture reference
64
-
65
- Phase 8, Step H in `docs/architecture/architecture.md`.
66
-
67
- ### Constraints from AGENTS.md
68
-
69
- - Keep scope tight; prefer small, reversible changes.
70
- - Prefer explicit configuration over hidden behavior.
71
- - Business logic should be pure functions — keep IO at the edges.
72
- - Keep Pi SDK imports out of business-logic modules.
73
-
74
- ## Design Overview
75
-
76
- ### `RunnerIO` interface
77
-
78
- Defined in `agent-runner.ts` alongside the existing runner types.
79
- Bundles all IO dependencies that `runAgent()` uses:
80
-
81
- ```typescript
82
- /** Minimal resource-loader contract used by the runner. */
83
- export interface ResourceLoaderLike {
84
- reload(): Promise<void>;
85
- }
86
-
87
- /** Minimal session-manager contract used by the runner. */
88
- export interface SessionManagerLike {
89
- newSession(opts: { parentSession?: string }): void;
90
- getSessionFile(): string | undefined;
91
- }
92
-
93
- /** Options passed to RunnerIO.createResourceLoader. */
94
- export interface ResourceLoaderOptions {
95
- cwd: string;
96
- agentDir: string;
97
- noExtensions?: boolean;
98
- noSkills?: boolean;
99
- noPromptTemplates?: boolean;
100
- noThemes?: boolean;
101
- noContextFiles?: boolean;
102
- systemPromptOverride?: () => string;
103
- appendSystemPromptOverride?: () => unknown[];
104
- }
105
-
106
- /** Options passed to RunnerIO.createSession. */
107
- export interface CreateSessionOptions {
108
- cwd: string;
109
- agentDir: string;
110
- sessionManager: SessionManagerLike;
111
- settingsManager: unknown;
112
- modelRegistry: unknown;
113
- model?: unknown;
114
- tools: string[];
115
- resourceLoader: ResourceLoaderLike;
116
- thinkingLevel?: ThinkingLevel;
117
- }
118
-
119
- /**
120
- * IO boundary injected into runAgent().
121
- *
122
- * Decouples the runner from direct Pi SDK imports and sibling-module IO,
123
- * making it testable via plain stub objects without vi.mock().
124
- */
125
- export interface RunnerIO {
126
- detectEnv: (exec: ShellExec, cwd: string) => Promise<EnvInfo>;
127
- getAgentDir: () => string;
128
- createResourceLoader: (opts: ResourceLoaderOptions) => ResourceLoaderLike;
129
- deriveSessionDir: (
130
- parentSessionFile: string | undefined,
131
- effectiveCwd: string,
132
- ) => string;
133
- createSessionManager: (
134
- cwd: string,
135
- sessionDir: string,
136
- ) => SessionManagerLike;
137
- createSettingsManager: (cwd: string, agentDir: string) => unknown;
138
- createSession: (
139
- opts: CreateSessionOptions,
140
- ) => Promise<{ session: AgentSession }>;
141
- assemblerIO: AssemblerIO;
142
- }
143
- ```
144
-
145
- The interface has 8 fields (7 functions + 1 nested `AssemblerIO`).
146
- All 8 are consumed by `runAgent()` — no field is relayed without use.
147
-
148
- ### `createAgentRunner` factory
149
-
150
- ```typescript
151
- export function createAgentRunner(io: RunnerIO): AgentRunner {
152
- return {
153
- run: (snapshot, type, prompt, options) =>
154
- runAgent(snapshot, type, prompt, options, io),
155
- resume: resumeAgent,
156
- };
157
- }
158
- ```
159
-
160
- This keeps the `AgentRunner` interface unchanged.
161
- `AgentManager` continues to receive an `AgentRunner` — it never sees `RunnerIO`.
162
-
163
- ### Call site in `index.ts`
164
-
165
- ```typescript
166
- import {
167
- createAgentSession,
168
- DefaultResourceLoader,
169
- getAgentDir,
170
- SessionManager,
171
- SettingsManager,
172
- } from "@earendil-works/pi-coding-agent";
173
- import { detectEnv } from "./env.js";
174
- import { buildMemoryBlock, buildReadOnlyMemoryBlock } from "./memory.js";
175
- import { buildAgentPrompt } from "./prompts.js";
176
- import { deriveSubagentSessionDir } from "./session-dir.js";
177
- import { preloadSkills } from "./skill-loader.js";
178
-
179
- const runnerIO: RunnerIO = {
180
- detectEnv,
181
- getAgentDir,
182
- createResourceLoader: (opts) => new DefaultResourceLoader(opts),
183
- deriveSessionDir: deriveSubagentSessionDir,
184
- createSessionManager: (cwd, dir) => SessionManager.create(cwd, dir),
185
- createSettingsManager: (cwd, dir) => SettingsManager.create(cwd, dir),
186
- createSession: createAgentSession,
187
- assemblerIO: {
188
- preloadSkills,
189
- buildMemoryBlock,
190
- buildReadOnlyMemoryBlock,
191
- buildAgentPrompt,
192
- },
193
- };
194
-
195
- const manager = new AgentManager({
196
- runner: createAgentRunner(runnerIO),
197
- // ... rest unchanged
198
- });
199
- ```
200
-
201
- SDK and IO imports move from `agent-runner.ts` to `index.ts` — the extension entry point, which is the natural IO edge.
202
-
203
- ### Test-side stubs
204
-
205
- Tests create a plain `RunnerIO` object with `vi.fn()` stubs:
206
-
207
- ```typescript
208
- function createRunnerIO(): RunnerIO {
209
- return {
210
- detectEnv: vi.fn(async () => ({
211
- isGitRepo: false,
212
- branch: "",
213
- platform: "linux",
214
- })),
215
- getAgentDir: vi.fn(() => "/mock/agent-dir"),
216
- createResourceLoader: vi.fn(() => ({ reload: vi.fn() })),
217
- deriveSessionDir: vi.fn(() => "/mock/session-dir/tasks"),
218
- createSessionManager: vi.fn(() => ({
219
- newSession: vi.fn(),
220
- getSessionFile: vi.fn(() => "/sessions/child.jsonl"),
221
- })),
222
- createSettingsManager: vi.fn(() => ({ kind: "settings-manager" })),
223
- createSession: vi.fn(),
224
- assemblerIO: {
225
- preloadSkills: vi.fn(() => []),
226
- buildMemoryBlock: vi.fn(() => ""),
227
- buildReadOnlyMemoryBlock: vi.fn(() => ""),
228
- buildAgentPrompt: vi.fn(() => "system prompt"),
229
- },
230
- };
231
- }
232
- ```
233
-
234
- This replaces all 7 `vi.mock()` calls, the `vi.hoisted()` block, and most of the `beforeEach` resets.
235
- Each test calls `runAgent(snapshot, type, prompt, options, io)` directly with a stub `io`.
236
-
237
- ### Interaction verification — consumer call site (Tell-Don't-Ask check)
238
-
239
- ```typescript
240
- // In index.ts — the consumer constructs RunnerIO and hands it off:
241
- const runnerIO: RunnerIO = { detectEnv, getAgentDir, ... };
242
- const manager = new AgentManager({
243
- runner: createAgentRunner(runnerIO),
244
- });
245
- // AgentManager calls runner.run(...) — never reaches through to runnerIO.
246
- // Tell-Don't-Ask: ✓ Manager tells runner to run; runner uses its own IO.
247
- ```
248
-
249
- ### Pure functions stay as direct imports
250
-
251
- `assembleSessionConfig` (pure after #132), `filterActiveTools` (module-private), `normalizeMaxTurns` (pure exported), `collectResponseText`, `getLastAssistantText`, and `forwardAbortSignal` remain as direct code — they have no IO dependencies.
252
-
253
- `getMemoryToolNames` / `getReadOnlyMemoryToolNames` in `session-config.ts` remain as direct imports (pure, no IO).
254
- The `vi.mock("../src/agent-types.js", ...)` in both test files can be removed because the mock agent config has no `memory` field, so the memory branch in `assembleSessionConfig` is never entered and those functions are never called.
255
-
256
- ## Module-Level Changes
257
-
258
- ### Modified files
259
-
260
- 1. `src/agent-runner.ts`
261
- - Add `RunnerIO`, `ResourceLoaderLike`, `SessionManagerLike`, `ResourceLoaderOptions`, `CreateSessionOptions` interface exports.
262
- - Add `createAgentRunner(io: RunnerIO): AgentRunner` factory export.
263
- - Add `io: RunnerIO` parameter to `runAgent()`.
264
- - Replace `detectEnv(...)` with `io.detectEnv(...)`.
265
- - Replace `getAgentDir()` with `io.getAgentDir()`.
266
- - Replace `new DefaultResourceLoader(...)` with `io.createResourceLoader(...)`.
267
- - Replace `deriveSubagentSessionDir(...)` with `io.deriveSessionDir(...)`.
268
- - Replace `SessionManager.create(...)` with `io.createSessionManager(...)`.
269
- - Replace `SettingsManager.create(...)` with `io.createSettingsManager(...)`.
270
- - Replace `createAgentSession(...)` with `io.createSession(...)`.
271
- - Replace inline `AssemblerIO` construction with `io.assemblerIO`.
272
- - Remove imports: `createAgentSession`, `DefaultResourceLoader`, `getAgentDir`, `SessionManager`, `SettingsManager` from `@earendil-works/pi-coding-agent`; `detectEnv` from `./env.js`; `deriveSubagentSessionDir` from `./session-dir.js`; `preloadSkills` from `./skill-loader.js`; `buildMemoryBlock`, `buildReadOnlyMemoryBlock` from `./memory.js`; `buildAgentPrompt` from `./prompts.js`.
273
- - Keep imports: `type AgentSession`, `type AgentSessionEvent` from SDK (used in function signatures and event handling); `type AssemblerIO` from `./session-config.js`; `assembleSessionConfig` from `./session-config.js`; `extractText` from `./context.js`.
274
-
275
- 2. `src/index.ts`
276
- - Add imports: `detectEnv` from `./env.js`; `deriveSubagentSessionDir` from `./session-dir.js`; `preloadSkills` from `./skill-loader.js`; `buildMemoryBlock`, `buildReadOnlyMemoryBlock` from `./memory.js`; `buildAgentPrompt` from `./prompts.js`.
277
- - Add import: `createAgentRunner`, `type RunnerIO` from `./agent-runner.js`.
278
- - Remove import: `runAgent` from `./agent-runner.js` (replaced by factory).
279
- - Construct `runnerIO` object from real implementations.
280
- - Replace `runner: { run: runAgent, resume: resumeAgent }` with `runner: createAgentRunner(runnerIO)`.
281
-
282
- 3. `test/agent-runner.test.ts`
283
- - Remove all 7 `vi.mock()` calls and the `vi.hoisted()` block.
284
- - Add `createRunnerIO()` factory function returning a stub `RunnerIO`.
285
- - Pass `io` to all `runAgent()` calls.
286
- - Simplify `beforeEach` to reset `io.createSession` (the only mock that needs per-test setup).
287
- - Remove `mockAgentLookup.resolveAgentConfig` and `mockAgentLookup.getToolNamesForType` resets that are now unnecessary.
288
- - Update assertions that verify SDK constructor arguments (e.g., `defaultResourceLoaderCtor` calls) to verify `io.createResourceLoader` calls instead.
289
- - Remove the `agent-types.js` mock — pure functions run against controlled inputs.
290
-
291
- 4. `test/agent-runner-extension-tools.test.ts`
292
- - Same structural changes as `agent-runner.test.ts`: remove all 7 `vi.mock()` calls, inject `RunnerIO` stubs.
293
- - Keep the `createSessionWithExtensionToolRegistration` helper — it creates mock sessions for testing post-bind tool filtering, which is behavioral.
294
- - Update assertions to use `io.createResourceLoader` / `io.createSession` stubs.
295
-
296
- ### Unchanged files
297
-
298
- - `src/agent-manager.ts` — receives `AgentRunner` via injection; unaffected by `RunnerIO`.
299
- - `test/agent-manager.test.ts` — already injects a mock `AgentRunner`; unaffected.
300
- - `src/session-config.ts` — pure function, already receives `AssemblerIO`; unaffected.
301
- - `test/session-config.test.ts` — tests the pure assembler directly; unaffected.
302
- - `test/agent-runner-settings.test.ts` — tests `normalizeMaxTurns` (pure, no mocks); unaffected.
303
- - `test/print-mode.test.ts` — mocks `runAgent` itself at the module level; unaffected (it tests `index.ts` notification wiring, not the runner internals).
304
-
305
- ## Test Impact Analysis
306
-
307
- 1. The `RunnerIO` injection enables testing `runAgent` without any module mocking.
308
- Tests create plain stub objects satisfying `RunnerIO` — no `vi.mock()`, no `vi.hoisted()`, no module-level mock variable management.
309
- This was previously impossible because `runAgent` hard-imported SDK constructors.
310
-
311
- 2. Several existing tests that verify mock constructor arguments become redundant or shift to verifying `io.*` stub calls:
312
- - "passes effective cwd and agentDir to the loader and settings manager" → verifies `io.createResourceLoader` and `io.createSettingsManager` were called with expected args (simpler, no `defaultResourceLoaderCtor` indirection).
313
- - "suppresses AGENTS.md/CLAUDE.md/APPEND_SYSTEM.md for subagents" → verifies `io.createResourceLoader` was called with `noContextFiles: true` and an `appendSystemPromptOverride` that returns `[]`.
314
-
315
- 3. Tests for turn-limit enforcement, abort forwarding, and response-text collection stay as-is — they already test behavioral outcomes through the mock session, not through SDK mock call patterns.
316
-
317
- 4. The extension-tools tests (Patch 2) remain behavioral — they verify `setActiveToolsByName` calls before/after `bindExtensions`.
318
- The only change is how the session is created (via `io.createSession` stub instead of a module mock).
319
-
320
- 5. The `agent-types.js` mock can be removed from both test files because the mock agent configs have no `memory` field, so the code path through `getMemoryToolNames` / `getReadOnlyMemoryToolNames` is never reached.
321
-
322
- ## TDD Order
323
-
324
- 1. **Define `RunnerIO` and `createAgentRunner`; inject IO into `runAgent`.**
325
- Add the `RunnerIO`, `ResourceLoaderLike`, `SessionManagerLike`, `ResourceLoaderOptions`, and `CreateSessionOptions` interfaces to `agent-runner.ts`.
326
- Add `io: RunnerIO` parameter to `runAgent()`.
327
- Add `createAgentRunner(io)` factory export.
328
- Replace all direct SDK and IO imports with `io.*` calls inside `runAgent()`.
329
- Remove the now-unused direct imports.
330
- Update `index.ts` to construct `runnerIO` from real implementations and use `createAgentRunner(runnerIO)`.
331
- Run `pnpm run check` to verify types compile.
332
- Commit: `feat: inject SDK boundary into agent-runner via RunnerIO (#133)`
333
-
334
- 2. **Migrate `agent-runner.test.ts` to use injected `RunnerIO` stubs.**
335
- Add `createRunnerIO()` helper returning a fully-stubbed `RunnerIO`.
336
- Pass `io` to all `runAgent()` calls.
337
- Remove all 7 `vi.mock()` calls and the `vi.hoisted()` block.
338
- Simplify `beforeEach` to reset only `io.createSession`.
339
- Update assertions that referenced hoisted mocks (e.g., `defaultResourceLoaderCtor`, `sessionManagerCreate`, `settingsManagerCreate`, `getAgentDir`) to reference `io.*` stubs.
340
- Remove the `mockAgentLookup` mock resets that are now unnecessary.
341
- All existing tests pass with equivalent assertions.
342
- Commit: `test: replace vi.mock with RunnerIO stubs in agent-runner tests (#133)`
343
-
344
- 3. **Migrate `agent-runner-extension-tools.test.ts` to use injected `RunnerIO` stubs.**
345
- Same structural changes as step 2: remove all 7 `vi.mock()` calls, inject `RunnerIO` stubs.
346
- Keep `createSessionWithExtensionToolRegistration` helper (tests tool filtering behavior).
347
- Simplify `beforeEach` and update stub references.
348
- Commit: `test: replace vi.mock with RunnerIO stubs in extension-tools tests (#133)`
349
-
350
- 4. **Shift constructor-argument assertions to behavioral checks.**
351
- In `agent-runner.test.ts`, update tests that verify internal SDK call arguments:
352
- - Replace `expect(defaultResourceLoaderCtor).toHaveBeenCalledWith(expect.objectContaining({...}))` with `expect(io.createResourceLoader).toHaveBeenCalledWith(expect.objectContaining({...}))`.
353
- - Where the assertion only verified plumbing (e.g., "settings manager gets the right cwd"), simplify to a behavioral assertion or remove if covered by other tests.
354
- - Keep assertions that verify meaningful configuration decisions (e.g., `noContextFiles: true`, `appendSystemPromptOverride` returns `[]`).
355
- Run full test suite.
356
- Commit: `test: shift agent-runner assertions toward behavioral checks (#133)`
357
-
358
- ## Risks and Mitigations
359
-
360
- | Risk | Mitigation |
361
- | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
362
- | `RunnerIO` at 8 fields may seem wide | All 8 are consumed by the single consumer (`runAgent`). No field is relayed without use. The interface represents a genuine IO boundary — further narrowing would require splitting `runAgent` itself (out of scope). |
363
- | Removing the `agent-types.js` mock could cause failures if a test unexpectedly enters the memory branch | The mock agent config has no `memory` field (`undefined`), so the memory branch is guarded by `if (agentConfig.memory)`. Verified by reading the test's `resolveAgentConfig` mock return value. |
364
- | `index.ts` accumulates many new imports | The imports move from `agent-runner.ts` to `index.ts` — the extension entry point is the natural IO edge. The total import count across the two files is unchanged. |
365
- | `createAgentRunner` factory adds indirection | The factory is a one-liner that captures `io` in a closure. The `AgentRunner` interface and `AgentManager` are completely unchanged. No new abstraction layer — just a construction-time binding. |
366
- | Steps 2–3 touch many call sites in two test files (add `, io` argument) | All changes are mechanical. Each `runAgent(snapshot, type, prompt, {...})` becomes `runAgent(snapshot, type, prompt, {...}, io)`. A single find-and-replace handles it. |
367
- | `print-mode.test.ts` mocks `runAgent` at the module level — does the new `io` parameter break it? | `print-mode.test.ts` mocks the entire `runAgent` export with `vi.mock("../src/agent-runner.js", ...)`. The mock replaces the function entirely, so the new parameter has no effect on that test. |
368
-
369
- ## Open Questions
370
-
371
- - Should `RunnerIO` live in `agent-runner.ts` or be extracted to a separate types file?
372
- The interface is tightly coupled to `runAgent()` — co-location follows the `AssemblerIO` precedent in `session-config.ts`.
373
- Extract only if a second consumer appears.