@gotgenes/pi-subagents 18.0.0 → 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 (257) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +22 -31
  3. package/docs/architecture/architecture.md +157 -204
  4. package/docs/architecture/history/phase-19-implement-ui-decisions.md +282 -0
  5. package/package.json +5 -6
  6. package/src/lifecycle/subagent.ts +5 -9
  7. package/src/observation/notification.ts +23 -10
  8. package/src/observation/subagent-events-observer.ts +1 -3
  9. package/src/tools/get-result-report.ts +60 -0
  10. package/src/tools/get-result-tool.ts +25 -40
  11. package/src/types.ts +1 -1
  12. package/src/ui/session-navigator.ts +0 -2
  13. package/.prettierignore +0 -5
  14. package/AGENTS.md +0 -7
  15. package/docs/plans/0048-implement-subagents-api.md +0 -304
  16. package/docs/plans/0049-remove-group-join-output-file-rpc.md +0 -180
  17. package/docs/plans/0051-update-adr-0001-hard-fork.md +0 -77
  18. package/docs/plans/0052-remove-scheduled-subagents.md +0 -133
  19. package/docs/plans/0053-extract-model-resolution-from-execute.md +0 -181
  20. package/docs/plans/0054-decompose-index-into-modules.md +0 -302
  21. package/docs/plans/0057-structured-debug-logging.md +0 -154
  22. package/docs/plans/0061-session-format-transcript.md +0 -284
  23. package/docs/plans/0066-replace-as-any-with-sdk-types.md +0 -215
  24. package/docs/plans/0069-create-subagent-runtime.md +0 -345
  25. package/docs/plans/0070-extract-event-handlers.md +0 -306
  26. package/docs/plans/0071-extract-session-config-assembler.md +0 -362
  27. package/docs/plans/0072-inject-agent-manager-collaborators.md +0 -329
  28. package/docs/plans/0076-inject-cwd-into-agent-manager.md +0 -102
  29. package/docs/plans/0077-inject-project-agents-dir.md +0 -115
  30. package/docs/plans/0080-consolidate-agent-config-lookup.md +0 -247
  31. package/docs/plans/0084-extract-git-worktree-manager.md +0 -142
  32. package/docs/plans/0087-evolve-subagent-runtime-methods.md +0 -240
  33. package/docs/plans/0098-extract-agent-record-state-machine.md +0 -435
  34. package/docs/plans/0099-replace-ctx-with-parent-snapshot.md +0 -488
  35. package/docs/plans/0100-replace-callback-threading-with-session-subscription.md +0 -454
  36. package/docs/plans/0102-consolidate-test-record-factory.md +0 -176
  37. package/docs/plans/0108-extract-agent-type-registry.md +0 -322
  38. package/docs/plans/0109-extract-settings-manager.md +0 -276
  39. package/docs/plans/0110-agent-activity-tracker.md +0 -297
  40. package/docs/plans/0111-split-agent-record-lifecycle.md +0 -582
  41. package/docs/plans/0112-replace-agent-manager-callbacks.md +0 -241
  42. package/docs/plans/0113-disambiguate-spawn-options.md +0 -155
  43. package/docs/plans/0114-narrow-agent-tool-menu-deps.md +0 -279
  44. package/docs/plans/0115-decompose-agent-tool.md +0 -337
  45. package/docs/plans/0116-type-housekeeping.md +0 -351
  46. package/docs/plans/0118-settings-manager-apply-methods.md +0 -271
  47. package/docs/plans/0123-remove-vi-fn-cast-smell.md +0 -179
  48. package/docs/plans/0131-consolidate-shared-test-fixtures.md +0 -207
  49. package/docs/plans/0132-inject-io-into-session-config.md +0 -219
  50. package/docs/plans/0133-inject-sdk-boundary-into-agent-runner.md +0 -373
  51. package/docs/plans/0134-reduce-as-any-casts.md +0 -366
  52. package/docs/plans/0135-extract-display-helpers.md +0 -182
  53. package/docs/plans/0136-decompose-agent-menu.md +0 -300
  54. package/docs/plans/0144-consolidate-observation-model.md +0 -263
  55. package/docs/plans/0145-decompose-execute-push-ctx-to-boundary.md +0 -290
  56. package/docs/plans/0146-narrow-ui-context.md +0 -319
  57. package/docs/plans/0147-inject-wrap-text-into-conversation-viewer.md +0 -166
  58. package/docs/plans/0148-split-agent-widget-rendering.md +0 -255
  59. package/docs/plans/0152-add-prompt-snippet.md +0 -91
  60. package/docs/plans/0164-reorganize-into-domain-directories.md +0 -409
  61. package/docs/plans/0165-decompose-resolved-spawn-config.md +0 -157
  62. package/docs/plans/0166-extract-parent-session-info.md +0 -231
  63. package/docs/plans/0167-narrow-runner-io.md +0 -150
  64. package/docs/plans/0168-extract-tool-filter-config.md +0 -173
  65. package/docs/plans/0169-extract-run-context-from-run-options.md +0 -194
  66. package/docs/plans/0170-reduce-build-content-lines-complexity.md +0 -225
  67. package/docs/plans/0171-reduce-render-result-complexity.md +0 -200
  68. package/docs/plans/0172-extract-turn-formatting.md +0 -206
  69. package/docs/plans/0180-reorder-append-prompt-for-kv-cache.md +0 -100
  70. package/docs/plans/0185-remove-persistent-agent-memory.md +0 -161
  71. package/docs/plans/0188-replace-any-casts-with-sdk-types.md +0 -162
  72. package/docs/plans/0192-define-session-context-interface.md +0 -107
  73. package/docs/plans/0193-runtime-owns-context-queries.md +0 -245
  74. package/docs/plans/0194-align-tool-interfaces-for-structural-typing.md +0 -139
  75. package/docs/plans/0195-convert-tool-factories-to-classes.md +0 -264
  76. package/docs/plans/0196-convert-runner-menu-to-classes.md +0 -268
  77. package/docs/plans/0205-decompose-render-widget-lines.md +0 -140
  78. package/docs/plans/0206-decompose-show-agent-detail.md +0 -211
  79. package/docs/plans/0207-decompose-agent-widget-update.md +0 -242
  80. package/docs/plans/0208-extract-shared-test-fixtures.md +0 -298
  81. package/docs/plans/0214-convert-remaining-closure-factories-to-classes.md +0 -261
  82. package/docs/plans/0215-decompose-build-parent-context.md +0 -166
  83. package/docs/plans/0216-decompose-start-agent.md +0 -255
  84. package/docs/plans/0217-extract-overwrite-guard.md +0 -176
  85. package/docs/plans/0218-push-sdk-boundary-in-settings.md +0 -172
  86. package/docs/plans/0219-reduce-test-duplication-top-3-clone-families.md +0 -162
  87. package/docs/plans/0227-evolve-agent-record-into-agent.md +0 -322
  88. package/docs/plans/0228-async-start-agent-dissolve-run-handle.md +0 -288
  89. package/docs/plans/0229-agent-born-complete.md +0 -564
  90. package/docs/plans/0230-extract-concurrency-queue.md +0 -265
  91. package/docs/plans/0231-push-exec-registry-to-runner.md +0 -245
  92. package/docs/plans/0232-agent-resume-internal-observer-lifecycle.md +0 -180
  93. package/docs/plans/0237-remove-disallowed-tools.md +0 -180
  94. package/docs/plans/0238-remove-extensions-filtering.md +0 -191
  95. package/docs/plans/0239-collapse-filter-active-tools.md +0 -217
  96. package/docs/plans/0242-rename-agent-tool-to-subagent.md +0 -165
  97. package/docs/plans/0256-extract-worktree-isolation.md +0 -256
  98. package/docs/plans/0257-extract-child-session-factory.md +0 -285
  99. package/docs/plans/0262-add-workspace-provider-seam.md +0 -264
  100. package/docs/plans/0264-remove-extension-lifecycle-control.md +0 -277
  101. package/docs/plans/0265-born-complete-subagent-session.md +0 -333
  102. package/docs/plans/0270-type-consumable-public-surface.md +0 -204
  103. package/docs/plans/0272-export-workspace-collaborator-types.md +0 -147
  104. package/docs/plans/0277-encapsulate-agent-session.md +0 -304
  105. package/docs/plans/0280-rename-agent-to-subagent.md +0 -197
  106. package/docs/plans/0360-custom-agents-default-append.md +0 -132
  107. package/docs/plans/0373-extract-subagent-state.md +0 -250
  108. package/docs/plans/0374-encapsulate-subagent-start-notification.md +0 -268
  109. package/docs/plans/0375-extract-run-listener-workspace-bracket.md +0 -300
  110. package/docs/plans/0376-extract-manager-observer.md +0 -232
  111. package/docs/plans/0377-split-widget-delegation-from-runtime.md +0 -254
  112. package/docs/plans/0378-consolidate-lifecycle-test-fixtures.md +0 -243
  113. package/docs/plans/0379-consolidate-ui-tools-test-fixtures.md +0 -335
  114. package/docs/plans/0380-extract-layered-settings-loader.md +0 -223
  115. package/docs/plans/0381-replace-concurrency-queue-with-limiter.md +0 -267
  116. package/docs/plans/0400-include-parent-prompt-in-replace-mode.md +0 -199
  117. package/docs/plans/0403-abort-subagents-on-interrupt.md +0 -180
  118. package/docs/plans/0412-unify-session-mock-builders.md +0 -146
  119. package/docs/plans/0420-fold-run-metrics-live-activity-onto-record.md +0 -228
  120. package/docs/plans/0421-migrate-activity-readers-to-record-getters.md +0 -309
  121. package/docs/plans/0422-delete-activity-tracker-ui-observer.md +0 -204
  122. package/docs/plans/0423-widget-self-drive-from-lifecycle.md +0 -264
  123. package/docs/plans/0424-drop-widget-dep-from-subagent-tool.md +0 -166
  124. package/docs/plans/0425-reconcile-subagent-events-contract.md +0 -144
  125. package/docs/plans/0426-consolidate-residual-test-clone-families.md +0 -235
  126. package/docs/plans/0427-reconsider-ui-direction.md +0 -212
  127. package/docs/plans/0441-remove-agent-definition-management-subtree.md +0 -180
  128. package/docs/plans/0442-dissolve-agents-conversation-viewer.md +0 -195
  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/retro/0048-implement-subagents-api.md +0 -44
  137. package/docs/retro/0049-remove-group-join-output-file-rpc.md +0 -49
  138. package/docs/retro/0051-update-adr-0001-hard-fork.md +0 -39
  139. package/docs/retro/0053-extract-model-resolution-from-execute.md +0 -40
  140. package/docs/retro/0054-decompose-index-into-modules.md +0 -53
  141. package/docs/retro/0057-structured-debug-logging.md +0 -77
  142. package/docs/retro/0061-session-format-transcript.md +0 -41
  143. package/docs/retro/0066-replace-as-any-with-sdk-types.md +0 -44
  144. package/docs/retro/0069-create-subagent-runtime.md +0 -43
  145. package/docs/retro/0070-extract-event-handlers.md +0 -49
  146. package/docs/retro/0071-extract-session-config-assembler.md +0 -60
  147. package/docs/retro/0072-inject-agent-manager-collaborators.md +0 -46
  148. package/docs/retro/0076-inject-cwd-into-agent-manager.md +0 -35
  149. package/docs/retro/0077-inject-project-agents-dir.md +0 -33
  150. package/docs/retro/0080-consolidate-agent-config-lookup.md +0 -35
  151. package/docs/retro/0084-extract-git-worktree-manager.md +0 -37
  152. package/docs/retro/0087-evolve-subagent-runtime-methods.md +0 -42
  153. package/docs/retro/0098-extract-agent-record-state-machine.md +0 -46
  154. package/docs/retro/0099-replace-ctx-with-parent-snapshot.md +0 -37
  155. package/docs/retro/0100-replace-callback-threading-with-session-subscription.md +0 -36
  156. package/docs/retro/0102-consolidate-test-record-factory.md +0 -30
  157. package/docs/retro/0108-extract-agent-type-registry.md +0 -41
  158. package/docs/retro/0109-extract-settings-manager.md +0 -55
  159. package/docs/retro/0110-agent-activity-tracker.md +0 -44
  160. package/docs/retro/0111-split-agent-record-lifecycle.md +0 -61
  161. package/docs/retro/0112-replace-agent-manager-callbacks.md +0 -35
  162. package/docs/retro/0113-disambiguate-spawn-options.md +0 -29
  163. package/docs/retro/0114-narrow-agent-tool-menu-deps.md +0 -38
  164. package/docs/retro/0115-decompose-agent-tool.md +0 -51
  165. package/docs/retro/0116-type-housekeeping.md +0 -42
  166. package/docs/retro/0118-settings-manager-apply-methods.md +0 -40
  167. package/docs/retro/0123-remove-vi-fn-cast-smell.md +0 -49
  168. package/docs/retro/0131-consolidate-shared-test-fixtures.md +0 -46
  169. package/docs/retro/0132-inject-io-into-session-config.md +0 -33
  170. package/docs/retro/0133-inject-sdk-boundary-into-agent-runner.md +0 -45
  171. package/docs/retro/0134-reduce-as-any-casts.md +0 -56
  172. package/docs/retro/0135-extract-display-helpers.md +0 -38
  173. package/docs/retro/0136-decompose-agent-menu.md +0 -43
  174. package/docs/retro/0144-consolidate-observation-model.md +0 -39
  175. package/docs/retro/0145-decompose-execute-push-ctx-to-boundary.md +0 -56
  176. package/docs/retro/0146-narrow-ui-context.md +0 -70
  177. package/docs/retro/0147-inject-wrap-text-into-conversation-viewer.md +0 -90
  178. package/docs/retro/0148-split-agent-widget-rendering.md +0 -39
  179. package/docs/retro/0152-add-prompt-snippet.md +0 -34
  180. package/docs/retro/0164-reorganize-into-domain-directories.md +0 -82
  181. package/docs/retro/0165-decompose-resolved-spawn-config.md +0 -78
  182. package/docs/retro/0166-extract-parent-session-info.md +0 -66
  183. package/docs/retro/0167-narrow-runner-io.md +0 -63
  184. package/docs/retro/0168-extract-tool-filter-config.md +0 -76
  185. package/docs/retro/0169-extract-run-context-from-run-options.md +0 -68
  186. package/docs/retro/0170-reduce-build-content-lines-complexity.md +0 -72
  187. package/docs/retro/0171-reduce-render-result-complexity.md +0 -77
  188. package/docs/retro/0172-extract-turn-formatting.md +0 -80
  189. package/docs/retro/0180-reorder-append-prompt-for-kv-cache.md +0 -62
  190. package/docs/retro/0185-remove-persistent-agent-memory.md +0 -73
  191. package/docs/retro/0188-replace-any-casts-with-sdk-types.md +0 -69
  192. package/docs/retro/0192-define-session-context-interface.md +0 -59
  193. package/docs/retro/0193-runtime-owns-context-queries.md +0 -75
  194. package/docs/retro/0194-align-tool-interfaces-for-structural-typing.md +0 -62
  195. package/docs/retro/0195-convert-tool-factories-to-classes.md +0 -84
  196. package/docs/retro/0196-convert-runner-menu-to-classes.md +0 -73
  197. package/docs/retro/0205-decompose-render-widget-lines.md +0 -64
  198. package/docs/retro/0206-decompose-show-agent-detail.md +0 -67
  199. package/docs/retro/0207-decompose-agent-widget-update.md +0 -92
  200. package/docs/retro/0208-extract-shared-test-fixtures.md +0 -102
  201. package/docs/retro/0214-convert-remaining-closure-factories-to-classes.md +0 -66
  202. package/docs/retro/0215-decompose-build-parent-context.md +0 -61
  203. package/docs/retro/0216-decompose-start-agent.md +0 -80
  204. package/docs/retro/0217-extract-overwrite-guard.md +0 -63
  205. package/docs/retro/0218-push-sdk-boundary-in-settings.md +0 -72
  206. package/docs/retro/0219-reduce-test-duplication-top-3-clone-families.md +0 -64
  207. package/docs/retro/0227-evolve-agent-record-into-agent.md +0 -80
  208. package/docs/retro/0228-async-start-agent-dissolve-run-handle.md +0 -80
  209. package/docs/retro/0229-agent-born-complete.md +0 -89
  210. package/docs/retro/0230-extract-concurrency-queue.md +0 -38
  211. package/docs/retro/0231-push-exec-registry-to-runner.md +0 -71
  212. package/docs/retro/0232-agent-resume-internal-observer-lifecycle.md +0 -109
  213. package/docs/retro/0237-remove-disallowed-tools.md +0 -78
  214. package/docs/retro/0238-remove-extensions-filtering.md +0 -72
  215. package/docs/retro/0239-collapse-filter-active-tools.md +0 -70
  216. package/docs/retro/0242-rename-agent-tool-to-subagent.md +0 -82
  217. package/docs/retro/0256-extract-worktree-isolation.md +0 -89
  218. package/docs/retro/0257-extract-child-session-factory.md +0 -33
  219. package/docs/retro/0262-add-workspace-provider-seam.md +0 -89
  220. package/docs/retro/0264-remove-extension-lifecycle-control.md +0 -91
  221. package/docs/retro/0265-born-complete-subagent-session.md +0 -97
  222. package/docs/retro/0270-type-consumable-public-surface.md +0 -108
  223. package/docs/retro/0272-export-workspace-collaborator-types.md +0 -38
  224. package/docs/retro/0277-encapsulate-agent-session.md +0 -80
  225. package/docs/retro/0280-rename-agent-to-subagent.md +0 -96
  226. package/docs/retro/0360-custom-agents-default-append.md +0 -81
  227. package/docs/retro/0373-extract-subagent-state.md +0 -94
  228. package/docs/retro/0374-encapsulate-subagent-start-notification.md +0 -171
  229. package/docs/retro/0375-extract-run-listener-workspace-bracket.md +0 -104
  230. package/docs/retro/0376-extract-manager-observer.md +0 -81
  231. package/docs/retro/0377-split-widget-delegation-from-runtime.md +0 -105
  232. package/docs/retro/0378-consolidate-lifecycle-test-fixtures.md +0 -100
  233. package/docs/retro/0379-consolidate-ui-tools-test-fixtures.md +0 -52
  234. package/docs/retro/0380-extract-layered-settings-loader.md +0 -97
  235. package/docs/retro/0381-replace-concurrency-queue-with-limiter.md +0 -95
  236. package/docs/retro/0400-include-parent-prompt-in-replace-mode.md +0 -84
  237. package/docs/retro/0403-abort-subagents-on-interrupt.md +0 -90
  238. package/docs/retro/0412-unify-session-mock-builders.md +0 -80
  239. package/docs/retro/0420-fold-run-metrics-live-activity-onto-record.md +0 -90
  240. package/docs/retro/0421-migrate-activity-readers-to-record-getters.md +0 -105
  241. package/docs/retro/0422-delete-activity-tracker-ui-observer.md +0 -97
  242. package/docs/retro/0423-widget-self-drive-from-lifecycle.md +0 -112
  243. package/docs/retro/0424-drop-widget-dep-from-subagent-tool.md +0 -89
  244. package/docs/retro/0425-reconcile-subagent-events-contract.md +0 -101
  245. package/docs/retro/0426-consolidate-residual-test-clone-families.md +0 -100
  246. package/docs/retro/0427-reconsider-ui-direction.md +0 -102
  247. package/docs/retro/0441-remove-agent-definition-management-subtree.md +0 -45
  248. package/docs/retro/0442-dissolve-agents-conversation-viewer.md +0 -108
  249. package/docs/retro/0444-shrink-widget-to-background-agents.md +0 -81
  250. package/docs/retro/0445-native-session-navigation.md +0 -122
  251. package/docs/retro/0446-spike-session-navigation-entry-criteria.md +0 -99
  252. package/docs/retro/0447-extract-subagents-settings-command.md +0 -91
  253. package/docs/retro/0448-block-disabled-agent-spawn.md +0 -75
  254. package/docs/retro/0462-navigation-renderer-tui-components.md +0 -105
  255. package/docs/retro/0463-file-snapshot-source-evicted-agents.md +0 -103
  256. package/src/observation/notification-state.ts +0 -27
  257. package/vitest.config.ts +0 -14
@@ -1,166 +0,0 @@
1
- ---
2
- issue: 147
3
- issue_title: "Inject text wrapping into ConversationViewer (Phase 9, Step O)"
4
- ---
5
-
6
- # Inject text wrapping into ConversationViewer
7
-
8
- ## Problem Statement
9
-
10
- `ConversationViewer` calls `wrapTextWithAnsi` directly from `@earendil-works/pi-tui` in four places inside `buildContentLines`.
11
- Because the function is a module-level binding, tests must intercept it via a hoisted `vi.mock("@earendil-works/pi-tui")` factory that replaces the entire TUI module.
12
- This is the last `vi.mock` on an SDK module in the test suite, added specifically to exercise the overwidth-clamping safety net.
13
-
14
- ## Goals
15
-
16
- - Accept `wrapText: (text: string, width: number) => string[]` via `ConversationViewerOptions`.
17
- - Destructure `ConversationViewerOptions` in the constructor signature (dependency bag convention).
18
- - Replace all four `wrapTextWithAnsi` calls in `buildContentLines` with `this.wrapText`.
19
- - Remove `wrapTextWithAnsi` from `conversation-viewer.ts`'s `@earendil-works/pi-tui` import.
20
- - Pass `wrapTextWithAnsi` at the production call site in `agent-menu.ts`.
21
- - Eliminate the hoisted `vi.mock("@earendil-works/pi-tui")` from `conversation-viewer.test.ts`.
22
-
23
- ## Non-Goals
24
-
25
- - Injecting `truncateToWidth` or any other TUI function (only `wrapTextWithAnsi` is relevant here).
26
- - Changing the overwidth-clamping behavior of `buildContentLines`.
27
- - Touching `agent-widget.ts` (tracked separately as Issue #148, Step P — already closed).
28
-
29
- ## Background
30
-
31
- `ui/conversation-viewer.ts` is the live conversation overlay rendered when a user selects an agent in the `/agents` menu.
32
- Its `buildContentLines` method formats messages from the agent session into displayable lines, calling `wrapTextWithAnsi` to soft-wrap text to the available terminal width.
33
-
34
- The overwidth-clamping safety net (`truncateToWidth` applied after `wrapTextWithAnsi`) exists because a prior upstream bug returned lines wider than the requested width.
35
- The `vi.mock` in the test is the mechanism for simulating that bug by returning overwidth strings from `wrapTextWithAnsi`.
36
-
37
- The only production call site for `new ConversationViewer(...)` is in the `viewAgentConversation` closure inside `createAgentsMenuHandler` in `ui/agent-menu.ts`.
38
-
39
- Architecture reference: `docs/architecture/architecture.md` § Phase 9, Step O.
40
-
41
- ## Design Overview
42
-
43
- ### `ConversationViewerOptions` — add `wrapText`
44
-
45
- ```typescript
46
- export interface ConversationViewerOptions {
47
- tui: TUI;
48
- session: AgentSession;
49
- record: AgentRecord;
50
- activity: AgentActivityTracker | undefined;
51
- theme: Theme;
52
- done: (result: undefined) => void;
53
- registry: AgentConfigLookup;
54
- wrapText: (text: string, width: number) => string[];
55
- }
56
- ```
57
-
58
- The field is **required** — it must be supplied at every construction site.
59
- No default is provided; the default would be an invisible SDK dependency hidden inside the class.
60
-
61
- ### Constructor destructuring
62
-
63
- The constructor adopts the dependency bag convention — destructure the options object rather than accessing via `options.*`:
64
-
65
- ```typescript
66
- constructor({
67
- tui, session, record, activity, theme, done, registry, wrapText,
68
- }: ConversationViewerOptions) {
69
- this.tui = tui;
70
- this.session = session;
71
- // … etc.
72
- this.wrapText = wrapText;
73
- this.unsubscribe = session.subscribe(() => { … });
74
- }
75
- ```
76
-
77
- ### Production wiring — `agent-menu.ts`
78
-
79
- `agent-menu.ts` statically imports `wrapTextWithAnsi` from `@earendil-works/pi-tui` and passes it when constructing `ConversationViewer`:
80
-
81
- ```typescript
82
- import { wrapTextWithAnsi } from "@earendil-works/pi-tui";
83
- // …
84
- return new ConversationViewer({
85
- tui, session, record, activity, theme, done, registry,
86
- wrapText: wrapTextWithAnsi,
87
- });
88
- ```
89
-
90
- Adding `wrapText` to `AgentMenuDeps` and threading it through the closure would violate the Law of Demeter — `AgentMenuDeps` has no conceptual ownership of a text-wrapping function.
91
- The `viewAgentConversation` closure is the direct consumer; the import belongs there.
92
-
93
- ### Test strategy
94
-
95
- After DI, tests pass `wrapText` directly in `ConversationViewerOptions`:
96
-
97
- - **"render width safety" tests**: pass `wrapText: wrapTextWithAnsi` (real function, statically imported — no mock).
98
- - **"safety net" tests**: pass a stub `wrapText: () => ["X".repeat(width + 50)]` inline in options — no `vi.mock` needed.
99
- - The "mock is intercepting wrapTextWithAnsi" test is removed (it verified the mock mechanism, not viewer behavior).
100
- - The module-level `wrapOverride` variable and the `vi.mock` block are removed entirely.
101
- - The `await import("@earendil-works/pi-tui")` and `await import("../src/ui/conversation-viewer.js")` dynamic imports are converted to ordinary top-level `import` statements.
102
-
103
- ## Module-Level Changes
104
-
105
- | File | Change |
106
- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
107
- | `src/ui/conversation-viewer.ts` | Add `wrapText` field to `ConversationViewerOptions`; add `private wrapText` field; destructure options in constructor; replace 4× `wrapTextWithAnsi(...)` with `this.wrapText(...)`; remove `wrapTextWithAnsi` from the `@earendil-works/pi-tui` import line |
108
- | `src/ui/agent-menu.ts` | Add `import { wrapTextWithAnsi } from "@earendil-works/pi-tui"`; pass `wrapText: wrapTextWithAnsi` in `viewAgentConversation` |
109
- | `test/conversation-viewer.test.ts` | Convert top-level dynamic `await import()` to static imports; remove `vi.mock`, `wrapOverride`, and "mock is intercepting" test; add `wrapText` to every `new ConversationViewer({…})` call; update safety-net tests to pass inline stub `wrapText` |
110
-
111
- No symbols are removed from exported API (`ConversationViewerOptions`, `ConversationViewer`, `VIEWPORT_HEIGHT_PCT` all remain).
112
- The `wrapText` addition to `ConversationViewerOptions` is a breaking change for any external consumers that construct `ConversationViewer` — check for usages outside this package.
113
-
114
- Grep check: `ConversationViewer` appears only in `src/ui/conversation-viewer.ts`, `src/ui/agent-menu.ts`, and `test/conversation-viewer.test.ts` — no other files construct it.
115
-
116
- ## Test Impact Analysis
117
-
118
- 1. **New unit-test capability**: The safety-net tests can now inject exactly the stub they need without patching a module.
119
- Each test is self-contained and immediately legible — the stub is declared inline at the call site.
120
-
121
- 2. **Tests that become redundant**: The "mock is intercepting wrapTextWithAnsi" test verified the test mechanism, not production behavior.
122
- It is deleted.
123
- The `wrapOverride` reset in `beforeEach` is no longer needed.
124
-
125
- 3. **Tests that stay**: All "render width safety" tests and all overwidth-clamping tests remain; they exercise real viewer behavior with real or controlled inputs.
126
-
127
- ## TDD Order
128
-
129
- ### Cycle 1 — Add `wrapText` field and update production wiring
130
-
131
- 1. **Red**: Update one `new ConversationViewer({…})` in the test to include `wrapText: vi.fn()` — TypeScript rejects the unknown field.
132
- 2. **Green**:
133
- - Add `wrapText: (text: string, width: number) => string[]` to `ConversationViewerOptions`.
134
- - Add `private wrapText: (text: string, width: number) => string[]` field to the class.
135
- - Destructure options in the constructor; assign `this.wrapText = wrapText`.
136
- - Replace all four `wrapTextWithAnsi(...)` calls with `this.wrapText(...)` in `buildContentLines`.
137
- - Remove `wrapTextWithAnsi` from the `@earendil-works/pi-tui` import in `conversation-viewer.ts`.
138
- - In `agent-menu.ts`: add static import of `wrapTextWithAnsi` from `@earendil-works/pi-tui`; pass `wrapText: wrapTextWithAnsi`.
139
- - Update **all** `new ConversationViewer({…})` calls in `conversation-viewer.test.ts` to include `wrapText`.
140
- "Render width safety" tests pass `wrapText: wrapTextWithAnsi` (real function, still imported via the existing `vi.mock` shim for now).
141
- Safety-net tests pass a stub inline: `wrapText: () => ["X".repeat(w + 50)]`.
142
- - Delete the "mock is intercepting wrapTextWithAnsi" test.
143
- 3. **Verify**: `pnpm vitest run test/conversation-viewer.test.ts` passes.
144
- 4. **Commit**: `feat: inject wrapText into ConversationViewer (Phase 9, Step O) (#147)`
145
-
146
- ### Cycle 2 — Remove the module mock
147
-
148
- 1. **Red**: Remove the `vi.mock("@earendil-works/pi-tui", …)` block, the `wrapOverride` variable, and the `beforeEach(() => { wrapOverride = null; })` reset.
149
- Convert `const { visibleWidth } = await import("@earendil-works/pi-tui")` to `import { visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui"`.
150
- Convert `const { ConversationViewer } = await import("../src/ui/conversation-viewer.js")` to `import { ConversationViewer } from "../src/ui/conversation-viewer.js"`.
151
- Run tests — they should still pass (the mock was no longer needed after Cycle 1).
152
- 2. **Green**: Tests pass without any module mock.
153
- 3. **Verify**: `pnpm vitest run test/conversation-viewer.test.ts` and `pnpm run check` both pass.
154
- 4. **Commit**: `refactor: remove vi.mock from conversation-viewer tests (#147)`
155
-
156
- ## Risks and Mitigations
157
-
158
- | Risk | Mitigation |
159
- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
160
- | Missing a `new ConversationViewer({…})` call site in tests | Grep confirms only `test/conversation-viewer.test.ts` constructs the viewer; all instances are in-file |
161
- | TypeScript missing the `private wrapText` field type | Use `pnpm run check` after Cycle 1 to verify no type errors |
162
- | The dynamic `await import()` pattern in tests was necessary for some other reason | The only purpose was to run after `vi.mock` hoisting; once the mock is gone, static imports work fine |
163
-
164
- ## Open Questions
165
-
166
- None — the issue's "Changes" section is unambiguous and the call-site inventory is small.
@@ -1,255 +0,0 @@
1
- ---
2
- issue: 148
3
- issue_title: "Split AgentWidget rendering from lifecycle (Phase 9, Step P)"
4
- ---
5
-
6
- # Split AgentWidget rendering from lifecycle
7
-
8
- ## Problem Statement
9
-
10
- `AgentWidget` (374 lines) mixes rendering, lifecycle management, spinner animation, state filtering, and status bar management in a single class.
11
- `renderWidget` alone is ~109 lines, and `renderFinishedLine` adds another ~40.
12
- The constructor takes 3 concrete collaborators (`AgentManager`, `Map<string, AgentActivityTracker>`, `AgentTypeRegistry`) with no interface extraction.
13
- Rendering logic cannot be unit-tested without instantiating the full widget with its lifecycle machinery.
14
-
15
- ## Goals
16
-
17
- - Extract pure rendering functions from `AgentWidget` into `ui/widget-renderer.ts`.
18
- - Make `AgentWidget` a thin lifecycle/polling wrapper that delegates to pure render functions.
19
- - Enable direct unit testing of rendering logic with plain data — no widget lifecycle, no mocks for `setInterval`/`setWidget`/`requestRender`.
20
-
21
- ## Non-Goals
22
-
23
- - Changing the visual output of the widget (this is a pure refactor).
24
- - Extracting the status bar logic into a separate module (could follow up).
25
- - Narrowing the `AgentManager` dependency to an interface (tracked separately in the architecture doc).
26
- - Injecting `truncateToWidth` (tracked as #147, Step O — an independent track).
27
-
28
- ## Background
29
-
30
- ### Dependency: #144 (Step L) — Consolidate observation model
31
-
32
- Issue #144 is **closed/implemented**.
33
- The renderer now reads stats (`toolUses`, `lifetimeUsage`, `compactionCount`) from `AgentRecord` and live UI state (`activeTools`, `responseText`, `turnCount`, `maxTurns`) from `AgentActivityTracker`.
34
- No dual-counting fallback exists.
35
-
36
- ### Existing pure helpers
37
-
38
- `ui/display.ts` already contains stateless formatting functions (`formatMs`, `formatTurns`, `formatSessionTokens`, `describeActivity`, `getDisplayName`, `getPromptModeLabel`, `SPINNER`, `ERROR_STATUSES`, `Theme`).
39
- The new `widget-renderer.ts` will consume these — it does not duplicate them.
40
-
41
- ### Rendering data flow
42
-
43
- The widget's `renderWidget` currently:
44
-
45
- 1. Calls `this.manager.listAgents()` to get `AgentRecord[]`.
46
- 2. Categorizes into running/queued/finished.
47
- 3. Filters finished agents via `this.shouldShowFinished()`.
48
- 4. Looks up `this.agentActivity.get(a.id)` for live stats.
49
- 5. Calls `this.registry` for display names.
50
- 6. Reads `this.widgetFrame` for spinner animation.
51
- 7. Assembles tree-style lines with overflow logic.
52
-
53
- Steps 3–7 are pure given the right inputs.
54
- Steps 1–2 are also pure categorization.
55
-
56
- ## Design Overview
57
-
58
- ### Separation of concerns
59
-
60
- The rendering extraction splits the widget into two layers:
61
-
62
- 1. **`widget-renderer.ts`** — Pure functions that accept data and return `string[]`.
63
- No `this`, no timers, no SDK types, no side effects.
64
- 2. **`agent-widget.ts`** — Thin lifecycle wrapper that owns timers, UICtx, finished-turn aging, and calls the renderer with live data.
65
-
66
- ### Renderer input shape
67
-
68
- Rather than passing the full `AgentRecord` class (which carries mutation methods and phase collaborators), the renderer receives a plain data slice:
69
-
70
- ```typescript
71
- /** Minimal agent snapshot for rendering — no class methods, no mutation surface. */
72
- export interface WidgetAgent {
73
- readonly id: string;
74
- readonly type: SubagentType;
75
- readonly status: string;
76
- readonly description: string;
77
- readonly toolUses: number;
78
- readonly startedAt: number;
79
- readonly completedAt?: number;
80
- readonly error?: string;
81
- readonly lifetimeUsage?: Readonly<LifetimeUsage>;
82
- readonly compactionCount: number;
83
- }
84
- ```
85
-
86
- This is structurally compatible with `AgentRecord` (the class satisfies it), so no mapping code is needed at the call site — `listAgents()` returns `AgentRecord[]` which satisfies `WidgetAgent[]`.
87
-
88
- ### Renderer input for activity
89
-
90
- Activity state is read from `AgentActivityTracker`.
91
- The renderer needs a read-only view per agent:
92
-
93
- ```typescript
94
- /** Read-only activity snapshot for widget rendering. */
95
- export interface WidgetActivity {
96
- readonly activeTools: ReadonlyMap<string, string>;
97
- readonly responseText: string;
98
- readonly turnCount: number;
99
- readonly maxTurns?: number;
100
- readonly session?: SessionLike;
101
- }
102
- ```
103
-
104
- `AgentActivityTracker` already satisfies this structurally (it exposes these as getters).
105
-
106
- ### Agent config lookup
107
-
108
- The renderer needs `getDisplayName` and `getPromptModeLabel`, which take a `SubagentType` and an `AgentConfigLookup`.
109
- The renderer accepts `AgentConfigLookup` (the existing interface from `agent-types.ts`) — not the concrete `AgentTypeRegistry` class.
110
-
111
- ### Renderer API
112
-
113
- ```typescript
114
- /** Pure rendering of the widget body. Returns lines to display. */
115
- export function renderWidgetLines(params: {
116
- agents: readonly WidgetAgent[];
117
- activityMap: ReadonlyMap<string, WidgetActivity>;
118
- registry: AgentConfigLookup;
119
- spinnerFrame: number;
120
- terminalWidth: number;
121
- shouldShowFinished: (agentId: string, status: string) => boolean;
122
- }): string[];
123
-
124
- /** Pure rendering of a single finished agent line (no tree connector prefix). */
125
- export function renderFinishedLine(
126
- agent: WidgetAgent,
127
- activity: WidgetActivity | undefined,
128
- registry: AgentConfigLookup,
129
- theme: Theme,
130
- ): string;
131
-
132
- /** Pure rendering of a single running agent (header + activity lines, no tree connector prefix). */
133
- export function renderRunningLines(
134
- agent: WidgetAgent,
135
- activity: WidgetActivity | undefined,
136
- registry: AgentConfigLookup,
137
- spinnerFrame: number,
138
- theme: Theme,
139
- ): [header: string, activity: string];
140
- ```
141
-
142
- The top-level `renderWidgetLines` encapsulates the full categorization, overflow logic, and tree-connector fixup.
143
- The per-agent functions are exported for fine-grained testing.
144
-
145
- The `shouldShowFinished` callback is injected rather than re-implementing the aging logic inside the renderer, keeping the renderer pure and the aging state in the widget.
146
-
147
- ### Call site in AgentWidget
148
-
149
- ```typescript
150
- // Inside renderWidget(tui, theme):
151
- const w = tui.terminal.columns;
152
- return renderWidgetLines({
153
- agents: this.manager.listAgents(),
154
- activityMap: this.agentActivity,
155
- registry: this.registry,
156
- spinnerFrame: this.widgetFrame,
157
- terminalWidth: w,
158
- shouldShowFinished: (id, status) => this.shouldShowFinished(id, status),
159
- });
160
- ```
161
-
162
- The widget's `renderWidget` method shrinks to ~5 lines.
163
-
164
- ### Tell-Don't-Ask verification
165
-
166
- The renderer receives pre-collected data and returns formatted strings.
167
- It does not reach through collaborators — it reads flat fields from `WidgetAgent` and `WidgetActivity`.
168
- The widget tells the renderer "render this data"; the renderer returns lines.
169
- No Law of Demeter violations.
170
-
171
- ## Module-Level Changes
172
-
173
- ### New file: `src/ui/widget-renderer.ts`
174
-
175
- - `WidgetAgent` interface (structural subset of `AgentRecord`).
176
- - `WidgetActivity` interface (structural subset of `AgentActivityTracker`).
177
- - `renderWidgetLines()` — top-level rendering with categorization, overflow, tree connectors.
178
- - `renderFinishedLine()` — single finished-agent line.
179
- - `renderRunningLines()` — single running-agent header + activity pair.
180
- - Imports from `display.ts` (`SPINNER`, `ERROR_STATUSES`, `formatMs`, `formatTurns`, `formatSessionTokens`, `describeActivity`, `getDisplayName`, `getPromptModeLabel`, `Theme`), from `usage.ts` (`getLifetimeTotal`, `getSessionContextPercent`, `LifetimeUsage`, `SessionLike`), and from `@earendil-works/pi-tui` (`truncateToWidth`).
181
-
182
- ### Modified: `src/ui/agent-widget.ts`
183
-
184
- - Remove `renderWidget()` method body — replace with call to `renderWidgetLines()`.
185
- - Remove `renderFinishedLine()` method entirely.
186
- - Remove direct imports of display helpers and usage helpers that are now only consumed by `widget-renderer.ts`.
187
- - Keep: constructor, `setUICtx`, `onTurnStart`, `ensureTimer`, `shouldShowFinished`, `markFinished`, `update`, `dispose`, `UICtx` type, `MAX_WIDGET_LINES`.
188
- - The inline type on `renderFinishedLine`'s parameter `a` is replaced by the `WidgetAgent` import.
189
-
190
- ### New file: `test/widget-renderer.test.ts`
191
-
192
- - Unit tests for `renderWidgetLines`, `renderFinishedLine`, `renderRunningLines`.
193
- - Uses plain data objects (no mocks for `AgentManager`, `setInterval`, or SDK).
194
- - Stub `Theme` matching the pattern in `test/renderer.test.ts`.
195
-
196
- ### No changes to
197
-
198
- - `src/index.ts` — the widget is constructed the same way; renderer is internal to the widget module.
199
- - `src/ui/display.ts` — unchanged; consumed by the new renderer.
200
- - `src/usage.ts` — unchanged.
201
-
202
- ## Test Impact Analysis
203
-
204
- 1. The extraction enables direct unit testing of widget rendering that was previously impossible — testing `renderWidget` required constructing a full `AgentWidget` with mocked `AgentManager`, fake timers, and a stubbed UICtx.
205
- The new tests cover: finished-agent line formatting (all status variants), running-agent header/activity rendering, overflow logic, tree-connector fixup, empty-state handling, and `shouldShowFinished` filtering.
206
- 2. No existing tests become redundant — there are currently **no** unit tests for `AgentWidget` rendering.
207
- The existing `display.test.ts` tests lower-level formatters and remains as-is.
208
- 3. `renderer.test.ts` tests the notification renderer — unrelated, stays as-is.
209
-
210
- ## TDD Order
211
-
212
- 1. **Red → Green:** Test `renderFinishedLine` for a completed agent (success icon, stats, duration).
213
- Commit: `test: add renderFinishedLine tests for completed status`
214
-
215
- 2. **Red → Green:** Test `renderFinishedLine` for error/aborted/steered/stopped statuses (icon and status text variations).
216
- Commit: `test: renderFinishedLine error and terminal status variants`
217
-
218
- 3. **Red → Green:** Test `renderRunningLines` (spinner frame, stats, activity description, token display).
219
- Commit: `test: add renderRunningLines tests`
220
-
221
- 4. **Red → Green:** Test `renderWidgetLines` — basic case with one running agent (heading, tree connectors).
222
- Commit: `test: renderWidgetLines single running agent`
223
-
224
- 5. **Red → Green:** Test `renderWidgetLines` — mixed running + finished + queued, verifying categorization and ordering.
225
- Commit: `test: renderWidgetLines mixed agent states`
226
-
227
- 6. **Red → Green:** Test `renderWidgetLines` — overflow cap with many agents, verifying the priority (running > queued > finished) and overflow summary line.
228
- Commit: `test: renderWidgetLines overflow behavior`
229
-
230
- 7. **Red → Green:** Test `renderWidgetLines` — empty state returns `[]`; finished-only state uses dim heading.
231
- Commit: `test: renderWidgetLines empty and finished-only states`
232
-
233
- 8. **Green → Refactor:** Extract `renderFinishedLine`, `renderRunningLines`, and `renderWidgetLines` into `src/ui/widget-renderer.ts`.
234
- All tests pass against the extracted module.
235
- Commit: `refactor: extract widget rendering into widget-renderer`
236
-
237
- 9. **Green → Refactor:** Wire `AgentWidget.renderWidget()` to delegate to `renderWidgetLines()`.
238
- Remove the inlined rendering logic from `agent-widget.ts`.
239
- Remove unused imports.
240
- Commit: `refactor: AgentWidget delegates rendering to widget-renderer`
241
-
242
- 10. **Verify:** Run full test suite (`pnpm vitest run`) and type check (`pnpm run check`).
243
- Commit: none (verification only).
244
-
245
- ## Risks and Mitigations
246
-
247
- | Risk | Mitigation |
248
- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
249
- | Structural compatibility between `AgentRecord` and `WidgetAgent` could drift if `AgentRecord` renames a field. | TypeScript's structural checking catches this at the call site in `agent-widget.ts` — `listAgents()` returns `AgentRecord[]` which must satisfy `readonly WidgetAgent[]`. |
250
- | `truncateToWidth` is an external dependency (`@earendil-works/pi-tui`) in the renderer. | Step O (#147) will inject it; for now, the renderer imports it directly, matching the current widget behavior. |
251
- | Overflow logic is complex and hand-tested — extraction could introduce subtle line-count bugs. | TDD steps 4–7 exercise overflow edge cases before the extraction step. The extraction is a mechanical move with tests already passing. |
252
-
253
- ## Open Questions
254
-
255
- - None — the design follows the architecture doc's Step P specification and the dependency (#144) is already implemented.
@@ -1,91 +0,0 @@
1
- ---
2
- issue: 152
3
- issue_title: "Add promptSnippet to pi-subagents tools"
4
- ---
5
-
6
- # Add `promptSnippet` to pi-subagents tools
7
-
8
- ## Problem Statement
9
-
10
- The `Agent`, `get_subagent_result`, and `steer_subagent` tools are the only tools across the monorepo that lack `promptSnippet`.
11
- Pi's `buildSystemPrompt` uses `promptSnippet` to build a concise tool summary in the system prompt.
12
- Without it, these tools rely entirely on their `description` field for model guidance.
13
- The `Agent` tool's description is especially long (embeds full usage guidelines), so a short snippet would give the model a better quick-reference view.
14
-
15
- ## Goals
16
-
17
- - Add `promptSnippet` to each of the three tool registrations in pi-subagents.
18
- - Match the established `"<toolName>: <one-liner>"` format used by pi-github-tools and pi-colgrep.
19
-
20
- ## Non-Goals
21
-
22
- - Changing `description`, `promptGuidelines`, or any other tool registration field.
23
- - Adding `promptSnippet` to tools in other packages (already done).
24
-
25
- ## Background
26
-
27
- Sibling packages pi-github-tools and pi-colgrep already provide `promptSnippet` on every tool.
28
- The convention is a single string in the form `"tool_name: Short imperative description."`.
29
- For example: `"ci_list: List recent CI runs for a workflow."`.
30
-
31
- The three tool factories live in:
32
-
33
- | Factory | File |
34
- | --------------------- | ------------------------------ |
35
- | `createAgentTool` | `src/tools/agent-tool.ts` |
36
- | `createGetResultTool` | `src/tools/get-result-tool.ts` |
37
- | `createSteerTool` | `src/tools/steer-tool.ts` |
38
-
39
- Each factory returns a plain object with `name`, `label`, `description`, `parameters`, and `execute`.
40
- Adding `promptSnippet` is a single property addition per factory.
41
-
42
- ## Design Overview
43
-
44
- No structural change — this is a property addition to three existing object literals.
45
-
46
- Proposed snippets:
47
-
48
- - **Agent** — `"Agent: Launch a specialized agent for complex, multi-step tasks."`
49
- - **get_subagent_result** — `"get_subagent_result: Check status and retrieve results from a background agent."`
50
- - **steer_subagent** — `"steer_subagent: Send a mid-run message to redirect a running background agent."`
51
-
52
- These are the exact phrasings from the issue.
53
- Exact wording may be refined during implementation.
54
-
55
- ## Module-Level Changes
56
-
57
- ### `src/tools/agent-tool.ts`
58
-
59
- Add `promptSnippet` property to the object returned by `createAgentTool`, after `label`.
60
-
61
- ### `src/tools/get-result-tool.ts`
62
-
63
- Add `promptSnippet` property to the object returned by `createGetResultTool`, after `label`.
64
-
65
- ### `src/tools/steer-tool.ts`
66
-
67
- Add `promptSnippet` property to the object returned by `createSteerTool`, after `label`.
68
-
69
- ## Test Impact Analysis
70
-
71
- Existing tool-definition tests (`test/tools/agent-tool.test.ts`, `get-result-tool.test.ts`, `steer-tool.test.ts`) assert `name`, `label`, and `description` but not `promptSnippet`.
72
- New assertions will verify the property exists with the expected value.
73
- No existing tests need modification — the new property is additive.
74
-
75
- ## TDD Order
76
-
77
- 1. **Red → Green:** Add `promptSnippet` assertions to the tool-definition tests for all three tools, then add the `promptSnippet` property to each factory.
78
- Commit: `feat: add promptSnippet to Agent, get_subagent_result, and steer_subagent (#152)`
79
-
80
- This is a single-cycle change — one test step, one implementation step, one commit.
81
-
82
- ## Risks and Mitigations
83
-
84
- | Risk | Mitigation |
85
- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
86
- | Snippet wording doesn't match what Pi displays well | The snippets mirror the first sentence of each tool's `description`; can be tweaked in a follow-up without breaking anything. |
87
- | SDK `defineTool` doesn't pass through `promptSnippet` | Sibling packages already use it successfully, confirming SDK support. |
88
-
89
- ## Open Questions
90
-
91
- None.