@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,297 +0,0 @@
1
- ---
2
- issue: 110
3
- issue_title: "refactor(pi-subagents): wrap AgentActivity in AgentActivityTracker class"
4
- ---
5
-
6
- # Wrap AgentActivity in AgentActivityTracker class
7
-
8
- ## Problem Statement
9
-
10
- `AgentActivity` is a 7-field mutable interface (`activeTools`, `toolUses`, `responseText`, `session`, `turnCount`, `maxTurns`, `lifetimeUsage`) shared across 4 modules.
11
- `ui-observer.ts` writes raw fields on it (output arguments), the widget and conversation viewer read them, and the agent-tool creates empty instances and stuffs them into a shared `Map`.
12
- The mutation contract is implicit — callers know which fields to set by convention, not by API.
13
-
14
- This is Phase 7, Step A3 in the architecture doc.
15
-
16
- ## Goals
17
-
18
- - Wrap `AgentActivity` in an `AgentActivityTracker` class with explicit transition methods.
19
- - Replace the output-argument writes in `ui-observer.ts` with tracker method calls.
20
- - Expose read-only accessors for the state the widget, notification system, conversation viewer, and agent-tool need.
21
- - Change the shared `Map<string, AgentActivity>` on `SubagentRuntime` to `Map<string, AgentActivityTracker>`.
22
- - Preserve all existing behavior — this is a pure encapsulation refactor.
23
-
24
- ## Non-Goals
25
-
26
- - Splitting `AgentRecord` lifecycle state (#111) — deferred to Step B.
27
- - Replacing `AgentManager` callbacks with an observer (#112) — deferred to Step C.
28
- - Narrowing `AgentToolDeps` or `AgentMenuDeps` further (#114) — deferred to Step D2.
29
- - Changing `createNotificationSystem` from closure to class (#116) — deferred to Step E2.
30
-
31
- ## Background
32
-
33
- ### Who writes AgentActivity today
34
-
35
- `ui-observer.ts` (`subscribeUIObserver`) is the sole writer.
36
- It subscribes to session events and mutates the state object directly:
37
-
38
- - `state.activeTools.set(...)` / `state.activeTools.delete(...)` on tool start/end
39
- - `state.toolUses++` on tool end
40
- - `state.responseText = ""` on message start, `state.responseText += delta` on message update
41
- - `state.turnCount++` on turn end
42
- - `addUsage(state.lifetimeUsage, ...)` on message end with assistant usage
43
-
44
- The agent-tool also writes `session` after session creation (`fgState.session = session`, `bgState.session = session`).
45
-
46
- ### Who reads AgentActivity today
47
-
48
- | Consumer | Fields read |
49
- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------- |
50
- | `agent-widget.ts` (widget render) | `activeTools`, `responseText`, `toolUses`, `turnCount`, `maxTurns`, `lifetimeUsage`, `session` |
51
- | `conversation-viewer.ts` | `toolUses`, `lifetimeUsage`, `session`, `activeTools`, `responseText` |
52
- | `notification.ts` (`buildNotificationDetails`) | `turnCount`, `maxTurns` |
53
- | `agent-tool.ts` (foreground streaming) | `toolUses`, `turnCount`, `maxTurns`, `activeTools`, `responseText`, `lifetimeUsage` |
54
- | `agent-menu.ts` (conversation viewer launch) | passes to `ConversationViewer` |
55
-
56
- ### Who creates AgentActivity today
57
-
58
- `createAgentActivity()` in `agent-tool.ts` — a factory function that returns a plain object with defaults.
59
-
60
- ### AGENTS.md constraints
61
-
62
- - One concern per file: the tracker gets its own module.
63
- - Avoid `any`: use typed accessors.
64
- - Output arguments: this refactor eliminates them from `ui-observer.ts`.
65
- - Keep modules focused: the tracker owns its mutable state; consumers use read-only accessors.
66
-
67
- ## Design Overview
68
-
69
- ### AgentActivityTracker class
70
-
71
- New file: `src/ui/agent-activity-tracker.ts`.
72
-
73
- The class owns the 7 mutable fields and exposes:
74
-
75
- 1. Transition methods (the write surface — called by `ui-observer.ts` and agent-tool):
76
-
77
- ```typescript
78
- onToolStart(toolName: string): void // adds to activeTools map
79
- onToolEnd(toolName: string): void // removes from activeTools, increments toolUses
80
- onMessageStart(): void // resets responseText
81
- onMessageUpdate(delta: string): void // appends to responseText
82
- onTurnEnd(): void // increments turnCount
83
- onUsageUpdate(usage: UsageDelta): void // accumulates into lifetimeUsage
84
- setSession(session: SessionLike): void // one-time session binding
85
- ```
86
-
87
- 2. Read-only accessors (the read surface — used by widget, notification, conversation viewer, agent-tool streaming):
88
-
89
- ```typescript
90
- get activeTools(): ReadonlyMap<string, string>
91
- get toolUses(): number
92
- get responseText(): string
93
- get session(): SessionLike | undefined
94
- get turnCount(): number
95
- get maxTurns(): number | undefined
96
- get lifetimeUsage(): Readonly<LifetimeUsage>
97
- ```
98
-
99
- The constructor accepts `maxTurns?: number` (set at creation time, immutable).
100
-
101
- ### UsageDelta type
102
-
103
- A narrow type for the usage values passed to `onUsageUpdate`:
104
-
105
- ```typescript
106
- interface UsageDelta { input: number; output: number; cacheWrite: number }
107
- ```
108
-
109
- This matches the shape `addUsage` already expects and avoids coupling to the full `LifetimeUsage` type name for what is logically a delta.
110
-
111
- ### activeTools key strategy
112
-
113
- The current `activeTools` Map uses `toolName + "_" + Date.now()` as a key to allow multiple concurrent tools with the same name.
114
- `onToolStart` returns `void` and generates the key internally (same `Date.now()` strategy).
115
- `onToolEnd(toolName)` finds and removes the first matching entry (same logic as today).
116
-
117
- ### subscribeUIObserver changes
118
-
119
- `subscribeUIObserver` changes its second parameter from `state: AgentActivity` to `tracker: AgentActivityTracker`.
120
- Instead of writing fields, it calls tracker methods:
121
-
122
- ```typescript
123
- // Before:
124
- state.activeTools.set(event.toolName + "_" + Date.now(), event.toolName);
125
- // After:
126
- tracker.onToolStart(event.toolName);
127
- ```
128
-
129
- ### Consumer interface
130
-
131
- Readers continue to access the same properties but through getters.
132
- Since the tracker exposes matching property names, consumer code like `bg.turnCount` and `bg.toolUses` remains syntactically identical — only the type annotation changes from `AgentActivity` to `AgentActivityTracker`.
133
-
134
- The `AgentActivity` interface is removed entirely.
135
- All references migrate to `AgentActivityTracker`.
136
-
137
- ### Map type change
138
-
139
- `SubagentRuntime.agentActivity` changes from `Map<string, AgentActivity>` to `Map<string, AgentActivityTracker>`.
140
- All dependency bags that pass this map (`AgentToolDeps`, `AgentMenuDeps`, `NotificationDeps`, `AgentWidget` constructor) update their type annotations.
141
-
142
- ### createAgentActivity replacement
143
-
144
- The factory function in `agent-tool.ts` is replaced by `new AgentActivityTracker(maxTurns)`.
145
-
146
- ## Module-Level Changes
147
-
148
- ### New file
149
-
150
- | File | What |
151
- | ---------------------------------- | ---------------------------------------------------------------------------- |
152
- | `src/ui/agent-activity-tracker.ts` | `AgentActivityTracker` class with transition methods and read-only accessors |
153
-
154
- ### New test file
155
-
156
- | File | What |
157
- | ---------------------------------------- | ------------------------------------------------------------- |
158
- | `test/ui/agent-activity-tracker.test.ts` | Unit tests for all transition methods and read-only accessors |
159
-
160
- ### Modified files
161
-
162
- | File | What changes |
163
- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
164
- | `src/ui/ui-observer.ts` | Accept `AgentActivityTracker` instead of `AgentActivity`; call transition methods instead of writing fields |
165
- | `src/ui/agent-widget.ts` | Remove `AgentActivity` interface; import `AgentActivityTracker`; update `Map` type and read sites (property names stay the same) |
166
- | `src/ui/conversation-viewer.ts` | Import `AgentActivityTracker` instead of `AgentActivity`; update parameter type |
167
- | `src/ui/agent-menu.ts` | Import `AgentActivityTracker` instead of `AgentActivity`; update `Map` type |
168
- | `src/tools/agent-tool.ts` | Import `AgentActivityTracker`; replace `createAgentActivity()` with `new AgentActivityTracker()`; replace `fgState.session = session` with `fgState.setSession(session)`; update `Map` type in `AgentToolDeps` |
169
- | `src/notification.ts` | Import `AgentActivityTracker` instead of `AgentActivity`; update `buildNotificationDetails` parameter and `NotificationDeps.agentActivity` Map type |
170
- | `src/runtime.ts` | Import `AgentActivityTracker`; change `agentActivity` Map type; update `AgentWidget` import (type only change since `AgentActivity` moves) |
171
- | `src/index.ts` | No changes (already references `runtime.agentActivity` by reference, the type flows through) |
172
-
173
- ### Modified test files
174
-
175
- | File | What changes |
176
- | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
177
- | `test/ui/ui-observer.test.ts` | Replace `makeActivity()` factory with `new AgentActivityTracker()`; access state through getters; assertions on accessor values instead of raw field reads |
178
- | `test/notification.test.ts` | Replace `as AgentActivity` casts with `new AgentActivityTracker()`; set up tracker state via transition methods |
179
- | `test/tools/agent-tool.test.ts` | Update `Map<string, AgentActivity>` type to `Map<string, AgentActivityTracker>` |
180
-
181
- ### Removed exports
182
-
183
- | Symbol | Was in | Replaced by |
184
- | ---------------------------------- | ------------------------- | ------------------------------------------------------------------ |
185
- | `AgentActivity` (interface) | `src/ui/agent-widget.ts` | `AgentActivityTracker` class in `src/ui/agent-activity-tracker.ts` |
186
- | `createAgentActivity()` (function) | `src/tools/agent-tool.ts` | `new AgentActivityTracker(maxTurns)` |
187
-
188
- Grep verification: `AgentActivity` is referenced in 7 source files and 3 test files (listed above) — all accounted for in the modified files list.
189
-
190
- ## Test Impact Analysis
191
-
192
- ### New unit tests enabled
193
-
194
- The `AgentActivityTracker` class enables focused unit tests for each transition method in isolation:
195
-
196
- - `onToolStart` / `onToolEnd` — concurrent tool tracking, correct toolUses increment
197
- - `onMessageStart` / `onMessageUpdate` — response text lifecycle
198
- - `onTurnEnd` — turn counting from initial value
199
- - `onUsageUpdate` — accumulation semantics
200
- - `setSession` — one-time binding
201
- - Read-only accessors — verify consumers cannot mutate internal state
202
-
203
- These were previously impossible to test without going through `subscribeUIObserver` and a mock session.
204
-
205
- ### Existing tests that simplify
206
-
207
- `test/ui/ui-observer.test.ts` — currently constructs a plain `AgentActivity` object and asserts on raw field mutations.
208
- After the change, it constructs an `AgentActivityTracker` and the assertions read the same properties through accessors.
209
- The `makeActivity()` helper is replaced by `new AgentActivityTracker()`.
210
- The test logic stays the same (event → tracker state check) but the assertions use getter-backed properties.
211
-
212
- ### Existing tests that stay as-is
213
-
214
- `test/notification.test.ts` — the pure helper tests (`escapeXml`, `getStatusLabel`, `formatTaskNotification`, `buildNotificationDetails`) only need their `AgentActivity` type references updated to `AgentActivityTracker`.
215
- The notification system integration tests that cast `{} as AgentActivity` need minimal updates to construct a real tracker instead.
216
-
217
- `test/tools/agent-tool.test.ts` — only the `Map` type annotation changes.
218
-
219
- ## TDD Order
220
-
221
- ### 1. Red/green: AgentActivityTracker class — transition methods and read-only accessors
222
-
223
- Test file: `test/ui/agent-activity-tracker.test.ts`
224
-
225
- Tests:
226
-
227
- - Constructor sets initial state (`turnCount: 1`, empty `activeTools`, `toolUses: 0`, empty `responseText`, zero `lifetimeUsage`, `maxTurns` from constructor arg, `session` undefined)
228
- - `onToolStart` adds entry to `activeTools`
229
- - `onToolEnd` removes entry and increments `toolUses`
230
- - `onToolEnd` with no matching tool is a no-op (defensive)
231
- - Multiple concurrent tools with same name tracked independently
232
- - `onMessageStart` resets `responseText` to empty
233
- - `onMessageUpdate` appends delta to `responseText`
234
- - `onTurnEnd` increments `turnCount`
235
- - `onUsageUpdate` accumulates into `lifetimeUsage`
236
- - `setSession` stores the session reference
237
- - Read-only: `activeTools` returns `ReadonlyMap`
238
- - Read-only: `lifetimeUsage` returns `Readonly<LifetimeUsage>`
239
-
240
- Commit: `feat: add AgentActivityTracker class (#110)`
241
-
242
- ### 2. Red/green: migrate ui-observer to use AgentActivityTracker
243
-
244
- Update `src/ui/ui-observer.ts` to accept `AgentActivityTracker` and call transition methods.
245
- Update `test/ui/ui-observer.test.ts`: replace `makeActivity()` with `new AgentActivityTracker()`, read state through accessors.
246
-
247
- All existing test scenarios must pass unchanged (same events → same observable state).
248
-
249
- Commit: `refactor: migrate ui-observer to AgentActivityTracker (#110)`
250
-
251
- ### 3. Migrate agent-widget and conversation-viewer
252
-
253
- Update `src/ui/agent-widget.ts`: remove `AgentActivity` interface, import `AgentActivityTracker`, update `Map` type and constructor parameter.
254
- Update `src/ui/conversation-viewer.ts`: import `AgentActivityTracker`, update parameter type.
255
-
256
- No test changes needed — widget and conversation viewer are not unit-tested (they render UI).
257
-
258
- Commit: `refactor: migrate widget and conversation-viewer to AgentActivityTracker (#110)`
259
-
260
- ### 4. Migrate agent-tool
261
-
262
- Update `src/tools/agent-tool.ts`: import `AgentActivityTracker`, replace `createAgentActivity()` with `new AgentActivityTracker()`, replace `fgState.session = session` with `fgState.setSession(session)`, update `AgentToolDeps` Map type.
263
- Update `test/tools/agent-tool.test.ts`: update Map type.
264
-
265
- Commit: `refactor: migrate agent-tool to AgentActivityTracker (#110)`
266
-
267
- ### 5. Migrate notification and agent-menu
268
-
269
- Update `src/notification.ts`: import `AgentActivityTracker`, update `buildNotificationDetails` parameter and `NotificationDeps` Map type.
270
- Update `src/ui/agent-menu.ts`: import `AgentActivityTracker`, update Map type in `AgentMenuDeps`.
271
- Update `test/notification.test.ts`: replace `as AgentActivity` casts with real `AgentActivityTracker` instances.
272
-
273
- Commit: `refactor: migrate notification and agent-menu to AgentActivityTracker (#110)`
274
-
275
- ### 6. Migrate runtime and clean up
276
-
277
- Update `src/runtime.ts`: import `AgentActivityTracker`, change `agentActivity` Map type.
278
- Remove any remaining `AgentActivity` references.
279
- Run `pnpm run check` to verify no type errors remain.
280
-
281
- Commit: `refactor: complete AgentActivityTracker migration, remove AgentActivity interface (#110)`
282
-
283
- ## Risks and Mitigations
284
-
285
- | Risk | Mitigation |
286
- | --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
287
- | Read-only getters change identity semantics for `activeTools` and `lifetimeUsage` | The `ReadonlyMap` and `Readonly<LifetimeUsage>` types restrict writes at compile time. Consumers already only read these values, so no runtime change. Return the internal mutable reference cast to readonly (no copy overhead). |
288
- | Spreading a class instance loses methods | Grep for `{ ...activity` or `{ ...bg` patterns — none found in current code. The `buildDetails` function spreads `detailBase` (a plain object), not the activity. |
289
- | `onToolEnd` matching logic fragility | Port the exact same `for...of` + `break` pattern from `ui-observer.ts`. New unit tests cover this independently. |
290
- | `turnCount` initial value of 1 (not 0) | The current `createAgentActivity` sets `turnCount: 1`. The tracker constructor preserves this. A dedicated test asserts the initial value. |
291
- | Test files casting `{} as AgentActivity` | Replace with real `AgentActivityTracker` instances. Where tests only need `turnCount` and `maxTurns` (e.g., `buildNotificationDetails`), construct a tracker and call `onTurnEnd` to set up the desired state. |
292
-
293
- ## Open Questions
294
-
295
- - None — the issue and architecture doc are prescriptive about the approach.
296
- The only design latitude is whether `onToolStart` returns a key (for symmetric `onToolEnd(key)`) or whether `onToolEnd(toolName)` does a lookup.
297
- The plan uses `onToolEnd(toolName)` with lookup to match the existing pattern and avoid threading a key through the session event handler.