@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.
- package/CHANGELOG.md +15 -0
- package/docs/architecture/architecture.md +165 -203
- package/docs/architecture/history/phase-19-implement-ui-decisions.md +282 -0
- package/package.json +6 -7
- package/src/config/default-agents.ts +3 -0
- package/src/lifecycle/subagent.ts +25 -14
- package/src/observation/notification.ts +23 -10
- package/src/observation/subagent-events-observer.ts +1 -3
- package/src/runtime.ts +2 -1
- package/src/service/service-adapter.ts +20 -17
- package/src/session/model-resolver.ts +31 -30
- package/src/tools/agent-tool.ts +17 -13
- package/src/tools/get-result-report.ts +60 -0
- package/src/tools/get-result-tool.ts +25 -40
- package/src/tools/helpers.ts +21 -5
- package/src/tools/spawn-config.ts +5 -5
- package/src/tools/steer-tool.ts +37 -27
- package/src/types.ts +4 -1
- package/src/ui/session-navigator.ts +0 -2
- package/.prettierignore +0 -5
- package/AGENTS.md +0 -7
- package/docs/plans/0048-implement-subagents-api.md +0 -304
- package/docs/plans/0049-remove-group-join-output-file-rpc.md +0 -180
- package/docs/plans/0051-update-adr-0001-hard-fork.md +0 -77
- package/docs/plans/0052-remove-scheduled-subagents.md +0 -133
- package/docs/plans/0053-extract-model-resolution-from-execute.md +0 -181
- package/docs/plans/0054-decompose-index-into-modules.md +0 -302
- package/docs/plans/0057-structured-debug-logging.md +0 -154
- package/docs/plans/0061-session-format-transcript.md +0 -284
- package/docs/plans/0066-replace-as-any-with-sdk-types.md +0 -215
- package/docs/plans/0069-create-subagent-runtime.md +0 -345
- package/docs/plans/0070-extract-event-handlers.md +0 -306
- package/docs/plans/0071-extract-session-config-assembler.md +0 -362
- package/docs/plans/0072-inject-agent-manager-collaborators.md +0 -329
- package/docs/plans/0076-inject-cwd-into-agent-manager.md +0 -102
- package/docs/plans/0077-inject-project-agents-dir.md +0 -115
- package/docs/plans/0080-consolidate-agent-config-lookup.md +0 -247
- package/docs/plans/0084-extract-git-worktree-manager.md +0 -142
- package/docs/plans/0087-evolve-subagent-runtime-methods.md +0 -240
- package/docs/plans/0098-extract-agent-record-state-machine.md +0 -435
- package/docs/plans/0099-replace-ctx-with-parent-snapshot.md +0 -488
- package/docs/plans/0100-replace-callback-threading-with-session-subscription.md +0 -454
- package/docs/plans/0102-consolidate-test-record-factory.md +0 -176
- package/docs/plans/0108-extract-agent-type-registry.md +0 -322
- package/docs/plans/0109-extract-settings-manager.md +0 -276
- package/docs/plans/0110-agent-activity-tracker.md +0 -297
- package/docs/plans/0111-split-agent-record-lifecycle.md +0 -582
- package/docs/plans/0112-replace-agent-manager-callbacks.md +0 -241
- package/docs/plans/0113-disambiguate-spawn-options.md +0 -155
- package/docs/plans/0114-narrow-agent-tool-menu-deps.md +0 -279
- package/docs/plans/0115-decompose-agent-tool.md +0 -337
- package/docs/plans/0116-type-housekeeping.md +0 -351
- package/docs/plans/0118-settings-manager-apply-methods.md +0 -271
- package/docs/plans/0123-remove-vi-fn-cast-smell.md +0 -179
- package/docs/plans/0131-consolidate-shared-test-fixtures.md +0 -207
- package/docs/plans/0132-inject-io-into-session-config.md +0 -219
- package/docs/plans/0133-inject-sdk-boundary-into-agent-runner.md +0 -373
- package/docs/plans/0134-reduce-as-any-casts.md +0 -366
- package/docs/plans/0135-extract-display-helpers.md +0 -182
- package/docs/plans/0136-decompose-agent-menu.md +0 -300
- package/docs/plans/0144-consolidate-observation-model.md +0 -263
- package/docs/plans/0145-decompose-execute-push-ctx-to-boundary.md +0 -290
- package/docs/plans/0146-narrow-ui-context.md +0 -319
- package/docs/plans/0147-inject-wrap-text-into-conversation-viewer.md +0 -166
- package/docs/plans/0148-split-agent-widget-rendering.md +0 -255
- package/docs/plans/0152-add-prompt-snippet.md +0 -91
- package/docs/plans/0164-reorganize-into-domain-directories.md +0 -409
- package/docs/plans/0165-decompose-resolved-spawn-config.md +0 -157
- package/docs/plans/0166-extract-parent-session-info.md +0 -231
- package/docs/plans/0167-narrow-runner-io.md +0 -150
- package/docs/plans/0168-extract-tool-filter-config.md +0 -173
- package/docs/plans/0169-extract-run-context-from-run-options.md +0 -194
- package/docs/plans/0170-reduce-build-content-lines-complexity.md +0 -225
- package/docs/plans/0171-reduce-render-result-complexity.md +0 -200
- package/docs/plans/0172-extract-turn-formatting.md +0 -206
- package/docs/plans/0180-reorder-append-prompt-for-kv-cache.md +0 -100
- package/docs/plans/0185-remove-persistent-agent-memory.md +0 -161
- package/docs/plans/0188-replace-any-casts-with-sdk-types.md +0 -162
- package/docs/plans/0192-define-session-context-interface.md +0 -107
- package/docs/plans/0193-runtime-owns-context-queries.md +0 -245
- package/docs/plans/0194-align-tool-interfaces-for-structural-typing.md +0 -139
- package/docs/plans/0195-convert-tool-factories-to-classes.md +0 -264
- package/docs/plans/0196-convert-runner-menu-to-classes.md +0 -268
- package/docs/plans/0205-decompose-render-widget-lines.md +0 -140
- package/docs/plans/0206-decompose-show-agent-detail.md +0 -211
- package/docs/plans/0207-decompose-agent-widget-update.md +0 -242
- package/docs/plans/0208-extract-shared-test-fixtures.md +0 -298
- package/docs/plans/0214-convert-remaining-closure-factories-to-classes.md +0 -261
- package/docs/plans/0215-decompose-build-parent-context.md +0 -166
- package/docs/plans/0216-decompose-start-agent.md +0 -255
- package/docs/plans/0217-extract-overwrite-guard.md +0 -176
- package/docs/plans/0218-push-sdk-boundary-in-settings.md +0 -172
- package/docs/plans/0219-reduce-test-duplication-top-3-clone-families.md +0 -162
- package/docs/plans/0227-evolve-agent-record-into-agent.md +0 -322
- package/docs/plans/0228-async-start-agent-dissolve-run-handle.md +0 -288
- package/docs/plans/0229-agent-born-complete.md +0 -564
- package/docs/plans/0230-extract-concurrency-queue.md +0 -265
- package/docs/plans/0231-push-exec-registry-to-runner.md +0 -245
- package/docs/plans/0232-agent-resume-internal-observer-lifecycle.md +0 -180
- package/docs/plans/0237-remove-disallowed-tools.md +0 -180
- package/docs/plans/0238-remove-extensions-filtering.md +0 -191
- package/docs/plans/0239-collapse-filter-active-tools.md +0 -217
- package/docs/plans/0242-rename-agent-tool-to-subagent.md +0 -165
- package/docs/plans/0256-extract-worktree-isolation.md +0 -256
- package/docs/plans/0257-extract-child-session-factory.md +0 -285
- package/docs/plans/0262-add-workspace-provider-seam.md +0 -264
- package/docs/plans/0264-remove-extension-lifecycle-control.md +0 -277
- package/docs/plans/0265-born-complete-subagent-session.md +0 -333
- package/docs/plans/0270-type-consumable-public-surface.md +0 -204
- package/docs/plans/0272-export-workspace-collaborator-types.md +0 -147
- package/docs/plans/0277-encapsulate-agent-session.md +0 -304
- package/docs/plans/0280-rename-agent-to-subagent.md +0 -197
- package/docs/plans/0360-custom-agents-default-append.md +0 -132
- package/docs/plans/0373-extract-subagent-state.md +0 -250
- package/docs/plans/0374-encapsulate-subagent-start-notification.md +0 -268
- package/docs/plans/0375-extract-run-listener-workspace-bracket.md +0 -300
- package/docs/plans/0376-extract-manager-observer.md +0 -232
- package/docs/plans/0377-split-widget-delegation-from-runtime.md +0 -254
- package/docs/plans/0378-consolidate-lifecycle-test-fixtures.md +0 -243
- package/docs/plans/0379-consolidate-ui-tools-test-fixtures.md +0 -335
- package/docs/plans/0380-extract-layered-settings-loader.md +0 -223
- package/docs/plans/0381-replace-concurrency-queue-with-limiter.md +0 -267
- package/docs/plans/0400-include-parent-prompt-in-replace-mode.md +0 -199
- package/docs/plans/0403-abort-subagents-on-interrupt.md +0 -180
- package/docs/plans/0412-unify-session-mock-builders.md +0 -146
- package/docs/plans/0420-fold-run-metrics-live-activity-onto-record.md +0 -228
- package/docs/plans/0421-migrate-activity-readers-to-record-getters.md +0 -309
- package/docs/plans/0422-delete-activity-tracker-ui-observer.md +0 -204
- package/docs/plans/0423-widget-self-drive-from-lifecycle.md +0 -264
- package/docs/plans/0424-drop-widget-dep-from-subagent-tool.md +0 -166
- package/docs/plans/0425-reconcile-subagent-events-contract.md +0 -144
- package/docs/plans/0426-consolidate-residual-test-clone-families.md +0 -235
- package/docs/plans/0427-reconsider-ui-direction.md +0 -212
- package/docs/plans/0441-remove-agent-definition-management-subtree.md +0 -180
- package/docs/plans/0442-dissolve-agents-conversation-viewer.md +0 -195
- package/docs/plans/0443-consolidate-remaining-test-clone-families.md +0 -268
- package/docs/plans/0444-shrink-widget-to-background-agents.md +0 -156
- package/docs/plans/0445-native-session-navigation.md +0 -365
- package/docs/plans/0446-spike-session-navigation-entry-criteria.md +0 -171
- package/docs/plans/0447-extract-subagents-settings-command.md +0 -220
- package/docs/plans/0448-block-disabled-agent-spawn.md +0 -207
- package/docs/plans/0462-navigation-renderer-tui-components.md +0 -338
- package/docs/plans/0463-file-snapshot-source-evicted-agents.md +0 -306
- package/docs/plans/0470-refresh-readme-command-surface.md +0 -159
- package/docs/retro/0048-implement-subagents-api.md +0 -44
- package/docs/retro/0049-remove-group-join-output-file-rpc.md +0 -49
- package/docs/retro/0051-update-adr-0001-hard-fork.md +0 -39
- package/docs/retro/0053-extract-model-resolution-from-execute.md +0 -40
- package/docs/retro/0054-decompose-index-into-modules.md +0 -53
- package/docs/retro/0057-structured-debug-logging.md +0 -77
- package/docs/retro/0061-session-format-transcript.md +0 -41
- package/docs/retro/0066-replace-as-any-with-sdk-types.md +0 -44
- package/docs/retro/0069-create-subagent-runtime.md +0 -43
- package/docs/retro/0070-extract-event-handlers.md +0 -49
- package/docs/retro/0071-extract-session-config-assembler.md +0 -60
- package/docs/retro/0072-inject-agent-manager-collaborators.md +0 -46
- package/docs/retro/0076-inject-cwd-into-agent-manager.md +0 -35
- package/docs/retro/0077-inject-project-agents-dir.md +0 -33
- package/docs/retro/0080-consolidate-agent-config-lookup.md +0 -35
- package/docs/retro/0084-extract-git-worktree-manager.md +0 -37
- package/docs/retro/0087-evolve-subagent-runtime-methods.md +0 -42
- package/docs/retro/0098-extract-agent-record-state-machine.md +0 -46
- package/docs/retro/0099-replace-ctx-with-parent-snapshot.md +0 -37
- package/docs/retro/0100-replace-callback-threading-with-session-subscription.md +0 -36
- package/docs/retro/0102-consolidate-test-record-factory.md +0 -30
- package/docs/retro/0108-extract-agent-type-registry.md +0 -41
- package/docs/retro/0109-extract-settings-manager.md +0 -55
- package/docs/retro/0110-agent-activity-tracker.md +0 -44
- package/docs/retro/0111-split-agent-record-lifecycle.md +0 -61
- package/docs/retro/0112-replace-agent-manager-callbacks.md +0 -35
- package/docs/retro/0113-disambiguate-spawn-options.md +0 -29
- package/docs/retro/0114-narrow-agent-tool-menu-deps.md +0 -38
- package/docs/retro/0115-decompose-agent-tool.md +0 -51
- package/docs/retro/0116-type-housekeeping.md +0 -42
- package/docs/retro/0118-settings-manager-apply-methods.md +0 -40
- package/docs/retro/0123-remove-vi-fn-cast-smell.md +0 -49
- package/docs/retro/0131-consolidate-shared-test-fixtures.md +0 -46
- package/docs/retro/0132-inject-io-into-session-config.md +0 -33
- package/docs/retro/0133-inject-sdk-boundary-into-agent-runner.md +0 -45
- package/docs/retro/0134-reduce-as-any-casts.md +0 -56
- package/docs/retro/0135-extract-display-helpers.md +0 -38
- package/docs/retro/0136-decompose-agent-menu.md +0 -43
- package/docs/retro/0144-consolidate-observation-model.md +0 -39
- package/docs/retro/0145-decompose-execute-push-ctx-to-boundary.md +0 -56
- package/docs/retro/0146-narrow-ui-context.md +0 -70
- package/docs/retro/0147-inject-wrap-text-into-conversation-viewer.md +0 -90
- package/docs/retro/0148-split-agent-widget-rendering.md +0 -39
- package/docs/retro/0152-add-prompt-snippet.md +0 -34
- package/docs/retro/0164-reorganize-into-domain-directories.md +0 -82
- package/docs/retro/0165-decompose-resolved-spawn-config.md +0 -78
- package/docs/retro/0166-extract-parent-session-info.md +0 -66
- package/docs/retro/0167-narrow-runner-io.md +0 -63
- package/docs/retro/0168-extract-tool-filter-config.md +0 -76
- package/docs/retro/0169-extract-run-context-from-run-options.md +0 -68
- package/docs/retro/0170-reduce-build-content-lines-complexity.md +0 -72
- package/docs/retro/0171-reduce-render-result-complexity.md +0 -77
- package/docs/retro/0172-extract-turn-formatting.md +0 -80
- package/docs/retro/0180-reorder-append-prompt-for-kv-cache.md +0 -62
- package/docs/retro/0185-remove-persistent-agent-memory.md +0 -73
- package/docs/retro/0188-replace-any-casts-with-sdk-types.md +0 -69
- package/docs/retro/0192-define-session-context-interface.md +0 -59
- package/docs/retro/0193-runtime-owns-context-queries.md +0 -75
- package/docs/retro/0194-align-tool-interfaces-for-structural-typing.md +0 -62
- package/docs/retro/0195-convert-tool-factories-to-classes.md +0 -84
- package/docs/retro/0196-convert-runner-menu-to-classes.md +0 -73
- package/docs/retro/0205-decompose-render-widget-lines.md +0 -64
- package/docs/retro/0206-decompose-show-agent-detail.md +0 -67
- package/docs/retro/0207-decompose-agent-widget-update.md +0 -92
- package/docs/retro/0208-extract-shared-test-fixtures.md +0 -102
- package/docs/retro/0214-convert-remaining-closure-factories-to-classes.md +0 -66
- package/docs/retro/0215-decompose-build-parent-context.md +0 -61
- package/docs/retro/0216-decompose-start-agent.md +0 -80
- package/docs/retro/0217-extract-overwrite-guard.md +0 -63
- package/docs/retro/0218-push-sdk-boundary-in-settings.md +0 -72
- package/docs/retro/0219-reduce-test-duplication-top-3-clone-families.md +0 -64
- package/docs/retro/0227-evolve-agent-record-into-agent.md +0 -80
- package/docs/retro/0228-async-start-agent-dissolve-run-handle.md +0 -80
- package/docs/retro/0229-agent-born-complete.md +0 -89
- package/docs/retro/0230-extract-concurrency-queue.md +0 -38
- package/docs/retro/0231-push-exec-registry-to-runner.md +0 -71
- package/docs/retro/0232-agent-resume-internal-observer-lifecycle.md +0 -109
- package/docs/retro/0237-remove-disallowed-tools.md +0 -78
- package/docs/retro/0238-remove-extensions-filtering.md +0 -72
- package/docs/retro/0239-collapse-filter-active-tools.md +0 -70
- package/docs/retro/0242-rename-agent-tool-to-subagent.md +0 -82
- package/docs/retro/0256-extract-worktree-isolation.md +0 -89
- package/docs/retro/0257-extract-child-session-factory.md +0 -33
- package/docs/retro/0262-add-workspace-provider-seam.md +0 -89
- package/docs/retro/0264-remove-extension-lifecycle-control.md +0 -91
- package/docs/retro/0265-born-complete-subagent-session.md +0 -97
- package/docs/retro/0270-type-consumable-public-surface.md +0 -108
- package/docs/retro/0272-export-workspace-collaborator-types.md +0 -38
- package/docs/retro/0277-encapsulate-agent-session.md +0 -80
- package/docs/retro/0280-rename-agent-to-subagent.md +0 -96
- package/docs/retro/0360-custom-agents-default-append.md +0 -81
- package/docs/retro/0373-extract-subagent-state.md +0 -94
- package/docs/retro/0374-encapsulate-subagent-start-notification.md +0 -171
- package/docs/retro/0375-extract-run-listener-workspace-bracket.md +0 -104
- package/docs/retro/0376-extract-manager-observer.md +0 -81
- package/docs/retro/0377-split-widget-delegation-from-runtime.md +0 -105
- package/docs/retro/0378-consolidate-lifecycle-test-fixtures.md +0 -100
- package/docs/retro/0379-consolidate-ui-tools-test-fixtures.md +0 -52
- package/docs/retro/0380-extract-layered-settings-loader.md +0 -97
- package/docs/retro/0381-replace-concurrency-queue-with-limiter.md +0 -95
- package/docs/retro/0400-include-parent-prompt-in-replace-mode.md +0 -84
- package/docs/retro/0403-abort-subagents-on-interrupt.md +0 -90
- package/docs/retro/0412-unify-session-mock-builders.md +0 -80
- package/docs/retro/0420-fold-run-metrics-live-activity-onto-record.md +0 -90
- package/docs/retro/0421-migrate-activity-readers-to-record-getters.md +0 -105
- package/docs/retro/0422-delete-activity-tracker-ui-observer.md +0 -97
- package/docs/retro/0423-widget-self-drive-from-lifecycle.md +0 -112
- package/docs/retro/0424-drop-widget-dep-from-subagent-tool.md +0 -89
- package/docs/retro/0425-reconcile-subagent-events-contract.md +0 -101
- package/docs/retro/0426-consolidate-residual-test-clone-families.md +0 -100
- package/docs/retro/0427-reconsider-ui-direction.md +0 -102
- package/docs/retro/0441-remove-agent-definition-management-subtree.md +0 -97
- package/docs/retro/0442-dissolve-agents-conversation-viewer.md +0 -108
- package/docs/retro/0443-consolidate-remaining-test-clone-families.md +0 -28
- package/docs/retro/0444-shrink-widget-to-background-agents.md +0 -81
- package/docs/retro/0445-native-session-navigation.md +0 -122
- package/docs/retro/0446-spike-session-navigation-entry-criteria.md +0 -99
- package/docs/retro/0447-extract-subagents-settings-command.md +0 -91
- package/docs/retro/0448-block-disabled-agent-spawn.md +0 -75
- package/docs/retro/0462-navigation-renderer-tui-components.md +0 -105
- package/docs/retro/0463-file-snapshot-source-evicted-agents.md +0 -103
- package/docs/retro/0470-refresh-readme-command-surface.md +0 -40
- package/src/observation/notification-state.ts +0 -27
- package/vitest.config.ts +0 -14
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 112
|
|
3
|
-
issue_title: "refactor(pi-subagents): replace AgentManager callbacks with observer interface"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Replace AgentManager callbacks with observer interface
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
`AgentManagerOptions` accepts three fire-and-forget callbacks — `onStart`, `onComplete`, `onCompact` — that `index.ts` wires as closure lambdas capturing `runtime`, `pi`, `notifications`, and other extension state.
|
|
11
|
-
This is the same callback-threading pattern that was replaced with direct session subscriptions in #100, but one level up.
|
|
12
|
-
The callbacks are notification-style (fire-and-forget, no return value) and match the observer pattern exactly.
|
|
13
|
-
|
|
14
|
-
## Goals
|
|
15
|
-
|
|
16
|
-
- Replace the three callback parameters on `AgentManagerOptions` with a single `observer?: AgentManagerObserver` interface.
|
|
17
|
-
- `index.ts` constructs one observer object instead of three independent closure lambdas.
|
|
18
|
-
- `AgentManagerOptions` shrinks by two net fields (remove 3 callbacks, add 1 observer).
|
|
19
|
-
- Preserve all existing behavior: lifecycle events, record persistence, notification dispatch, compaction events.
|
|
20
|
-
- Non-breaking refactor — no public API changes (the callbacks are internal to the package).
|
|
21
|
-
|
|
22
|
-
## Non-Goals
|
|
23
|
-
|
|
24
|
-
- Extracting the observer implementation from `index.ts` into its own module — that can follow if the object grows.
|
|
25
|
-
- Changing `RecordObserverOptions` (session-level observer) — it remains a separate concern at a different layer.
|
|
26
|
-
- Narrowing `AgentToolDeps` or `AgentMenuDeps` — tracked in #114.
|
|
27
|
-
- Disambiguating `SpawnOptions` — tracked in #113.
|
|
28
|
-
|
|
29
|
-
## Background
|
|
30
|
-
|
|
31
|
-
### Current callback wiring
|
|
32
|
-
|
|
33
|
-
`agent-manager.ts` defines three callback type aliases and stores them as private fields:
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
export type OnAgentStart = (record: AgentRecord) => void;
|
|
37
|
-
export type OnAgentComplete = (record: AgentRecord) => void;
|
|
38
|
-
export type OnAgentCompact = (record: AgentRecord, info: CompactionInfo) => void;
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
`AgentManager` invokes them at three points:
|
|
42
|
-
|
|
43
|
-
1. `onStart` — called in `startAgent()` after `record.markRunning()`.
|
|
44
|
-
2. `onComplete` — called in `startAgent()`'s `.then()` and `.catch()` handlers for background agents, and in `drainQueue()` on late failure.
|
|
45
|
-
3. `onCompact` — relayed through `subscribeRecordObserver()` → `RecordObserverOptions.onCompact`.
|
|
46
|
-
|
|
47
|
-
`index.ts` builds ~30 lines of closure lambdas (lines 73–116) that capture `pi`, `notifications`, and `buildEventData`.
|
|
48
|
-
|
|
49
|
-
### Observer pattern already established
|
|
50
|
-
|
|
51
|
-
`record-observer.ts` and `ui/ui-observer.ts` are session-level observers that subscribe directly to session events.
|
|
52
|
-
This refactoring applies the same principle at the manager level — grouping related notification callbacks into a single interface.
|
|
53
|
-
|
|
54
|
-
### Dependency: issue #111 (AgentRecord lifecycle split)
|
|
55
|
-
|
|
56
|
-
Issue #111 is closed.
|
|
57
|
-
The observer interface is designed against the current record shape, which reflects the post-#111 lifecycle split.
|
|
58
|
-
|
|
59
|
-
### Architecture reference
|
|
60
|
-
|
|
61
|
-
Phase 7, Step C in `docs/architecture/architecture.md`.
|
|
62
|
-
|
|
63
|
-
## Design Overview
|
|
64
|
-
|
|
65
|
-
### Observer interface
|
|
66
|
-
|
|
67
|
-
```typescript
|
|
68
|
-
export interface AgentManagerObserver {
|
|
69
|
-
onAgentStarted(record: AgentRecord): void;
|
|
70
|
-
onAgentCompleted(record: AgentRecord): void;
|
|
71
|
-
onAgentCompacted(record: AgentRecord, info: CompactionInfo): void;
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
All three methods are fire-and-forget (void return, no async).
|
|
76
|
-
The interface uses past-tense naming (`Started`, `Completed`, `Compacted`) to signal that these are after-the-fact notifications, not hooks that influence the operation.
|
|
77
|
-
|
|
78
|
-
### `AgentManagerOptions` change
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
export interface AgentManagerOptions {
|
|
82
|
-
runner: AgentRunner;
|
|
83
|
-
worktrees: WorktreeManager;
|
|
84
|
-
exec: ShellExec;
|
|
85
|
-
registry: AgentTypeRegistry;
|
|
86
|
-
getMaxConcurrent?: () => number;
|
|
87
|
-
getRunConfig?: () => RunConfig;
|
|
88
|
-
observer?: AgentManagerObserver; // replaces onStart, onComplete, onCompact
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Fields go from 9 → 7 (remove 3 callbacks, add 1 observer).
|
|
93
|
-
|
|
94
|
-
### AgentManager internal changes
|
|
95
|
-
|
|
96
|
-
The three private fields (`onStart`, `onComplete`, `onCompact`) become one: `private observer?: AgentManagerObserver`.
|
|
97
|
-
Call sites change from `this.onStart?.(record)` to `this.observer?.onAgentStarted(record)`.
|
|
98
|
-
|
|
99
|
-
The `onCompact` relay into `subscribeRecordObserver` changes from:
|
|
100
|
-
|
|
101
|
-
```typescript
|
|
102
|
-
onCompact: (r, info) => this.onCompact?.(r, info),
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
to:
|
|
106
|
-
|
|
107
|
-
```typescript
|
|
108
|
-
onCompact: (r, info) => this.observer?.onAgentCompacted(r, info),
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### `CompactionInfo` stays in `agent-manager.ts`
|
|
112
|
-
|
|
113
|
-
`CompactionInfo` is a data shape consumed by the observer interface and already defined in `agent-manager.ts`.
|
|
114
|
-
It stays co-located since both `AgentManagerObserver` and `CompactionInfo` are exported from the same module.
|
|
115
|
-
`record-observer.ts` continues to import `CompactionInfo` from `agent-manager.ts`.
|
|
116
|
-
|
|
117
|
-
### Observer construction in `index.ts`
|
|
118
|
-
|
|
119
|
-
The three closure lambdas collapse into one object literal:
|
|
120
|
-
|
|
121
|
-
```typescript
|
|
122
|
-
const observer: AgentManagerObserver = {
|
|
123
|
-
onAgentStarted(record) {
|
|
124
|
-
pi.events.emit("subagents:started", {
|
|
125
|
-
id: record.id, type: record.type, description: record.description,
|
|
126
|
-
});
|
|
127
|
-
},
|
|
128
|
-
onAgentCompleted(record) {
|
|
129
|
-
const isError = record.status === "error" || record.status === "stopped" || record.status === "aborted";
|
|
130
|
-
const eventData = buildEventData(record);
|
|
131
|
-
if (isError) pi.events.emit("subagents:failed", eventData);
|
|
132
|
-
else pi.events.emit("subagents:completed", eventData);
|
|
133
|
-
|
|
134
|
-
pi.appendEntry("subagents:record", { /* same fields as today */ });
|
|
135
|
-
|
|
136
|
-
if (record.notification?.resultConsumed) {
|
|
137
|
-
notifications.cleanupCompleted(record.id);
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
notifications.sendCompletion(record);
|
|
141
|
-
},
|
|
142
|
-
onAgentCompacted(record, info) {
|
|
143
|
-
pi.events.emit("subagents:compacted", {
|
|
144
|
-
id: record.id, type: record.type, description: record.description,
|
|
145
|
-
reason: info.reason, tokensBefore: info.tokensBefore,
|
|
146
|
-
compactionCount: record.compactionCount,
|
|
147
|
-
});
|
|
148
|
-
},
|
|
149
|
-
};
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
Passed as `observer` to `new AgentManager({ ..., observer })`.
|
|
153
|
-
|
|
154
|
-
### Removed exports
|
|
155
|
-
|
|
156
|
-
The three callback type aliases are removed:
|
|
157
|
-
|
|
158
|
-
- `OnAgentStart`
|
|
159
|
-
- `OnAgentComplete`
|
|
160
|
-
- `OnAgentCompact`
|
|
161
|
-
|
|
162
|
-
These are only imported in `agent-manager.test.ts` — no production consumers outside `agent-manager.ts`.
|
|
163
|
-
|
|
164
|
-
## Module-Level Changes
|
|
165
|
-
|
|
166
|
-
### `src/agent-manager.ts`
|
|
167
|
-
|
|
168
|
-
- Add `AgentManagerObserver` interface (3 methods).
|
|
169
|
-
- Remove `OnAgentStart`, `OnAgentComplete`, `OnAgentCompact` type aliases.
|
|
170
|
-
- Replace `onStart`, `onComplete`, `onCompact` fields in `AgentManagerOptions` with `observer?: AgentManagerObserver`.
|
|
171
|
-
- Replace three private fields with `private observer?: AgentManagerObserver`.
|
|
172
|
-
- Update constructor to assign `this.observer = options.observer`.
|
|
173
|
-
- Update all call sites: `this.onStart?.(record)` → `this.observer?.onAgentStarted(record)`, etc.
|
|
174
|
-
- The `onCompact` relay to `subscribeRecordObserver` uses `this.observer?.onAgentCompacted`.
|
|
175
|
-
|
|
176
|
-
### `src/index.ts`
|
|
177
|
-
|
|
178
|
-
- Replace the three closure-lambda properties (`onComplete:`, `onStart:`, `onCompact:`) with a single `observer` object literal.
|
|
179
|
-
- Import `AgentManagerObserver` from `agent-manager.ts`.
|
|
180
|
-
- Remove any now-unused callback type imports.
|
|
181
|
-
|
|
182
|
-
### `src/record-observer.ts`
|
|
183
|
-
|
|
184
|
-
- No changes.
|
|
185
|
-
`RecordObserverOptions.onCompact` stays as-is — it is the session-level relay, not the manager-level observer.
|
|
186
|
-
`CompactionInfo` import from `agent-manager.ts` stays unchanged.
|
|
187
|
-
|
|
188
|
-
### `test/agent-manager.test.ts`
|
|
189
|
-
|
|
190
|
-
- Update imports: remove `OnAgentStart`, `OnAgentComplete`, `OnAgentCompact`; add `AgentManagerObserver`.
|
|
191
|
-
- Update `createManager` helper: replace the three callback overrides with `observer?: Partial<AgentManagerObserver>`.
|
|
192
|
-
The factory spreads a no-op default observer with test-provided overrides.
|
|
193
|
-
- Update each test that wires a callback to construct an observer object instead.
|
|
194
|
-
|
|
195
|
-
## Test Impact Analysis
|
|
196
|
-
|
|
197
|
-
1. No new unit tests are enabled by this refactoring — it's a 1:1 shape change.
|
|
198
|
-
2. No existing tests become redundant — each test exercises a specific lifecycle scenario (race condition, foreground vs background, error handling, queue drain).
|
|
199
|
-
3. All existing `agent-manager.test.ts` tests stay, with mechanical updates to the observer wiring.
|
|
200
|
-
The assertions remain the same (e.g., "observer.onAgentCompleted fires with `resultConsumed=false` when `markConsumed` called after await").
|
|
201
|
-
|
|
202
|
-
## TDD Order
|
|
203
|
-
|
|
204
|
-
### Step 1: Introduce `AgentManagerObserver` interface alongside existing callbacks
|
|
205
|
-
|
|
206
|
-
Add the interface to `agent-manager.ts`.
|
|
207
|
-
No production behavior changes — the interface is unused at this point.
|
|
208
|
-
|
|
209
|
-
- Commit: `refactor: add AgentManagerObserver interface`
|
|
210
|
-
|
|
211
|
-
### Step 2: Switch `AgentManager` internals to observer
|
|
212
|
-
|
|
213
|
-
1. Replace the three `onStart`/`onComplete`/`onCompact` fields on `AgentManagerOptions` with `observer?: AgentManagerObserver`.
|
|
214
|
-
2. Replace the three private fields with one `private observer?: AgentManagerObserver`.
|
|
215
|
-
3. Update all internal call sites (`this.onStart?.(record)` → `this.observer?.onAgentStarted(record)`, etc.).
|
|
216
|
-
4. Remove the three callback type aliases (`OnAgentStart`, `OnAgentComplete`, `OnAgentCompact`).
|
|
217
|
-
5. Update `test/agent-manager.test.ts`: change imports, update `createManager` helper and all test call sites to construct observer objects instead of individual callbacks.
|
|
218
|
-
6. Run `pnpm run check` to verify types.
|
|
219
|
-
|
|
220
|
-
- Commit: `refactor: replace AgentManager callbacks with observer interface (#112)`
|
|
221
|
-
|
|
222
|
-
### Step 3: Update `index.ts` to construct observer
|
|
223
|
-
|
|
224
|
-
1. Replace the three closure-lambda properties in the `new AgentManager({...})` call with a single `observer` object.
|
|
225
|
-
2. Import `AgentManagerObserver` type.
|
|
226
|
-
3. Remove unused callback type imports.
|
|
227
|
-
4. Run full test suite.
|
|
228
|
-
|
|
229
|
-
- Commit: `refactor: construct AgentManagerObserver in index.ts (#112)`
|
|
230
|
-
|
|
231
|
-
## Risks and Mitigations
|
|
232
|
-
|
|
233
|
-
| Risk | Mitigation |
|
|
234
|
-
| ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
235
|
-
| Tests break silently because esbuild ignores excess properties — old `onComplete` fields pass through without error | Step 2 removes the type aliases, so TypeScript catches any test still using the old shape via `pnpm run check` |
|
|
236
|
-
| `onComplete` error-swallowing behavior changes | The `try/catch` around `this.onComplete?.(record)` in the `.then()` path moves exactly to `this.observer?.onAgentCompleted(record)` — same guard, same catch, same debugLog |
|
|
237
|
-
| `Partial<AgentManagerObserver>` in test factory silently drops required methods | Tests that need a specific method construct it explicitly; the factory only provides a convenient default for tests that don't care about any observer method |
|
|
238
|
-
|
|
239
|
-
## Open Questions
|
|
240
|
-
|
|
241
|
-
- None — the issue's proposed design is unambiguous and aligns with the established session-observer pattern.
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 113
|
|
3
|
-
issue_title: "refactor(pi-subagents): disambiguate SpawnOptions (public vs internal)"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Disambiguate SpawnOptions (public vs internal)
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
`SpawnOptions` is defined in two places with the same name but incompatible shapes:
|
|
11
|
-
|
|
12
|
-
- `service.ts` (public API): 8 fields, JSON-friendly (`model` is `string`, `thinkingLevel` is `string`, uses `foreground` not `isBackground`).
|
|
13
|
-
- `agent-manager.ts` (internal): 13 fields, runtime types (`model` is `Model<any>`, `thinkingLevel` is `ThinkingLevel`, includes `signal`, `onSessionCreated`, `invocation`).
|
|
14
|
-
|
|
15
|
-
The name collision makes it ambiguous which type a reader is working with when they see `SpawnOptions` in a signature.
|
|
16
|
-
`service-adapter.ts` manually converts between the two shapes.
|
|
17
|
-
|
|
18
|
-
## Goals
|
|
19
|
-
|
|
20
|
-
- Rename the internal `SpawnOptions` in `agent-manager.ts` to `AgentSpawnConfig`.
|
|
21
|
-
- Keep the public `SpawnOptions` in `service.ts` unchanged — it's the published API.
|
|
22
|
-
- Update all internal consumers (`agent-tool.ts`, `agent-menu.ts`, `agent-manager.ts`) to use the new name.
|
|
23
|
-
- Update the `SpawnArgs` internal interface in `agent-manager.ts` to reference `AgentSpawnConfig`.
|
|
24
|
-
- Non-breaking refactor — the public API surface is unchanged.
|
|
25
|
-
|
|
26
|
-
## Non-Goals
|
|
27
|
-
|
|
28
|
-
- Splitting `AgentSpawnConfig` into agent-configuration fields vs execution/lifecycle fields — the issue mentions this as a "consider" item; defer to a follow-up if the type grows further.
|
|
29
|
-
- Narrowing `AgentToolDeps` or `AgentMenuDeps` — tracked in #114.
|
|
30
|
-
- Removing `onSessionCreated` — it's a legitimate per-spawn callback used by `agent-tool.ts` for UI streaming, structurally different from the lifecycle observer (#112).
|
|
31
|
-
|
|
32
|
-
## Background
|
|
33
|
-
|
|
34
|
-
### Current consumers of internal `SpawnOptions`
|
|
35
|
-
|
|
36
|
-
| File | How it references `SpawnOptions` |
|
|
37
|
-
| --------------------- | ------------------------------------------------------------------------------------------- |
|
|
38
|
-
| `agent-manager.ts` | Defines the type; uses it in `spawn()`, `spawnAndWait()`, and `SpawnArgs` |
|
|
39
|
-
| `tools/agent-tool.ts` | Imports and uses in `AgentToolManager.spawn` and `AgentToolManager.spawnAndWait` signatures |
|
|
40
|
-
| `ui/agent-menu.ts` | Imports and uses in `AgentMenuManager.spawnAndWait` signature |
|
|
41
|
-
|
|
42
|
-
### Public `SpawnOptions` in `service.ts`
|
|
43
|
-
|
|
44
|
-
Defined alongside `SubagentsService`.
|
|
45
|
-
Used by `service-adapter.ts` at the conversion boundary.
|
|
46
|
-
Published via `package.json` exports — **not touched by this change**.
|
|
47
|
-
|
|
48
|
-
### Dependency: issue #112 (observer refactor)
|
|
49
|
-
|
|
50
|
-
Issue #112 is closed.
|
|
51
|
-
The observer eliminated `onStart`/`onComplete`/`onCompact` from `AgentManagerOptions`.
|
|
52
|
-
`onSessionCreated` remains on the internal `SpawnOptions` (now `AgentSpawnConfig`) — it's per-spawn, not per-manager.
|
|
53
|
-
|
|
54
|
-
### Architecture reference
|
|
55
|
-
|
|
56
|
-
Phase 7, Step D1 in `docs/architecture/architecture.md`.
|
|
57
|
-
|
|
58
|
-
## Design Overview
|
|
59
|
-
|
|
60
|
-
This is a pure rename — no structural or behavioral changes.
|
|
61
|
-
The internal `SpawnOptions` becomes `AgentSpawnConfig`.
|
|
62
|
-
Every `import type { SpawnOptions }` from `"../agent-manager.js"` or `"./agent-manager.js"` becomes `import type { AgentSpawnConfig }`.
|
|
63
|
-
|
|
64
|
-
The name `AgentSpawnConfig` was chosen because:
|
|
65
|
-
|
|
66
|
-
1. It disambiguates from the public `SpawnOptions`.
|
|
67
|
-
2. It follows the established naming convention in this package (`AgentRecord`, `AgentInvocation`, `AgentTypeRegistry`).
|
|
68
|
-
3. "Config" conveys that this is a configuration bag assembled by the caller and consumed by the manager — not a service-level options type.
|
|
69
|
-
|
|
70
|
-
### Type shape (unchanged)
|
|
71
|
-
|
|
72
|
-
```typescript
|
|
73
|
-
export interface AgentSpawnConfig {
|
|
74
|
-
description: string;
|
|
75
|
-
model?: Model<any>;
|
|
76
|
-
maxTurns?: number;
|
|
77
|
-
isolated?: boolean;
|
|
78
|
-
inheritContext?: boolean;
|
|
79
|
-
thinkingLevel?: ThinkingLevel;
|
|
80
|
-
isBackground?: boolean;
|
|
81
|
-
bypassQueue?: boolean;
|
|
82
|
-
isolation?: IsolationMode;
|
|
83
|
-
invocation?: AgentInvocation;
|
|
84
|
-
signal?: AbortSignal;
|
|
85
|
-
onSessionCreated?: (session: AgentSession) => void;
|
|
86
|
-
parentSessionFile?: string;
|
|
87
|
-
parentSessionId?: string;
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## Module-Level Changes
|
|
92
|
-
|
|
93
|
-
### `src/agent-manager.ts`
|
|
94
|
-
|
|
95
|
-
- Rename `export interface SpawnOptions` → `export interface AgentSpawnConfig`.
|
|
96
|
-
- Update `SpawnArgs.options` type from `SpawnOptions` to `AgentSpawnConfig`.
|
|
97
|
-
- Update `spawn()` parameter type from `SpawnOptions` to `AgentSpawnConfig`.
|
|
98
|
-
- Update `spawnAndWait()` parameter type from `Omit<SpawnOptions, "isBackground">` to `Omit<AgentSpawnConfig, "isBackground">`.
|
|
99
|
-
|
|
100
|
-
### `src/tools/agent-tool.ts`
|
|
101
|
-
|
|
102
|
-
- Change import from `SpawnOptions` to `AgentSpawnConfig`.
|
|
103
|
-
- Update `AgentToolManager.spawn` and `AgentToolManager.spawnAndWait` signatures.
|
|
104
|
-
|
|
105
|
-
### `src/ui/agent-menu.ts`
|
|
106
|
-
|
|
107
|
-
- Change import from `SpawnOptions` to `AgentSpawnConfig`.
|
|
108
|
-
- Update `AgentMenuManager.spawnAndWait` signature.
|
|
109
|
-
|
|
110
|
-
### `src/service.ts`
|
|
111
|
-
|
|
112
|
-
- No changes — the public `SpawnOptions` stays as-is.
|
|
113
|
-
|
|
114
|
-
### `src/service-adapter.ts`
|
|
115
|
-
|
|
116
|
-
- No changes — it already uses `unknown` for the spawn options parameter in `AgentManagerLike`.
|
|
117
|
-
|
|
118
|
-
### `test/agent-manager.test.ts`
|
|
119
|
-
|
|
120
|
-
- No import changes needed — the test file does not import `SpawnOptions`.
|
|
121
|
-
- One test description string mentions "SpawnOptions" → update to "AgentSpawnConfig" for accuracy.
|
|
122
|
-
|
|
123
|
-
## Test Impact Analysis
|
|
124
|
-
|
|
125
|
-
1. No new tests are enabled by this rename — it's a 1:1 name substitution.
|
|
126
|
-
2. No existing tests become redundant.
|
|
127
|
-
3. All existing tests stay as-is — they construct raw object literals that structurally satisfy the type regardless of its name.
|
|
128
|
-
|
|
129
|
-
## TDD Order
|
|
130
|
-
|
|
131
|
-
### Step 1: Rename `SpawnOptions` to `AgentSpawnConfig` and update all consumers
|
|
132
|
-
|
|
133
|
-
1. Rename the interface in `agent-manager.ts`.
|
|
134
|
-
2. Update `SpawnArgs`, `spawn()`, and `spawnAndWait()` in `agent-manager.ts`.
|
|
135
|
-
3. Update the import and signatures in `tools/agent-tool.ts`.
|
|
136
|
-
4. Update the import and signature in `ui/agent-menu.ts`.
|
|
137
|
-
5. Update the test description string in `test/agent-manager.test.ts`.
|
|
138
|
-
6. Run `pnpm run check` to verify types.
|
|
139
|
-
7. Run `pnpm vitest run` to verify all tests pass.
|
|
140
|
-
|
|
141
|
-
- Commit: `refactor: rename internal SpawnOptions to AgentSpawnConfig (#113)`
|
|
142
|
-
|
|
143
|
-
This is a single-step refactor because the rename is mechanical and all consumers must be updated atomically for the type checker to stay green.
|
|
144
|
-
|
|
145
|
-
## Risks and Mitigations
|
|
146
|
-
|
|
147
|
-
| Risk | Mitigation |
|
|
148
|
-
| -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
149
|
-
| Missed consumer still references old name | `pnpm run check` will catch any unresolved `SpawnOptions` import from `agent-manager.ts` since the export no longer exists |
|
|
150
|
-
| Test descriptions become misleading | Grep for "SpawnOptions" in test files and update any description strings that reference the old name |
|
|
151
|
-
| Confusion with `service.ts` `SpawnOptions` during review | The plan is scoped to internal-only changes; `service.ts` is explicitly listed as "no changes" |
|
|
152
|
-
|
|
153
|
-
## Open Questions
|
|
154
|
-
|
|
155
|
-
- None — the rename is unambiguous and aligns with both the issue proposal and the architecture doc.
|
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 114
|
|
3
|
-
issue_title: "refactor(pi-subagents): narrow AgentToolDeps and AgentMenuDeps"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Narrow AgentToolDeps and AgentMenuDeps
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
With the foundational extractions complete — `AgentTypeRegistry` (#108), `SettingsManager` (#109), `AgentActivityTracker` (#110), and `AgentManagerObserver` (#112) — the two widest dependency bags in the extension still carry fields that belong on their collaborators.
|
|
11
|
-
|
|
12
|
-
`AgentToolDeps` has 9 fields: 3 are description-text strings derivable from the registry, 1 is a raw `emitEvent` callback that the observer should own, and the `agentActivity` Map is passed as raw mutable state.
|
|
13
|
-
`AgentMenuDeps` has 8 fields: `emitEvent` is defined but never referenced in the module (dead field).
|
|
14
|
-
|
|
15
|
-
Each excess field inflates test mock construction and obscures the real dependency surface.
|
|
16
|
-
|
|
17
|
-
## Goals
|
|
18
|
-
|
|
19
|
-
- Remove `emitEvent` from both `AgentToolDeps` and `AgentMenuDeps`.
|
|
20
|
-
- Remove `typeListText` and `availableTypesText` from `AgentToolDeps` — derive them from `registry` inside `createAgentTool`.
|
|
21
|
-
- Add `onAgentCreated` to `AgentManagerObserver` so the `subagents:created` event is emitted by the observer, not the tool.
|
|
22
|
-
- Narrow `agentActivity` in both interfaces to a typed read/write interface instead of raw `Map`.
|
|
23
|
-
- Final counts: `AgentToolDeps` 9 → 6, `AgentMenuDeps` 8 → 7.
|
|
24
|
-
|
|
25
|
-
## Non-Goals
|
|
26
|
-
|
|
27
|
-
- Removing `agentDir` from `AgentToolDeps` — it is not derivable from the registry (it comes from the Pi SDK's `getAgentDir()`).
|
|
28
|
-
- Adding presentation methods to `AgentTypeRegistry` — that would mix SRP concerns.
|
|
29
|
-
- Splitting `agent-tool.ts` foreground/background (tracked in #115).
|
|
30
|
-
- Removing `personalAgentsDir` / `projectAgentsDir` from `AgentMenuDeps` — they are genuine menu-level concerns (file management UI).
|
|
31
|
-
|
|
32
|
-
## Background
|
|
33
|
-
|
|
34
|
-
### Prerequisite status
|
|
35
|
-
|
|
36
|
-
All prerequisites are implemented and merged:
|
|
37
|
-
|
|
38
|
-
| Issue | Title | Status |
|
|
39
|
-
| ----- | ---------------------------------------------- | ------- |
|
|
40
|
-
| #108 | Extract `AgentTypeRegistry` | ✅ Done |
|
|
41
|
-
| #109 | Extract `SettingsManager` | ✅ Done |
|
|
42
|
-
| #110 | `AgentActivityTracker` | ✅ Done |
|
|
43
|
-
| #112 | Replace `AgentManager` callbacks with observer | ✅ Done |
|
|
44
|
-
| #113 | Disambiguate `SpawnOptions` | ✅ Done |
|
|
45
|
-
| #118 | `SettingsManager` apply methods | ✅ Done |
|
|
46
|
-
|
|
47
|
-
### Current interfaces
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
// tools/agent-tool.ts — 9 fields
|
|
51
|
-
interface AgentToolDeps {
|
|
52
|
-
manager: AgentToolManager;
|
|
53
|
-
widget: AgentToolWidget;
|
|
54
|
-
agentActivity: Map<string, AgentActivityTracker>;
|
|
55
|
-
emitEvent: (name: string, data: unknown) => void;
|
|
56
|
-
registry: AgentTypeRegistry;
|
|
57
|
-
typeListText: string;
|
|
58
|
-
availableTypesText: string;
|
|
59
|
-
agentDir: string;
|
|
60
|
-
settings: { readonly defaultMaxTurns: number | undefined };
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// ui/agent-menu.ts — 8 fields
|
|
64
|
-
interface AgentMenuDeps {
|
|
65
|
-
manager: AgentMenuManager;
|
|
66
|
-
registry: AgentTypeRegistry;
|
|
67
|
-
agentActivity: Map<string, AgentActivityTracker>;
|
|
68
|
-
getModelLabel: (type: string, registry?: ModelRegistry) => string;
|
|
69
|
-
settings: AgentMenuSettings;
|
|
70
|
-
emitEvent: (name: string, data: unknown) => void; // ← dead field
|
|
71
|
-
personalAgentsDir: string;
|
|
72
|
-
projectAgentsDir: string;
|
|
73
|
-
}
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### Relevant design principles
|
|
77
|
-
|
|
78
|
-
- **Dependency width** (code-design skill): do not pass a shared bag to functions that only use a subset.
|
|
79
|
-
- **Output arguments**: `agentActivity` is a raw `Map` mutated via `.set()` and `.delete()` — encapsulate behind methods.
|
|
80
|
-
- **ISP**: consumers should depend on the narrowest interface they need.
|
|
81
|
-
|
|
82
|
-
## Design Overview
|
|
83
|
-
|
|
84
|
-
### 1. Move `subagents:created` to observer
|
|
85
|
-
|
|
86
|
-
The `AgentManagerObserver` interface gains an `onAgentCreated` method.
|
|
87
|
-
`AgentManager.spawn()` calls `observer.onAgentCreated(record)` after creating the record.
|
|
88
|
-
The observer implementation in `index.ts` emits `pi.events.emit("subagents:created", ...)`.
|
|
89
|
-
The tool no longer calls `deps.emitEvent(...)`.
|
|
90
|
-
|
|
91
|
-
The event payload includes `id`, `type`, `description`, and `isBackground`.
|
|
92
|
-
Since `isBackground` is known at spawn-time (it's part of the spawn config), the observer has all needed data.
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
interface AgentManagerObserver {
|
|
96
|
-
onAgentStarted(record: AgentRecord): void;
|
|
97
|
-
onAgentCompleted(record: AgentRecord): void;
|
|
98
|
-
onAgentCompacted(record: AgentRecord, info: CompactionInfo): void;
|
|
99
|
-
onAgentCreated(record: AgentRecord): void; // ← new
|
|
100
|
-
}
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### 2. Derive description text from registry
|
|
104
|
-
|
|
105
|
-
Move `buildTypeListText()` from `index.ts` to `tools/helpers.ts` as a pure function that accepts the registry and `agentDir`:
|
|
106
|
-
|
|
107
|
-
```typescript
|
|
108
|
-
function buildTypeListText(
|
|
109
|
-
registry: AgentConfigLookup & { getDefaultAgentNames(): string[]; getUserAgentNames(): string[] },
|
|
110
|
-
agentDir: string,
|
|
111
|
-
): string;
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
Inside `createAgentTool`, compute both strings from `deps.registry` and `deps.agentDir`:
|
|
115
|
-
|
|
116
|
-
```typescript
|
|
117
|
-
const typeListText = buildTypeListText(deps.registry, deps.agentDir);
|
|
118
|
-
const availableTypesText = deps.registry.getAvailableTypes().join(", ");
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
This removes `typeListText` and `availableTypesText` from the interface.
|
|
122
|
-
The helper requires `getModelLabelFromConfig`, which already lives in `tools/helpers.ts`.
|
|
123
|
-
|
|
124
|
-
### 3. Narrow agentActivity to a typed interface
|
|
125
|
-
|
|
126
|
-
Instead of `Map<string, AgentActivityTracker>`, both interfaces accept a narrow typed interface matching their actual usage:
|
|
127
|
-
|
|
128
|
-
```typescript
|
|
129
|
-
/** Read/write interface for agent-tool's activity tracking needs. */
|
|
130
|
-
interface AgentActivityAccess {
|
|
131
|
-
get(id: string): AgentActivityTracker | undefined;
|
|
132
|
-
set(id: string, tracker: AgentActivityTracker): void;
|
|
133
|
-
delete(id: string): void;
|
|
134
|
-
}
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
The `AgentMenuDeps` only reads (`.get()`), so it gets a narrower read-only type:
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
/** Read-only interface for menu's conversation viewer. */
|
|
141
|
-
interface AgentActivityReader {
|
|
142
|
-
get(id: string): AgentActivityTracker | undefined;
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
The runtime's `Map<string, AgentActivityTracker>` satisfies both interfaces structurally.
|
|
147
|
-
No wrapper class is needed — `Map` already implements `get/set/delete`.
|
|
148
|
-
The benefit is that the type signature communicates the actual usage pattern.
|
|
149
|
-
|
|
150
|
-
### 4. Remove dead `emitEvent` from `AgentMenuDeps`
|
|
151
|
-
|
|
152
|
-
This field is defined in the interface but never referenced inside `agent-menu.ts`.
|
|
153
|
-
Remove it from the interface and from the construction site in `index.ts`.
|
|
154
|
-
|
|
155
|
-
### Final interfaces
|
|
156
|
-
|
|
157
|
-
```typescript
|
|
158
|
-
// tools/agent-tool.ts — 6 fields (was 9)
|
|
159
|
-
interface AgentToolDeps {
|
|
160
|
-
manager: AgentToolManager;
|
|
161
|
-
widget: AgentToolWidget;
|
|
162
|
-
agentActivity: AgentActivityAccess;
|
|
163
|
-
registry: AgentTypeRegistry;
|
|
164
|
-
agentDir: string;
|
|
165
|
-
settings: { readonly defaultMaxTurns: number | undefined };
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// ui/agent-menu.ts — 7 fields (was 8)
|
|
169
|
-
interface AgentMenuDeps {
|
|
170
|
-
manager: AgentMenuManager;
|
|
171
|
-
registry: AgentTypeRegistry;
|
|
172
|
-
agentActivity: AgentActivityReader;
|
|
173
|
-
getModelLabel: (type: string, registry?: ModelRegistry) => string;
|
|
174
|
-
settings: AgentMenuSettings;
|
|
175
|
-
personalAgentsDir: string;
|
|
176
|
-
projectAgentsDir: string;
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## Module-Level Changes
|
|
181
|
-
|
|
182
|
-
### Modified files
|
|
183
|
-
|
|
184
|
-
1. **`src/agent-manager.ts`** — Call `observer.onAgentCreated(record)` in `spawn()` after creating the record.
|
|
185
|
-
Update `AgentManagerObserver` interface to include `onAgentCreated`.
|
|
186
|
-
|
|
187
|
-
2. **`src/tools/agent-tool.ts`** — Remove `emitEvent`, `typeListText`, `availableTypesText` from `AgentToolDeps`.
|
|
188
|
-
Add `AgentActivityAccess` interface.
|
|
189
|
-
Derive description text from `registry` + `agentDir` inside `createAgentTool`.
|
|
190
|
-
Remove `deps.emitEvent(...)` call.
|
|
191
|
-
Replace `Map<string, AgentActivityTracker>` with `AgentActivityAccess`.
|
|
192
|
-
|
|
193
|
-
3. **`src/tools/helpers.ts`** — Add `buildTypeListText(registry, agentDir)` extracted from `index.ts`.
|
|
194
|
-
|
|
195
|
-
4. **`src/ui/agent-menu.ts`** — Remove `emitEvent` from `AgentMenuDeps`.
|
|
196
|
-
Add `AgentActivityReader` interface.
|
|
197
|
-
Replace `Map<string, AgentActivityTracker>` with `AgentActivityReader`.
|
|
198
|
-
|
|
199
|
-
5. **`src/index.ts`** — Remove `buildTypeListText` closure.
|
|
200
|
-
Remove `typeListText`, `availableTypesText`, `emitEvent` from the `AgentToolDeps` construction.
|
|
201
|
-
Remove `emitEvent` from the `AgentMenuDeps` construction.
|
|
202
|
-
Add `onAgentCreated` to the observer object.
|
|
203
|
-
|
|
204
|
-
6. **`test/tools/agent-tool.test.ts`** — Update `makeDeps` factory: remove `emitEvent`, `typeListText`, `availableTypesText`.
|
|
205
|
-
Update assertions that check `emitEvent` was called.
|
|
206
|
-
|
|
207
|
-
7. **`test/ui/agent-menu.test.ts`** — Update `makeDeps` factory: remove `emitEvent`.
|
|
208
|
-
|
|
209
|
-
8. **`test/agent-manager.test.ts`** — Add test for `observer.onAgentCreated` being called during spawn.
|
|
210
|
-
|
|
211
|
-
## Test Impact Analysis
|
|
212
|
-
|
|
213
|
-
1. **New tests enabled**: `observer.onAgentCreated` can be tested in `agent-manager.test.ts` — verify it fires during `spawn()` with the correct record.
|
|
214
|
-
|
|
215
|
-
2. **Tests that simplify**: `agent-tool.test.ts` mock factory drops 3 fields (`emitEvent`, `typeListText`, `availableTypesText`).
|
|
216
|
-
Tests asserting `deps.emitEvent` was called become assertions that the observer was invoked (tested at the manager level instead).
|
|
217
|
-
`agent-menu.test.ts` mock factory drops 1 field (`emitEvent`).
|
|
218
|
-
|
|
219
|
-
3. **Tests that stay**: all tool-behavior tests (spawn paths, resume, error handling) remain — they test the tool's own logic, not the narrowed plumbing.
|
|
220
|
-
|
|
221
|
-
## TDD Order
|
|
222
|
-
|
|
223
|
-
1. **Add `onAgentCreated` to observer interface and manager.**
|
|
224
|
-
Add the method to `AgentManagerObserver`.
|
|
225
|
-
Call it in `AgentManager.spawn()`.
|
|
226
|
-
Test: verify `observer.onAgentCreated` fires with the created record.
|
|
227
|
-
Commit: `feat: add onAgentCreated to AgentManagerObserver`
|
|
228
|
-
|
|
229
|
-
2. **Extract `buildTypeListText` to helpers.**
|
|
230
|
-
Move the function from `index.ts` to `tools/helpers.ts` as a pure function.
|
|
231
|
-
Test: unit test `buildTypeListText` with a mock registry.
|
|
232
|
-
Update `index.ts` to import and call the extracted helper.
|
|
233
|
-
Commit: `refactor: extract buildTypeListText to tools/helpers`
|
|
234
|
-
|
|
235
|
-
3. **Derive description text inside `createAgentTool`.**
|
|
236
|
-
Remove `typeListText` and `availableTypesText` from `AgentToolDeps`.
|
|
237
|
-
Compute them from `deps.registry` + `deps.agentDir` inside `createAgentTool`.
|
|
238
|
-
Update `index.ts` construction site.
|
|
239
|
-
Update `agent-tool.test.ts` mock factory.
|
|
240
|
-
Test: verify tool description still contains expected text.
|
|
241
|
-
Commit: `refactor: derive description text from registry in createAgentTool`
|
|
242
|
-
|
|
243
|
-
4. **Remove `emitEvent` from `AgentToolDeps`.**
|
|
244
|
-
Remove the field from the interface.
|
|
245
|
-
Remove the `deps.emitEvent(...)` call in the background spawn path.
|
|
246
|
-
Wire `onAgentCreated` in the `index.ts` observer to emit `subagents:created`.
|
|
247
|
-
Update `agent-tool.test.ts` (remove `emitEvent` from factory, remove/update related assertions).
|
|
248
|
-
Commit: `refactor: remove emitEvent from AgentToolDeps`
|
|
249
|
-
|
|
250
|
-
5. **Remove dead `emitEvent` from `AgentMenuDeps`.**
|
|
251
|
-
Remove the field from the interface.
|
|
252
|
-
Remove from `index.ts` construction site.
|
|
253
|
-
Update `agent-menu.test.ts` mock factory.
|
|
254
|
-
Commit: `refactor: remove dead emitEvent from AgentMenuDeps`
|
|
255
|
-
|
|
256
|
-
6. **Narrow `agentActivity` to typed interfaces.**
|
|
257
|
-
Add `AgentActivityAccess` interface to `agent-tool.ts`.
|
|
258
|
-
Add `AgentActivityReader` interface to `agent-menu.ts`.
|
|
259
|
-
Replace `Map<string, AgentActivityTracker>` with the narrow type in both interfaces.
|
|
260
|
-
Update test factories (no functional change — `Map` satisfies both interfaces).
|
|
261
|
-
Commit: `refactor: narrow agentActivity to typed interfaces`
|
|
262
|
-
|
|
263
|
-
## Risks and Mitigations
|
|
264
|
-
|
|
265
|
-
| Risk | Mitigation |
|
|
266
|
-
| --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
267
|
-
| `subagents:created` event data changes shape when moved to observer | Observer receives the full `AgentRecord` which contains `id`, `type`, `description`. `isBackground` must be derivable from the record or spawn config — verify the record carries this at spawn time. |
|
|
268
|
-
| `buildTypeListText` depends on `getModelLabelFromConfig` which is in `tools/helpers.ts` | This is already the target file — no circular dependency risk. |
|
|
269
|
-
| Third-party consumers rely on `emitEvent` presence in `AgentToolDeps` | `AgentToolDeps` is not in the public `exports` — it's internal. No external API breakage. |
|
|
270
|
-
| `AgentActivityAccess` interface is structurally identical to a subset of `Map` | This is intentional — the `Map` satisfies it without a wrapper. If a non-Map implementation is needed later, the interface is already in place. |
|
|
271
|
-
|
|
272
|
-
## Open Questions
|
|
273
|
-
|
|
274
|
-
1. Should `onAgentCreated` receive the full `AgentRecord` or a narrow payload?
|
|
275
|
-
The other observer methods receive `AgentRecord` — consistency suggests the same.
|
|
276
|
-
The `isBackground` flag is needed for the event payload; verify it's available on the record at creation time (it should be, since background is set at spawn).
|
|
277
|
-
2. Should `steer-tool.ts`'s `emitEvent` (emits `subagents:steered`) also move to the observer?
|
|
278
|
-
It's a separate concern (tool-level steering) and a different event.
|
|
279
|
-
Defer to a follow-up if desired.
|