@gotgenes/pi-subagents 18.0.1 → 18.0.2

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 (260) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/docs/architecture/architecture.md +157 -204
  3. package/docs/architecture/history/phase-19-implement-ui-decisions.md +282 -0
  4. package/package.json +5 -6
  5. package/src/lifecycle/subagent.ts +5 -9
  6. package/src/observation/notification.ts +23 -10
  7. package/src/observation/subagent-events-observer.ts +1 -3
  8. package/src/tools/get-result-report.ts +60 -0
  9. package/src/tools/get-result-tool.ts +25 -40
  10. package/src/types.ts +1 -1
  11. package/src/ui/session-navigator.ts +0 -2
  12. package/.prettierignore +0 -5
  13. package/AGENTS.md +0 -7
  14. package/docs/plans/0048-implement-subagents-api.md +0 -304
  15. package/docs/plans/0049-remove-group-join-output-file-rpc.md +0 -180
  16. package/docs/plans/0051-update-adr-0001-hard-fork.md +0 -77
  17. package/docs/plans/0052-remove-scheduled-subagents.md +0 -133
  18. package/docs/plans/0053-extract-model-resolution-from-execute.md +0 -181
  19. package/docs/plans/0054-decompose-index-into-modules.md +0 -302
  20. package/docs/plans/0057-structured-debug-logging.md +0 -154
  21. package/docs/plans/0061-session-format-transcript.md +0 -284
  22. package/docs/plans/0066-replace-as-any-with-sdk-types.md +0 -215
  23. package/docs/plans/0069-create-subagent-runtime.md +0 -345
  24. package/docs/plans/0070-extract-event-handlers.md +0 -306
  25. package/docs/plans/0071-extract-session-config-assembler.md +0 -362
  26. package/docs/plans/0072-inject-agent-manager-collaborators.md +0 -329
  27. package/docs/plans/0076-inject-cwd-into-agent-manager.md +0 -102
  28. package/docs/plans/0077-inject-project-agents-dir.md +0 -115
  29. package/docs/plans/0080-consolidate-agent-config-lookup.md +0 -247
  30. package/docs/plans/0084-extract-git-worktree-manager.md +0 -142
  31. package/docs/plans/0087-evolve-subagent-runtime-methods.md +0 -240
  32. package/docs/plans/0098-extract-agent-record-state-machine.md +0 -435
  33. package/docs/plans/0099-replace-ctx-with-parent-snapshot.md +0 -488
  34. package/docs/plans/0100-replace-callback-threading-with-session-subscription.md +0 -454
  35. package/docs/plans/0102-consolidate-test-record-factory.md +0 -176
  36. package/docs/plans/0108-extract-agent-type-registry.md +0 -322
  37. package/docs/plans/0109-extract-settings-manager.md +0 -276
  38. package/docs/plans/0110-agent-activity-tracker.md +0 -297
  39. package/docs/plans/0111-split-agent-record-lifecycle.md +0 -582
  40. package/docs/plans/0112-replace-agent-manager-callbacks.md +0 -241
  41. package/docs/plans/0113-disambiguate-spawn-options.md +0 -155
  42. package/docs/plans/0114-narrow-agent-tool-menu-deps.md +0 -279
  43. package/docs/plans/0115-decompose-agent-tool.md +0 -337
  44. package/docs/plans/0116-type-housekeeping.md +0 -351
  45. package/docs/plans/0118-settings-manager-apply-methods.md +0 -271
  46. package/docs/plans/0123-remove-vi-fn-cast-smell.md +0 -179
  47. package/docs/plans/0131-consolidate-shared-test-fixtures.md +0 -207
  48. package/docs/plans/0132-inject-io-into-session-config.md +0 -219
  49. package/docs/plans/0133-inject-sdk-boundary-into-agent-runner.md +0 -373
  50. package/docs/plans/0134-reduce-as-any-casts.md +0 -366
  51. package/docs/plans/0135-extract-display-helpers.md +0 -182
  52. package/docs/plans/0136-decompose-agent-menu.md +0 -300
  53. package/docs/plans/0144-consolidate-observation-model.md +0 -263
  54. package/docs/plans/0145-decompose-execute-push-ctx-to-boundary.md +0 -290
  55. package/docs/plans/0146-narrow-ui-context.md +0 -319
  56. package/docs/plans/0147-inject-wrap-text-into-conversation-viewer.md +0 -166
  57. package/docs/plans/0148-split-agent-widget-rendering.md +0 -255
  58. package/docs/plans/0152-add-prompt-snippet.md +0 -91
  59. package/docs/plans/0164-reorganize-into-domain-directories.md +0 -409
  60. package/docs/plans/0165-decompose-resolved-spawn-config.md +0 -157
  61. package/docs/plans/0166-extract-parent-session-info.md +0 -231
  62. package/docs/plans/0167-narrow-runner-io.md +0 -150
  63. package/docs/plans/0168-extract-tool-filter-config.md +0 -173
  64. package/docs/plans/0169-extract-run-context-from-run-options.md +0 -194
  65. package/docs/plans/0170-reduce-build-content-lines-complexity.md +0 -225
  66. package/docs/plans/0171-reduce-render-result-complexity.md +0 -200
  67. package/docs/plans/0172-extract-turn-formatting.md +0 -206
  68. package/docs/plans/0180-reorder-append-prompt-for-kv-cache.md +0 -100
  69. package/docs/plans/0185-remove-persistent-agent-memory.md +0 -161
  70. package/docs/plans/0188-replace-any-casts-with-sdk-types.md +0 -162
  71. package/docs/plans/0192-define-session-context-interface.md +0 -107
  72. package/docs/plans/0193-runtime-owns-context-queries.md +0 -245
  73. package/docs/plans/0194-align-tool-interfaces-for-structural-typing.md +0 -139
  74. package/docs/plans/0195-convert-tool-factories-to-classes.md +0 -264
  75. package/docs/plans/0196-convert-runner-menu-to-classes.md +0 -268
  76. package/docs/plans/0205-decompose-render-widget-lines.md +0 -140
  77. package/docs/plans/0206-decompose-show-agent-detail.md +0 -211
  78. package/docs/plans/0207-decompose-agent-widget-update.md +0 -242
  79. package/docs/plans/0208-extract-shared-test-fixtures.md +0 -298
  80. package/docs/plans/0214-convert-remaining-closure-factories-to-classes.md +0 -261
  81. package/docs/plans/0215-decompose-build-parent-context.md +0 -166
  82. package/docs/plans/0216-decompose-start-agent.md +0 -255
  83. package/docs/plans/0217-extract-overwrite-guard.md +0 -176
  84. package/docs/plans/0218-push-sdk-boundary-in-settings.md +0 -172
  85. package/docs/plans/0219-reduce-test-duplication-top-3-clone-families.md +0 -162
  86. package/docs/plans/0227-evolve-agent-record-into-agent.md +0 -322
  87. package/docs/plans/0228-async-start-agent-dissolve-run-handle.md +0 -288
  88. package/docs/plans/0229-agent-born-complete.md +0 -564
  89. package/docs/plans/0230-extract-concurrency-queue.md +0 -265
  90. package/docs/plans/0231-push-exec-registry-to-runner.md +0 -245
  91. package/docs/plans/0232-agent-resume-internal-observer-lifecycle.md +0 -180
  92. package/docs/plans/0237-remove-disallowed-tools.md +0 -180
  93. package/docs/plans/0238-remove-extensions-filtering.md +0 -191
  94. package/docs/plans/0239-collapse-filter-active-tools.md +0 -217
  95. package/docs/plans/0242-rename-agent-tool-to-subagent.md +0 -165
  96. package/docs/plans/0256-extract-worktree-isolation.md +0 -256
  97. package/docs/plans/0257-extract-child-session-factory.md +0 -285
  98. package/docs/plans/0262-add-workspace-provider-seam.md +0 -264
  99. package/docs/plans/0264-remove-extension-lifecycle-control.md +0 -277
  100. package/docs/plans/0265-born-complete-subagent-session.md +0 -333
  101. package/docs/plans/0270-type-consumable-public-surface.md +0 -204
  102. package/docs/plans/0272-export-workspace-collaborator-types.md +0 -147
  103. package/docs/plans/0277-encapsulate-agent-session.md +0 -304
  104. package/docs/plans/0280-rename-agent-to-subagent.md +0 -197
  105. package/docs/plans/0360-custom-agents-default-append.md +0 -132
  106. package/docs/plans/0373-extract-subagent-state.md +0 -250
  107. package/docs/plans/0374-encapsulate-subagent-start-notification.md +0 -268
  108. package/docs/plans/0375-extract-run-listener-workspace-bracket.md +0 -300
  109. package/docs/plans/0376-extract-manager-observer.md +0 -232
  110. package/docs/plans/0377-split-widget-delegation-from-runtime.md +0 -254
  111. package/docs/plans/0378-consolidate-lifecycle-test-fixtures.md +0 -243
  112. package/docs/plans/0379-consolidate-ui-tools-test-fixtures.md +0 -335
  113. package/docs/plans/0380-extract-layered-settings-loader.md +0 -223
  114. package/docs/plans/0381-replace-concurrency-queue-with-limiter.md +0 -267
  115. package/docs/plans/0400-include-parent-prompt-in-replace-mode.md +0 -199
  116. package/docs/plans/0403-abort-subagents-on-interrupt.md +0 -180
  117. package/docs/plans/0412-unify-session-mock-builders.md +0 -146
  118. package/docs/plans/0420-fold-run-metrics-live-activity-onto-record.md +0 -228
  119. package/docs/plans/0421-migrate-activity-readers-to-record-getters.md +0 -309
  120. package/docs/plans/0422-delete-activity-tracker-ui-observer.md +0 -204
  121. package/docs/plans/0423-widget-self-drive-from-lifecycle.md +0 -264
  122. package/docs/plans/0424-drop-widget-dep-from-subagent-tool.md +0 -166
  123. package/docs/plans/0425-reconcile-subagent-events-contract.md +0 -144
  124. package/docs/plans/0426-consolidate-residual-test-clone-families.md +0 -235
  125. package/docs/plans/0427-reconsider-ui-direction.md +0 -212
  126. package/docs/plans/0441-remove-agent-definition-management-subtree.md +0 -180
  127. package/docs/plans/0442-dissolve-agents-conversation-viewer.md +0 -195
  128. package/docs/plans/0443-consolidate-remaining-test-clone-families.md +0 -268
  129. package/docs/plans/0444-shrink-widget-to-background-agents.md +0 -156
  130. package/docs/plans/0445-native-session-navigation.md +0 -365
  131. package/docs/plans/0446-spike-session-navigation-entry-criteria.md +0 -171
  132. package/docs/plans/0447-extract-subagents-settings-command.md +0 -220
  133. package/docs/plans/0448-block-disabled-agent-spawn.md +0 -207
  134. package/docs/plans/0462-navigation-renderer-tui-components.md +0 -338
  135. package/docs/plans/0463-file-snapshot-source-evicted-agents.md +0 -306
  136. package/docs/plans/0470-refresh-readme-command-surface.md +0 -159
  137. package/docs/retro/0048-implement-subagents-api.md +0 -44
  138. package/docs/retro/0049-remove-group-join-output-file-rpc.md +0 -49
  139. package/docs/retro/0051-update-adr-0001-hard-fork.md +0 -39
  140. package/docs/retro/0053-extract-model-resolution-from-execute.md +0 -40
  141. package/docs/retro/0054-decompose-index-into-modules.md +0 -53
  142. package/docs/retro/0057-structured-debug-logging.md +0 -77
  143. package/docs/retro/0061-session-format-transcript.md +0 -41
  144. package/docs/retro/0066-replace-as-any-with-sdk-types.md +0 -44
  145. package/docs/retro/0069-create-subagent-runtime.md +0 -43
  146. package/docs/retro/0070-extract-event-handlers.md +0 -49
  147. package/docs/retro/0071-extract-session-config-assembler.md +0 -60
  148. package/docs/retro/0072-inject-agent-manager-collaborators.md +0 -46
  149. package/docs/retro/0076-inject-cwd-into-agent-manager.md +0 -35
  150. package/docs/retro/0077-inject-project-agents-dir.md +0 -33
  151. package/docs/retro/0080-consolidate-agent-config-lookup.md +0 -35
  152. package/docs/retro/0084-extract-git-worktree-manager.md +0 -37
  153. package/docs/retro/0087-evolve-subagent-runtime-methods.md +0 -42
  154. package/docs/retro/0098-extract-agent-record-state-machine.md +0 -46
  155. package/docs/retro/0099-replace-ctx-with-parent-snapshot.md +0 -37
  156. package/docs/retro/0100-replace-callback-threading-with-session-subscription.md +0 -36
  157. package/docs/retro/0102-consolidate-test-record-factory.md +0 -30
  158. package/docs/retro/0108-extract-agent-type-registry.md +0 -41
  159. package/docs/retro/0109-extract-settings-manager.md +0 -55
  160. package/docs/retro/0110-agent-activity-tracker.md +0 -44
  161. package/docs/retro/0111-split-agent-record-lifecycle.md +0 -61
  162. package/docs/retro/0112-replace-agent-manager-callbacks.md +0 -35
  163. package/docs/retro/0113-disambiguate-spawn-options.md +0 -29
  164. package/docs/retro/0114-narrow-agent-tool-menu-deps.md +0 -38
  165. package/docs/retro/0115-decompose-agent-tool.md +0 -51
  166. package/docs/retro/0116-type-housekeeping.md +0 -42
  167. package/docs/retro/0118-settings-manager-apply-methods.md +0 -40
  168. package/docs/retro/0123-remove-vi-fn-cast-smell.md +0 -49
  169. package/docs/retro/0131-consolidate-shared-test-fixtures.md +0 -46
  170. package/docs/retro/0132-inject-io-into-session-config.md +0 -33
  171. package/docs/retro/0133-inject-sdk-boundary-into-agent-runner.md +0 -45
  172. package/docs/retro/0134-reduce-as-any-casts.md +0 -56
  173. package/docs/retro/0135-extract-display-helpers.md +0 -38
  174. package/docs/retro/0136-decompose-agent-menu.md +0 -43
  175. package/docs/retro/0144-consolidate-observation-model.md +0 -39
  176. package/docs/retro/0145-decompose-execute-push-ctx-to-boundary.md +0 -56
  177. package/docs/retro/0146-narrow-ui-context.md +0 -70
  178. package/docs/retro/0147-inject-wrap-text-into-conversation-viewer.md +0 -90
  179. package/docs/retro/0148-split-agent-widget-rendering.md +0 -39
  180. package/docs/retro/0152-add-prompt-snippet.md +0 -34
  181. package/docs/retro/0164-reorganize-into-domain-directories.md +0 -82
  182. package/docs/retro/0165-decompose-resolved-spawn-config.md +0 -78
  183. package/docs/retro/0166-extract-parent-session-info.md +0 -66
  184. package/docs/retro/0167-narrow-runner-io.md +0 -63
  185. package/docs/retro/0168-extract-tool-filter-config.md +0 -76
  186. package/docs/retro/0169-extract-run-context-from-run-options.md +0 -68
  187. package/docs/retro/0170-reduce-build-content-lines-complexity.md +0 -72
  188. package/docs/retro/0171-reduce-render-result-complexity.md +0 -77
  189. package/docs/retro/0172-extract-turn-formatting.md +0 -80
  190. package/docs/retro/0180-reorder-append-prompt-for-kv-cache.md +0 -62
  191. package/docs/retro/0185-remove-persistent-agent-memory.md +0 -73
  192. package/docs/retro/0188-replace-any-casts-with-sdk-types.md +0 -69
  193. package/docs/retro/0192-define-session-context-interface.md +0 -59
  194. package/docs/retro/0193-runtime-owns-context-queries.md +0 -75
  195. package/docs/retro/0194-align-tool-interfaces-for-structural-typing.md +0 -62
  196. package/docs/retro/0195-convert-tool-factories-to-classes.md +0 -84
  197. package/docs/retro/0196-convert-runner-menu-to-classes.md +0 -73
  198. package/docs/retro/0205-decompose-render-widget-lines.md +0 -64
  199. package/docs/retro/0206-decompose-show-agent-detail.md +0 -67
  200. package/docs/retro/0207-decompose-agent-widget-update.md +0 -92
  201. package/docs/retro/0208-extract-shared-test-fixtures.md +0 -102
  202. package/docs/retro/0214-convert-remaining-closure-factories-to-classes.md +0 -66
  203. package/docs/retro/0215-decompose-build-parent-context.md +0 -61
  204. package/docs/retro/0216-decompose-start-agent.md +0 -80
  205. package/docs/retro/0217-extract-overwrite-guard.md +0 -63
  206. package/docs/retro/0218-push-sdk-boundary-in-settings.md +0 -72
  207. package/docs/retro/0219-reduce-test-duplication-top-3-clone-families.md +0 -64
  208. package/docs/retro/0227-evolve-agent-record-into-agent.md +0 -80
  209. package/docs/retro/0228-async-start-agent-dissolve-run-handle.md +0 -80
  210. package/docs/retro/0229-agent-born-complete.md +0 -89
  211. package/docs/retro/0230-extract-concurrency-queue.md +0 -38
  212. package/docs/retro/0231-push-exec-registry-to-runner.md +0 -71
  213. package/docs/retro/0232-agent-resume-internal-observer-lifecycle.md +0 -109
  214. package/docs/retro/0237-remove-disallowed-tools.md +0 -78
  215. package/docs/retro/0238-remove-extensions-filtering.md +0 -72
  216. package/docs/retro/0239-collapse-filter-active-tools.md +0 -70
  217. package/docs/retro/0242-rename-agent-tool-to-subagent.md +0 -82
  218. package/docs/retro/0256-extract-worktree-isolation.md +0 -89
  219. package/docs/retro/0257-extract-child-session-factory.md +0 -33
  220. package/docs/retro/0262-add-workspace-provider-seam.md +0 -89
  221. package/docs/retro/0264-remove-extension-lifecycle-control.md +0 -91
  222. package/docs/retro/0265-born-complete-subagent-session.md +0 -97
  223. package/docs/retro/0270-type-consumable-public-surface.md +0 -108
  224. package/docs/retro/0272-export-workspace-collaborator-types.md +0 -38
  225. package/docs/retro/0277-encapsulate-agent-session.md +0 -80
  226. package/docs/retro/0280-rename-agent-to-subagent.md +0 -96
  227. package/docs/retro/0360-custom-agents-default-append.md +0 -81
  228. package/docs/retro/0373-extract-subagent-state.md +0 -94
  229. package/docs/retro/0374-encapsulate-subagent-start-notification.md +0 -171
  230. package/docs/retro/0375-extract-run-listener-workspace-bracket.md +0 -104
  231. package/docs/retro/0376-extract-manager-observer.md +0 -81
  232. package/docs/retro/0377-split-widget-delegation-from-runtime.md +0 -105
  233. package/docs/retro/0378-consolidate-lifecycle-test-fixtures.md +0 -100
  234. package/docs/retro/0379-consolidate-ui-tools-test-fixtures.md +0 -52
  235. package/docs/retro/0380-extract-layered-settings-loader.md +0 -97
  236. package/docs/retro/0381-replace-concurrency-queue-with-limiter.md +0 -95
  237. package/docs/retro/0400-include-parent-prompt-in-replace-mode.md +0 -84
  238. package/docs/retro/0403-abort-subagents-on-interrupt.md +0 -90
  239. package/docs/retro/0412-unify-session-mock-builders.md +0 -80
  240. package/docs/retro/0420-fold-run-metrics-live-activity-onto-record.md +0 -90
  241. package/docs/retro/0421-migrate-activity-readers-to-record-getters.md +0 -105
  242. package/docs/retro/0422-delete-activity-tracker-ui-observer.md +0 -97
  243. package/docs/retro/0423-widget-self-drive-from-lifecycle.md +0 -112
  244. package/docs/retro/0424-drop-widget-dep-from-subagent-tool.md +0 -89
  245. package/docs/retro/0425-reconcile-subagent-events-contract.md +0 -101
  246. package/docs/retro/0426-consolidate-residual-test-clone-families.md +0 -100
  247. package/docs/retro/0427-reconsider-ui-direction.md +0 -102
  248. package/docs/retro/0441-remove-agent-definition-management-subtree.md +0 -97
  249. package/docs/retro/0442-dissolve-agents-conversation-viewer.md +0 -108
  250. package/docs/retro/0443-consolidate-remaining-test-clone-families.md +0 -28
  251. package/docs/retro/0444-shrink-widget-to-background-agents.md +0 -81
  252. package/docs/retro/0445-native-session-navigation.md +0 -122
  253. package/docs/retro/0446-spike-session-navigation-entry-criteria.md +0 -99
  254. package/docs/retro/0447-extract-subagents-settings-command.md +0 -91
  255. package/docs/retro/0448-block-disabled-agent-spawn.md +0 -75
  256. package/docs/retro/0462-navigation-renderer-tui-components.md +0 -105
  257. package/docs/retro/0463-file-snapshot-source-evicted-agents.md +0 -103
  258. package/docs/retro/0470-refresh-readme-command-surface.md +0 -40
  259. package/src/observation/notification-state.ts +0 -27
  260. package/vitest.config.ts +0 -14
@@ -1,366 +0,0 @@
1
- ---
2
- issue: 134
3
- issue_title: "Reduce `as any` casts in test suite"
4
- ---
5
-
6
- # Reduce as-any casts in test suite
7
-
8
- ## Problem Statement
9
-
10
- The test suite contains 93 `as any` casts (plus 2 `as any[]`).
11
- These casts silence the type checker, hiding real errors — if a production interface adds a required field, tests silently pass with incomplete mocks instead of failing at compile time.
12
- The heaviest offenders are `renderer.test.ts` (29), `runtime.test.ts` (10), `agent-menu.test.ts` (8), and `helpers.test.ts` (7).
13
- The production source has 8 `as any` casts — 2 SDK bridge casts in `index.ts` and 6 message-shape casts in `conversation-viewer.ts` and `agent-runner.ts`.
14
-
15
- ## Goals
16
-
17
- - Target near-zero `as any` casts across both source and test code.
18
- - Widen `CreateSessionOptions` and `ResourceLoaderOptions` to use SDK types, eliminating the SDK bridge casts in `index.ts`.
19
- - Define local message-content types and type guards in `conversation-viewer.ts` and `agent-runner.ts`, eliminating polymorphic duck-typing casts.
20
- - Define narrow production interfaces (`MenuCtx`, `WidgetLike`) where SDK types are too wide for test construction.
21
- - Define typed test factories where partial mocks currently require casting.
22
- - Preserve existing test coverage — no behavior changes.
23
-
24
- ## Non-Goals
25
-
26
- - Changing production behavior or public API shapes.
27
- - Reaching literally zero — 1–3 casts may remain for private-field test access (`(manager as any).cleanupInterval`) where the alternative (exposing internals) is worse than the cast.
28
-
29
- ## Background
30
-
31
- ### Prerequisites
32
-
33
- Issues #132 and #133 (IO injection) are both closed.
34
- These eliminated the `vi.mock()`-heavy test patterns and introduced narrow injectable interfaces (`AssemblerIO`, `RunnerIO`), which already removed some `as any` casts from `agent-runner.test.ts` and `session-config.test.ts`.
35
-
36
- ### Current as-any inventory by pattern
37
-
38
- | Pattern | Count | Primary files |
39
- | ------------------------------------------------ | ----- | ------------------------------------------------------------------------------------------------------------------- |
40
- | Renderer — theme, message, result access | 29 | `renderer.test.ts` |
41
- | Context — `ctx as any` for handler/menu | 14 | `agent-menu.test.ts`, `agent-manager.test.ts`, `print-mode.test.ts`, `parent-snapshot.test.ts`, `make-deps.test.ts` |
42
- | Session — `{ session: {} as any }` | 10 | tool tests, `service-adapter.test.ts`, `print-mode.test.ts`, `agent-manager.test.ts` |
43
- | Runtime/widget — `fakeWidget as any` | 9 | `runtime.test.ts` |
44
- | Conversation viewer — message shapes | 8 | `conversation-viewer.test.ts`, `src/conversation-viewer.ts` |
45
- | Helpers — registry, activity, details | 7 | `helpers.test.ts` |
46
- | RunOptions — `} as any, io)` | 3 | `agent-runner.test.ts` |
47
- | Tool execute — `{} as any` for ctx | 5 | `steer-tool.test.ts`, `get-result-tool.test.ts`, `make-deps.test.ts` |
48
- | SDK bridge — `opts as any` in index.ts | 2 | `src/index.ts` |
49
- | Other — `messages: [] as any[]`, internal access | 6 | `agent-runner*.test.ts`, `usage.test.ts`, `agent-manager.test.ts` |
50
-
51
- ### Constraints from AGENTS.md
52
-
53
- - Avoid `any` unless absolutely necessary.
54
- - Prefer explicit configuration over hidden behavior.
55
- - Keep scope tight; prefer small, reversible changes.
56
-
57
- ## Design Overview
58
-
59
- ### Production changes that make the test changes easy
60
-
61
- Three targeted source-code changes remove the structural blockers that force casts elsewhere.
62
-
63
- #### 1. SDK-typed option interfaces (eliminates 2 source casts)
64
-
65
- `CreateSessionOptions` and `ResourceLoaderOptions` currently use `unknown` for opaque fields (`settingsManager`, `modelRegistry`, `model`).
66
- Tests never construct these option objects — they mock `io.createSession` and `io.createResourceLoader` at the function level.
67
- The `unknown` fields don't buy testability; the function-level mock does.
68
-
69
- The SDK exports `CreateAgentSessionOptions` with all fields optional, using `ModelRegistry`, `Model<any>`, `ResourceLoader`, `SessionManager`, `SettingsManager`.
70
- Widening `CreateSessionOptions` to use these SDK types makes the `as any` cast in `index.ts` unnecessary while preserving full test mockability.
71
-
72
- ```typescript
73
- // Before (agent-runner.ts)
74
- export interface CreateSessionOptions {
75
- settingsManager: unknown;
76
- modelRegistry: unknown;
77
- model?: unknown;
78
- // ...
79
- }
80
-
81
- // After — use SDK types (type-only imports)
82
- import type { Model } from "@earendil-works/pi-ai";
83
- import type {
84
- ModelRegistry,
85
- ResourceLoader,
86
- SessionManager,
87
- SettingsManager,
88
- } from "@earendil-works/pi-coding-agent";
89
-
90
- export interface CreateSessionOptions {
91
- settingsManager: SettingsManager;
92
- modelRegistry: ModelRegistry;
93
- model?: Model<any>;
94
- resourceLoader: ResourceLoader;
95
- sessionManager: SessionManager;
96
- // ...
97
- }
98
- ```
99
-
100
- The `RunnerIO.createSettingsManager` return type also changes from `unknown` to `SettingsManager`.
101
-
102
- For `ResourceLoaderOptions`, the options are all primitives and callbacks — the SDK's `DefaultResourceLoader` constructor accepts them structurally.
103
- The fix is to ensure the option interface matches the constructor's parameter type so `new DefaultResourceLoader(opts)` works without `as any`.
104
-
105
- #### 2. Local message-content types + type guards (eliminates 6 source casts)
106
-
107
- `conversation-viewer.ts` and `agent-runner.ts` both do:
108
-
109
- ```typescript
110
- (c as any).name ?? (c as any).toolName ?? "unknown"
111
- (msg as any).role === "bashExecution"
112
- const bash = msg as any;
113
- ```
114
-
115
- Fix: define local discriminated-union types for the content items and message roles the code actually handles, plus type guards:
116
-
117
- ```typescript
118
- /** Tool-call content item — SDK doesn't export a narrow type for this variant. */
119
- interface ToolCallContent {
120
- type: "toolCall";
121
- name?: string;
122
- toolName?: string;
123
- }
124
-
125
- function getToolCallName(c: { type: string }): string | undefined {
126
- if (c.type !== "toolCall") return undefined;
127
- const tc = c as ToolCallContent;
128
- return tc.name ?? tc.toolName;
129
- }
130
-
131
- /** Bash execution message — not in the standard role union. */
132
- interface BashExecutionMessage {
133
- role: "bashExecution";
134
- command: string;
135
- output?: string;
136
- }
137
-
138
- function isBashExecution(msg: { role: string }): msg is BashExecutionMessage {
139
- return msg.role === "bashExecution";
140
- }
141
- ```
142
-
143
- These are small, file-local types that document the shapes the code already handles at runtime.
144
- They make the duck-typing explicit and compile-time checked.
145
-
146
- #### 3. Narrow production interfaces (`MenuCtx`, `WidgetLike`)
147
-
148
- Already described in the test-side patterns below.
149
- These are production-code changes that make the test-side casts disappear.
150
-
151
- ### Test-side patterns
152
-
153
- #### Pattern A: renderer.test.ts (29 casts → 0)
154
-
155
- The renderer already defines narrow interfaces (`RendererMessage`, `RendererTheme`, `RenderOptions`).
156
- The test casts because it doesn't use them — `stubTheme()` and `{ details: makeDetails() }` already satisfy the interfaces structurally.
157
- The return type `Text` has a `.text` property — `(result as any).text` can become `result!.text` (non-null assertion after `expect(result).toBeDefined()`).
158
-
159
- Fix: remove the casts; structural typing handles it.
160
- For result access, define a minimal `{ text: string }` type or use non-null assertion.
161
-
162
- #### Pattern B: context casts (14 casts → 0)
163
-
164
- - `agent-menu.test.ts` (8): define `MenuCtx` in production; type `makeCtx()` return.
165
- - `agent-manager.test.ts` (1): `mockCtx` is consumed by a mocked `buildParentSnapshot` — type as `unknown`.
166
- - `parent-snapshot.test.ts` (1): define a test-local interface matching the fields `buildParentSnapshot` reads.
167
- - `print-mode.test.ts` (2): type `makeHeadlessCtx()` return.
168
- - `runtime.test.ts` (1): pass a structurally valid `UICtx` (fixed by `WidgetLike` step).
169
- - `make-deps.test.ts` (3): type ctx args or use `unknown`.
170
-
171
- #### Pattern C: session casts (10 casts → ~1)
172
-
173
- Most are `{ session: {} as any, outputFile: ... }` for `record.execution`.
174
- Fix: expand `createMockSession()` to include the fields these tests need (`dispose`, `steer`, `getSessionStats`), then use it.
175
- One cast may remain for truly minimal session stubs.
176
-
177
- #### Pattern D: runtime/widget casts (9 casts → 0)
178
-
179
- Define `WidgetLike` in `runtime.ts`; change the `widget` field type.
180
- Use real `AgentActivityTracker` instances (constructor takes only `maxTurns?`).
181
-
182
- #### Pattern E: tool-execute ctx casts (5 casts → 0)
183
-
184
- Define a `STUB_CTX` constant in `test/helpers/` satisfying the tool execute's context parameter.
185
-
186
- #### Pattern F: RunOptions casts (3 casts → 0)
187
-
188
- Check whether `defaultMaxTurns` and `graceTurns` are on `RunOptions` — they are.
189
- The `as any` casts are vestigial; remove them.
190
-
191
- #### Pattern G: helpers.test.ts (7 casts → 0)
192
-
193
- Construct typed `TypeListRegistry` mocks.
194
- Fix `textResult` return type to avoid `details as any`.
195
- Use real `AgentActivityTracker` instances.
196
-
197
- #### Pattern H: conversation-viewer test casts (4 test casts → ~1)
198
-
199
- Type message mock objects using the local types from production change #2.
200
- Keep `(viewer as any).buildContentLines()` (private method access — the alternative of exposing the method is worse).
201
-
202
- #### Pattern I: other (6 casts → ~2)
203
-
204
- - `messages: [] as any[]` → type as `unknown[]`.
205
- - `(manager as any).cleanupInterval` → keep (private field assertion is intentional).
206
- - `usage.test.ts` (2) → type mock objects.
207
-
208
- ## Module-Level Changes
209
-
210
- ### Modified source files
211
-
212
- 1. `src/agent-runner.ts`
213
- - Import SDK types (`Model`, `ModelRegistry`, `SettingsManager`, `SessionManager`, `ResourceLoader`) as type-only imports.
214
- - Widen `CreateSessionOptions` fields from `unknown` to SDK types.
215
- - Change `RunnerIO.createSettingsManager` return type from `unknown` to `SettingsManager`.
216
- - Define `getToolCallName()` helper and local `ToolCallContent` interface.
217
- - Replace `(c as any).name ?? (c as any).toolName` with `getToolCallName(c)` in `getAgentConversation`.
218
-
219
- 2. `src/ui/conversation-viewer.ts`
220
- - Define local `ToolCallContent`, `BashExecutionMessage` interfaces and type guards.
221
- - Replace `(c as any).name ?? (c as any).toolName` with typed helper.
222
- - Replace `(msg as any).role === "bashExecution"` / `const bash = msg as any` with type guard.
223
-
224
- 3. `src/ui/agent-menu.ts`
225
- - Define and export `MenuCtx` interface.
226
- - Change handler parameter type from `ExtensionContext` to `MenuCtx`.
227
-
228
- 4. `src/runtime.ts`
229
- - Define and export `WidgetLike` interface.
230
- - Change `widget` field type from `AgentWidget | null` to `WidgetLike | null`.
231
-
232
- 5. `src/tools/helpers.ts`
233
- - Change `textResult` to avoid `details as any` — type the return properly.
234
-
235
- 6. `src/index.ts`
236
- - Remove `opts as any` casts in `createResourceLoader` and `createSession` factories (enabled by SDK-typed option interfaces).
237
-
238
- ### Modified test files
239
-
240
- 1. `test/renderer.test.ts` — remove all 29 casts.
241
- 2. `test/runtime.test.ts` — use `WidgetLike` stubs and real `AgentActivityTracker`.
242
- 3. `test/ui/agent-menu.test.ts` — type `makeCtx()` as `MenuCtx`.
243
- 4. `test/tools/helpers.test.ts` — typed registry mocks, real `AgentActivityTracker`.
244
- 5. `test/conversation-viewer.test.ts` — typed message mocks.
245
- 6. `test/agent-runner.test.ts` — remove `as any` on RunOptions; type messages.
246
- 7. `test/agent-runner-extension-tools.test.ts` — type messages.
247
- 8. `test/agent-manager.test.ts` — type `mockCtx`.
248
- 9. `test/print-mode.test.ts` — type `makeHeadlessCtx()`.
249
- 10. `test/parent-snapshot.test.ts` — type mock context.
250
- 11. `test/service-adapter.test.ts` — use `createMockSession()`.
251
- 12. `test/tools/steer-tool.test.ts` — stub ctx, use `createMockSession()`.
252
- 13. `test/tools/get-result-tool.test.ts` — stub ctx, use `createMockSession()`.
253
- 14. `test/tools/foreground-runner.test.ts` — use `createMockSession()`.
254
- 15. `test/tools/background-spawner.test.ts` — use `createMockSession()`.
255
- 16. `test/tools/agent-tool.test.ts` — use `createMockSession()`.
256
- 17. `test/helpers/make-deps.test.ts` — type ctx args.
257
- 18. `test/usage.test.ts` — type mock objects.
258
-
259
- ## Test Impact Analysis
260
-
261
- 1. No new test coverage — this is a type-safety improvement on existing tests.
262
- 2. No tests become redundant.
263
- 3. All existing tests stay as-is in terms of assertions; only type annotations and mock construction change.
264
- 4. `pnpm run check` is the primary validation — every step must pass type checking since the goal is eliminating type holes.
265
- 5. Expanding `createMockSession()` affects multiple consumers — diff existing defaults before changing (per testing skill).
266
-
267
- ## TDD Order
268
-
269
- Steps are ordered by independence and impact (production changes first, then largest cast-count test reductions).
270
-
271
- 1. **Widen option interfaces to SDK types; remove index.ts casts (2 source casts → 0).**
272
- Import SDK types as type-only in `agent-runner.ts`.
273
- Widen `CreateSessionOptions` fields (`settingsManager`, `modelRegistry`, `model`, `resourceLoader`, `sessionManager`) to SDK types.
274
- Change `RunnerIO.createSettingsManager` return type to `SettingsManager`.
275
- Remove `as any` casts from `index.ts` factories.
276
- Run `pnpm run check` + full suite.
277
- Commit: `feat: use SDK types in CreateSessionOptions (#134)`
278
-
279
- 2. **Add message-content type guards; remove viewer and runner source casts (6 source casts → 0).**
280
- Define `ToolCallContent` interface and `getToolCallName()` helper in `conversation-viewer.ts`.
281
- Define `BashExecutionMessage` interface and `isBashExecution()` guard in `conversation-viewer.ts`.
282
- Replace all source `as any` casts in `conversation-viewer.ts`.
283
- Define the same `getToolCallName()` helper (or extract a shared one) in `agent-runner.ts` and replace its cast.
284
- Run `pnpm run check` + affected tests.
285
- Commit: `fix: replace message-shape as-any casts with type guards (#134)`
286
-
287
- 3. **Remove renderer test casts (29 → 0).**
288
- Remove all `as any` casts on `stubTheme()`, message objects, and result access.
289
- Use `result!.text` (non-null assertion after `toBeDefined()` guard) for result access.
290
- Run `pnpm run check` + `pnpm vitest run test/renderer.test.ts`.
291
- Commit: `test: remove as-any casts in renderer tests (#134)`
292
-
293
- 4. **Add `MenuCtx` interface; remove menu-test casts (8 → 0).**
294
- Define `MenuCtx` in `agent-menu.ts`.
295
- Change handler parameter from `ExtensionContext` to `MenuCtx`.
296
- Type `makeCtx()` return in test.
297
- Run `pnpm run check` + `pnpm vitest run test/ui/agent-menu.test.ts`.
298
- Commit: `feat: narrow menu handler to MenuCtx interface (#134)`
299
-
300
- 5. **Add `WidgetLike`; remove runtime casts (9 → 0).**
301
- Define `WidgetLike` in `runtime.ts`.
302
- Change `widget` field type.
303
- Update `runtime.test.ts`: typed stubs, real `AgentActivityTracker` instances.
304
- Run `pnpm run check` + `pnpm vitest run test/runtime.test.ts`.
305
- Commit: `feat: narrow runtime widget field to WidgetLike interface (#134)`
306
-
307
- 6. **Expand `createMockSession`; remove session casts (10 → ~1).**
308
- Add fields to `createMockSession()` that tool/service tests need.
309
- Use it in tool tests, service-adapter, agent-manager for `record.execution.session`.
310
- Run `pnpm run check` + full suite.
311
- Commit: `test: use createMockSession for session execution casts (#134)`
312
-
313
- 7. **Remove helpers.test.ts casts (7 → 0).**
314
- Typed `TypeListRegistry` mocks.
315
- Fix `textResult` return type in `src/tools/helpers.ts`.
316
- Real `AgentActivityTracker` instances.
317
- Run `pnpm run check` + `pnpm vitest run test/tools/helpers.test.ts`.
318
- Commit: `test: remove as-any casts in helpers tests (#134)`
319
-
320
- 8. **Remove context casts across remaining test files (6 → 0).**
321
- Type `mockCtx` in `agent-manager.test.ts`.
322
- Type `makeHeadlessCtx()` in `print-mode.test.ts`.
323
- Type mock context in `parent-snapshot.test.ts`.
324
- Type `{} as any` in `make-deps.test.ts`.
325
- Run `pnpm run check` + full suite.
326
- Commit: `test: remove remaining context as-any casts (#134)`
327
-
328
- 9. **Remove RunOptions and message-array casts (5 → 0).**
329
- Remove vestigial `as any` on RunOptions objects.
330
- Type `messages` arrays as `unknown[]`.
331
- Run `pnpm run check` + affected tests.
332
- Commit: `test: remove RunOptions and message-array casts (#134)`
333
-
334
- 10. **Remove tool-execute ctx casts (5 → 0).**
335
- Define `STUB_CTX` in `test/helpers/`.
336
- Use it in `steer-tool.test.ts`, `get-result-tool.test.ts`, `make-deps.test.ts`.
337
- Run `pnpm run check` + affected tests.
338
- Commit: `test: remove tool-execute context casts (#134)`
339
-
340
- 11. **Clean up conversation-viewer test and usage casts (6 → ~2).**
341
- Type message mocks in `conversation-viewer.test.ts`.
342
- Type usage mock objects in `usage.test.ts`.
343
- Keep `(viewer as any).buildContentLines()` and `(manager as any).cleanupInterval` (private access, intentional).
344
- Run `pnpm run check` + full suite.
345
- Commit: `test: remove conversation-viewer and usage as-any casts (#134)`
346
-
347
- ## Risks and Mitigations
348
-
349
- | Risk | Mitigation |
350
- | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
351
- | Widening `CreateSessionOptions` to SDK types re-couples `agent-runner.ts` to SDK | These are type-only imports — no runtime coupling. Tests still mock at the `RunnerIO` function level. The `RunnerIO` interface is the decoupling boundary, not the option types. |
352
- | Narrowing `widget` to `WidgetLike` could break callers accessing `AgentWidget`-specific methods | Grep all `runtime.widget` access sites first; verify they only use `update()`, `markFinished()`, `setUICtx()`. |
353
- | Narrowing menu handler to `MenuCtx` could break callers passing `ExtensionContext` | `ExtensionContext` is structurally a superset of `MenuCtx` — callers pass it unchanged. |
354
- | Expanding `createMockSession()` could break consumers with different default expectations | Diff existing consumers' default expectations before adding fields (per testing skill). |
355
- | Message type guards add code to conversation-viewer and agent-runner | Each guard is 2–4 lines; they replace unsafe `as any` access with documented, compile-checked types. Net code stays similar. |
356
- | 11-step plan is large | Each step is independently committable. No step depends on a subsequent one. Steps can be reordered or skipped. |
357
-
358
- ## Open Questions
359
-
360
- - Should `getToolCallName()` be shared between `conversation-viewer.ts` and `agent-runner.ts`, or duplicated?
361
- Both files handle the same SDK message shape.
362
- A shared helper in a common module (e.g., `context.ts` which already has `extractText`) avoids duplication.
363
- Alternatively, the duplication is cheap (3 lines) and the two files have different concerns.
364
- - Should `STUB_CTX` live in `test/helpers/stub-ctx.ts` or inline?
365
- Centralize — 3+ tool tests share the pattern.
366
- - Estimated final count: 2–3 remaining casts (`(viewer as any).buildContentLines()`, `(manager as any).cleanupInterval`, possibly 1 more for an unexported SDK type).
@@ -1,182 +0,0 @@
1
- ---
2
- issue: 135
3
- issue_title: "Extract display helpers from `agent-widget.ts`"
4
- ---
5
-
6
- # Extract display helpers from agent-widget.ts
7
-
8
- ## Problem Statement
9
-
10
- `agent-widget.ts` (522 lines) exports 11 helper functions and constants that are general-purpose display utilities with no dependency on the widget's lifecycle or state.
11
- Six other source modules (`agent-menu.ts`, `conversation-viewer.ts`, `renderer.ts`, `agent-tool.ts`, `foreground-runner.ts`, `get-result-tool.ts`) and two tool support modules (`helpers.ts`, `background-spawner.ts`) import formatting functions or display types from the widget — creating a false dependency on a lifecycle-heavy UI module.
12
-
13
- This is Phase 8, Step J of the architecture plan.
14
-
15
- ## Goals
16
-
17
- - Extract pure formatters, display helpers, constants, and associated types into `ui/display.ts`.
18
- - Update all import sites to import from `ui/display.ts` instead of `ui/agent-widget.ts`.
19
- - Reduce `agent-widget.ts` to only the `AgentWidget` class and its immediate dependencies (`UICtx`, private helpers).
20
- - Unblock Step K (menu decomposition, #136) — extracted menu sub-modules will import display helpers without pulling in the widget.
21
-
22
- ## Non-Goals
23
-
24
- - Decomposing `agent-menu.ts` — deferred to #136 (Step K).
25
- - Changing any runtime behavior or public API.
26
- - Extracting `UICtx` — it is a widget-lifecycle type used only by `AgentWidget`, `runtime.ts`, and `index.ts`.
27
-
28
- ## Background
29
-
30
- The architecture doc (Phase 8 roadmap, Step J) prescribes exactly which symbols to extract.
31
- The `code-design` skill's "Helpers stay in the file" rule applies: these helpers have accumulated to the point where they warrant their own module and tests.
32
- AGENTS.md's "one concern per file" constraint also supports the extraction.
33
-
34
- ### Symbols to extract
35
-
36
- #### Pure formatters (zero runtime dependencies)
37
-
38
- 1. `formatTokens(count)` — compact token count ("33.8k token").
39
- 2. `formatSessionTokens(tokens, percent, theme, compactions)` — annotated token string with threshold colors.
40
- 3. `formatTurns(turnCount, maxTurns)` — turn counter with optional limit.
41
- 4. `formatMs(ms)` — milliseconds → "1.2s".
42
- 5. `formatDuration(startedAt, completedAt)` — timestamp pair → human duration.
43
-
44
- #### Display helpers (registry lookup only)
45
-
46
- 6. `getDisplayName(type, registry)` — resolved display name for an agent type.
47
- 7. `getPromptModeLabel(type, registry)` — "twin" for append mode, undefined otherwise.
48
- 8. `buildInvocationTags(invocation)` — config tags array from invocation options.
49
- 9. `describeActivity(activeTools, responseText)` — human-readable activity string.
50
-
51
- #### Constants
52
-
53
- 10. `SPINNER` — braille spinner frames.
54
- 11. `ERROR_STATUSES` — set of error/non-success status strings.
55
- 12. `TOOL_DISPLAY` — tool name → action verb mapping (private, moves with `describeActivity`).
56
-
57
- #### Types
58
-
59
- 13. `Theme` — used in `formatSessionTokens` signature; must co-locate.
60
- 14. `AgentDetails` — display metadata interface used by tools; no widget dependency.
61
-
62
- `UICtx` stays in `agent-widget.ts` — it defines the widget's host contract and is only consumed by the widget class, `runtime.ts`, and `index.ts`.
63
-
64
- ### Current import graph (agent-widget.ts consumers)
65
-
66
- | Consumer | Symbols imported |
67
- | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
68
- | `ui/conversation-viewer.ts` | `buildInvocationTags`, `describeActivity`, `formatDuration`, `formatSessionTokens`, `getDisplayName`, `getPromptModeLabel`, `Theme` |
69
- | `ui/agent-menu.ts` | `formatDuration`, `getDisplayName` |
70
- | `tools/agent-tool.ts` | `AgentDetails`, `buildInvocationTags`, `formatMs`, `formatTurns`, `getDisplayName`, `getPromptModeLabel`, `SPINNER`, `UICtx` |
71
- | `tools/foreground-runner.ts` | `AgentDetails`, `describeActivity`, `formatMs`, `SPINNER` |
72
- | `tools/get-result-tool.ts` | `formatDuration`, `getDisplayName` |
73
- | `tools/helpers.ts` | `AgentDetails`, `formatTokens` |
74
- | `tools/background-spawner.ts` | `AgentDetails` |
75
- | `renderer.ts` | `formatMs`, `formatTokens`, `formatTurns` |
76
- | `runtime.ts` | `UICtx` |
77
- | `index.ts` | `AgentWidget`, `UICtx` |
78
- | `test/agent-widget.test.ts` | `formatSessionTokens`, `getDisplayName`, `getPromptModeLabel` |
79
- | `test/conversation-viewer.test.ts` | `Theme` |
80
-
81
- ### Post-extraction import graph
82
-
83
- After extraction, `ui/agent-widget.ts` imports `display.ts` for the symbols it still uses internally (e.g., `getDisplayName`, `formatMs`, `formatTurns`, `formatSessionTokens`, `ERROR_STATUSES`, `SPINNER`, `describeActivity`).
84
- All other consumers switch their imports from `./agent-widget.js` to `./display.js` (or `../ui/display.js` for `tools/` and `renderer.ts`).
85
-
86
- Only `index.ts` and `runtime.ts` continue to import from `agent-widget.ts` (for `AgentWidget` class and `UICtx` type).
87
- `tools/agent-tool.ts` splits its import: `UICtx` from `agent-widget.ts`, everything else from `display.ts`.
88
-
89
- ## Design Overview
90
-
91
- This is a pure code-motion refactoring — no behavior changes.
92
-
93
- ### New module: `ui/display.ts`
94
-
95
- Contains all 12 exported symbols (5 formatters, 4 display helpers, 3 constants) plus 2 types (`Theme`, `AgentDetails`) and 1 private helper (`truncateLine`, used by `describeActivity`).
96
-
97
- The module's only imports are:
98
-
99
- - `AgentConfigLookup` from `../agent-types.js` (type-only, for `getDisplayName`/`getPromptModeLabel`).
100
- - `SubagentType`, `AgentInvocation` from `../types.js` (type-only).
101
-
102
- No SDK imports, no runtime dependencies — exactly the kind of pure utility module the code-design skill prescribes.
103
-
104
- ### Residual `agent-widget.ts`
105
-
106
- After extraction, `agent-widget.ts` contains:
107
-
108
- - `UICtx` type (widget host contract).
109
- - `AgentWidget` class (~340 lines) with its private helpers.
110
- - Imports from `./display.js` for the format/display functions used in rendering.
111
-
112
- ## Module-Level Changes
113
-
114
- ### New files
115
-
116
- | File | Contents |
117
- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
118
- | `src/ui/display.ts` | All extracted symbols: `Theme`, `AgentDetails`, `SPINNER`, `ERROR_STATUSES`, `TOOL_DISPLAY`, `formatTokens`, `formatSessionTokens`, `formatTurns`, `formatMs`, `formatDuration`, `getDisplayName`, `getPromptModeLabel`, `buildInvocationTags`, `describeActivity`, private `truncateLine`. |
119
-
120
- ### Modified files
121
-
122
- | File | Change |
123
- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
124
- | `src/ui/agent-widget.ts` | Remove all extracted symbols. Add `import` from `./display.js` for symbols `AgentWidget` still uses internally. Keep `UICtx`, `AgentWidget` class, private widget helpers. |
125
- | `src/ui/conversation-viewer.ts` | Change import path from `./agent-widget.js` to `./display.js`. |
126
- | `src/ui/agent-menu.ts` | Change import path from `./agent-widget.js` to `./display.js`. |
127
- | `src/tools/agent-tool.ts` | Split import: `UICtx` from `../ui/agent-widget.js`; all others from `../ui/display.js`. |
128
- | `src/tools/foreground-runner.ts` | Change import path from `../ui/agent-widget.js` to `../ui/display.js`. |
129
- | `src/tools/get-result-tool.ts` | Change import path from `../ui/agent-widget.js` to `../ui/display.js`. |
130
- | `src/tools/helpers.ts` | Change import path from `../ui/agent-widget.js` to `../ui/display.js`. |
131
- | `src/tools/background-spawner.ts` | Change import path from `../ui/agent-widget.js` to `../ui/display.js`. |
132
- | `src/renderer.ts` | Change import path from `./ui/agent-widget.js` to `./ui/display.js`. |
133
- | `test/agent-widget.test.ts` | Change import path to `../src/ui/display.js`. Rename file to `test/display.test.ts` since it tests extracted functions. |
134
- | `test/conversation-viewer.test.ts` | Change `Theme` import from `../src/ui/agent-widget.js` to `../src/ui/display.js`. |
135
-
136
- ### Unchanged files
137
-
138
- | File | Reason |
139
- | ---------------- | ------------------------------------------------------------------- |
140
- | `src/runtime.ts` | Imports only `UICtx` — stays in `agent-widget.ts`. |
141
- | `src/index.ts` | Imports `AgentWidget` and `UICtx` — both stay in `agent-widget.ts`. |
142
-
143
- ## Test Impact Analysis
144
-
145
- 1. The extraction enables dedicated `display.test.ts` that tests formatting functions in isolation without any widget class ceremony.
146
- The existing `agent-widget.test.ts` already tests only extracted functions (`formatSessionTokens`, `getDisplayName`, `getPromptModeLabel`) — it becomes `display.test.ts` with no assertion changes, just a file rename and import path update.
147
- 2. No existing tests become redundant — the current test file already exercises the extracted layer exclusively.
148
- 3. No existing tests need assertion changes — this is a pure code-motion refactoring with no behavior change.
149
-
150
- ## TDD Order
151
-
152
- 1. **Create `ui/display.ts` with all extracted symbols; update `agent-widget.ts` to import from it.**
153
- Move the 12 exported symbols, 2 types, and 1 private helper to `ui/display.ts`.
154
- Remove them from `agent-widget.ts` and add imports from `./display.js` for symbols the `AgentWidget` class still references.
155
- Commit: `refactor: extract display helpers into ui/display.ts (#135)`
156
-
157
- 2. **Update all consumer imports to point at `ui/display.ts`.**
158
- Update the 8 source files (`conversation-viewer.ts`, `agent-menu.ts`, `agent-tool.ts`, `foreground-runner.ts`, `get-result-tool.ts`, `helpers.ts`, `background-spawner.ts`, `renderer.ts`) to import from the new module.
159
- Commit: `refactor: update imports to use ui/display.ts (#135)`
160
-
161
- 3. **Rename test file and update test imports.**
162
- Rename `test/agent-widget.test.ts` → `test/display.test.ts`.
163
- Update import path to `../src/ui/display.js`.
164
- Update `Theme` import in `test/conversation-viewer.test.ts`.
165
- Commit: `test: rename agent-widget test to display test (#135)`
166
-
167
- 4. **Verify: run `pnpm run check` and `pnpm vitest run`.**
168
- Confirm type-checking and all tests pass.
169
- No commit needed — validation step.
170
-
171
- ## Risks and Mitigations
172
-
173
- | Risk | Mitigation |
174
- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
175
- | Missed import site causes runtime `undefined` import | Grep confirmed all 10 source consumers and 2 test consumers above. Step 4 validates with type-check + full test suite. |
176
- | `TOOL_DISPLAY` made public unintentionally | Keep it non-exported in `display.ts` (only `describeActivity` uses it). |
177
- | Circular dependency `display.ts` ↔ `agent-widget.ts` | `display.ts` has no imports from `agent-widget.ts`. `agent-widget.ts` imports from `display.ts` — one-directional. |
178
- | Re-export churn for downstream consumers | No downstream consumers — these are all internal module imports, not public API. |
179
-
180
- ## Open Questions
181
-
182
- None — the architecture doc and issue specify the exact extraction set and target module.