@gotgenes/pi-subagents 6.3.0 → 6.4.0

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.
@@ -0,0 +1,322 @@
1
+ ---
2
+ issue: 108
3
+ issue_title: "refactor(pi-subagents): extract AgentTypeRegistry class from module-scoped state"
4
+ ---
5
+
6
+ # Extract AgentTypeRegistry class
7
+
8
+ ## Problem Statement
9
+
10
+ `agent-types.ts` manages a module-scoped `Map<string, AgentConfig>` mutated by `registerAgents()` and read by 12+ call sites across 6 files.
11
+ This is global mutable state hidden behind free functions — tests must call `registerAgents(new Map())` in `beforeEach` to reset it, and `reloadCustomAgents` is threaded as a callback through `AgentToolDeps` and `AgentMenuDeps` because there is no object to own the reload.
12
+
13
+ ## Goals
14
+
15
+ - Wrap the module-scoped `agents` Map and its free functions into an injectable `AgentTypeRegistry` class.
16
+ - Replace the `reloadCustomAgents` callback (threaded through 2 dependency bags) with `registry.reload()`.
17
+ - Move `DEFAULT_AGENT_NAMES` from `types.ts` to the registry (it is a constant, not a type).
18
+ - Enable test isolation without module resets — each test creates its own registry instance.
19
+ - Use lift-and-shift: introduce the class alongside the free functions, migrate consumers incrementally, then remove the free functions.
20
+
21
+ ## Non-Goals
22
+
23
+ - `SettingsManager` extraction (#109) — separate Phase 7 step.
24
+ - `AgentActivityTracker` extraction (#110) — separate Phase 7 step.
25
+ - Splitting `AgentRecord` lifecycle state (#111) — separate Phase 7 step.
26
+ - Narrowing `AgentConfig` (21 fields) — tracked in the architecture doc but out of scope.
27
+ - Moving `BUILTIN_TOOL_NAMES` — it is a constant with no Map dependency, stays as a module export.
28
+
29
+ ## Background
30
+
31
+ ### Architecture reference
32
+
33
+ Phase 7, Step A1 in `docs/architecture/architecture.md`.
34
+ Steps A1–A3 are independent and can proceed in any order.
35
+ This plan addresses A1 only.
36
+
37
+ ### Relevant modules
38
+
39
+ | Module | Role | agent-types dependency |
40
+ | --------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
41
+ | `agent-types.ts` | Module-scoped `agents` Map + 11 free functions | Owns the state |
42
+ | `default-agents.ts` | `DEFAULT_AGENTS` Map constant | Read by `registerAgents` |
43
+ | `custom-agents.ts` | `loadCustomAgents()` → disk scan | Imports `BUILTIN_TOOL_NAMES` |
44
+ | `session-config.ts` | `assembleSessionConfig()` | Imports `resolveAgentConfig`, `getToolNamesForType`, `getMemoryToolNames`, `getReadOnlyMemoryToolNames` |
45
+ | `agent-runner.ts` | `runAgent()` → calls `assembleSessionConfig` | No direct import (transitive via session-config) |
46
+ | `agent-manager.ts` | `AgentManager` → calls runner | No direct import |
47
+ | `tools/agent-tool.ts` | Agent tool definition | Imports `resolveAgentConfig`, `resolveType`; receives `reloadCustomAgents` via `AgentToolDeps` |
48
+ | `ui/agent-menu.ts` | `/agents` command handler | Imports `BUILTIN_TOOL_NAMES`, `getAllTypes`, `resolveAgentConfig`, `resolveType`; receives `reloadCustomAgents` via `AgentMenuDeps` |
49
+ | `ui/agent-widget.ts` | Widget + `getDisplayName` / `getPromptModeLabel` helpers | Imports `resolveAgentConfig` |
50
+ | `ui/conversation-viewer.ts` | Live conversation overlay | Imports `getDisplayName`, `getPromptModeLabel` from `agent-widget.ts` |
51
+ | `tools/get-result-tool.ts` | `get_subagent_result` tool | Imports `getDisplayName` from `agent-widget.ts` |
52
+ | `index.ts` | Extension entry point, wiring | Imports `registerAgents`, `getAvailableTypes`, `getDefaultAgentNames`, `getUserAgentNames`, `resolveAgentConfig`; defines `reloadCustomAgents` closure |
53
+
54
+ ### Test files affected
55
+
56
+ | Test file | Current agent-types coupling | Change needed |
57
+ | -------------------------------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
58
+ | `agent-types.test.ts` (333 lines) | Tests free functions directly, calls `registerAgents()` in `beforeEach` | Add class tests; eventually migrate free-function tests to class tests |
59
+ | `session-config.test.ts` (601 lines) | `vi.mock("../src/agent-types.js")` | Pass mock registry param, remove module mock |
60
+ | `agent-runner.test.ts` (302 lines) | `vi.mock("../src/agent-types.js")` | Provide mock registry in `RunOptions`, remove module mock |
61
+ | `agent-runner-extension-tools.test.ts` (307 lines) | `vi.mock("../src/agent-types.js")` | Same as `agent-runner.test.ts` |
62
+ | `tools/agent-tool.test.ts` (240 lines) | Mocks `reloadCustomAgents` in deps | Replace with `registry` in deps |
63
+ | `ui/agent-menu.test.ts` (184 lines) | `vi.mock("../../src/agent-types.js")`, mocks `reloadCustomAgents` in deps | Replace with `registry` in deps, remove module mock |
64
+ | `agent-widget.test.ts` (26 lines) | Minimal | Pass registry to widget constructor |
65
+ | `agent-manager.test.ts` (712 lines) | No `agent-types.js` mock | Add registry to constructor options |
66
+
67
+ ### Constraints from AGENTS.md / code-design skill
68
+
69
+ - **ISP:** `session-config.ts` should accept a narrow interface (only `resolveAgentConfig` + `getToolNamesForType`), not the full registry class.
70
+ - **DIP:** Accept collaborators as parameters; keep IO at the edges.
71
+ - **Pi SDK boundaries:** Pure helpers must not import Pi SDK types.
72
+ - **Lift-and-shift:** Never plan a single step that rewrites an entire large test file at once.
73
+
74
+ ## Design Overview
75
+
76
+ ### `AgentTypeRegistry` class
77
+
78
+ ```typescript
79
+ export class AgentTypeRegistry {
80
+ private agents = new Map<string, AgentConfig>();
81
+
82
+ constructor(private loadUserAgents: () => Map<string, AgentConfig>) {
83
+ this.reload();
84
+ }
85
+
86
+ /** Re-scan custom agents from disk and merge with defaults. */
87
+ reload(): void { /* clear + merge DEFAULT_AGENTS + loadUserAgents() */ }
88
+
89
+ resolveAgentConfig(type: string): AgentConfig { /* ... */ }
90
+ resolveType(name: string): string | undefined { /* ... */ }
91
+ getAvailableTypes(): string[] { /* ... */ }
92
+ getAllTypes(): string[] { /* ... */ }
93
+ getDefaultAgentNames(): string[] { /* ... */ }
94
+ getUserAgentNames(): string[] { /* ... */ }
95
+ isValidType(type: string): boolean { /* ... */ }
96
+ getToolNamesForType(type: string): string[] { /* ... */ }
97
+
98
+ static readonly DEFAULT_AGENT_NAMES = ["general-purpose", "Explore", "Plan"] as const;
99
+ }
100
+ ```
101
+
102
+ The constructor accepts a `loadUserAgents` callback (typically `() => loadCustomAgents(process.cwd())`).
103
+ This keeps `process.cwd()` at the edge (in `index.ts`) and makes tests trivial — they pass `() => new Map()` or a fixture.
104
+
105
+ ### What stays as free functions
106
+
107
+ - **`BUILTIN_TOOL_NAMES`** — constant array, no Map dependency.
108
+ Stays as a module-level export in `agent-types.ts`.
109
+ - **`getMemoryToolNames` / `getReadOnlyMemoryToolNames`** — pure functions over constant arrays, no Map access.
110
+ Stay as module-level exports.
111
+
112
+ ### Narrow interface for `session-config.ts`
113
+
114
+ ```typescript
115
+ /** Narrow registry interface for session-config (ISP). */
116
+ export interface AgentConfigLookup {
117
+ resolveAgentConfig(type: string): AgentConfig;
118
+ getToolNamesForType(type: string): string[];
119
+ }
120
+ ```
121
+
122
+ `assembleSessionConfig` gains a `registry: AgentConfigLookup` parameter.
123
+ Tests construct a plain object satisfying this interface — no class instantiation needed.
124
+
125
+ ### Threading through the call chain
126
+
127
+ `session-config.ts` ← called by `agent-runner.ts` ← called by `AgentManager`:
128
+
129
+ 1. `assembleSessionConfig(type, ctx, options, env, registry)` — new param.
130
+ 2. `RunOptions` gains `registry: AgentConfigLookup`.
131
+ 3. `AgentManagerOptions` gains `registry: AgentTypeRegistry`.
132
+ 4. `AgentManager` stores the registry and passes it to the runner via `RunOptions`.
133
+
134
+ ### Replacing `reloadCustomAgents` callback
135
+
136
+ Before:
137
+
138
+ ```typescript
139
+ // index.ts
140
+ const reloadCustomAgents = () => {
141
+ const userAgents = loadCustomAgents(process.cwd());
142
+ registerAgents(userAgents);
143
+ };
144
+
145
+ // AgentToolDeps / AgentMenuDeps
146
+ reloadCustomAgents: () => void;
147
+ ```
148
+
149
+ After:
150
+
151
+ ```typescript
152
+ // index.ts
153
+ const registry = new AgentTypeRegistry(() => loadCustomAgents(process.cwd()));
154
+
155
+ // AgentToolDeps / AgentMenuDeps
156
+ registry: AgentTypeRegistry;
157
+
158
+ // Callers use:
159
+ deps.registry.reload();
160
+ ```
161
+
162
+ ### Display helpers (`getDisplayName`, `getPromptModeLabel`)
163
+
164
+ These functions in `agent-widget.ts` call `resolveAgentConfig(type)`.
165
+ After the extraction, they accept the registry (or a `resolveAgentConfig` callback) as a parameter.
166
+ The `AgentWidget` constructor gains a `registry` parameter and passes it to these helpers internally.
167
+ External callers (`conversation-viewer.ts`, `get-result-tool.ts`, etc.) pass the registry they already hold via their deps.
168
+
169
+ ## Module-Level Changes
170
+
171
+ ### New
172
+
173
+ No new files.
174
+
175
+ ### Modified
176
+
177
+ 1. **`src/agent-types.ts`**
178
+ - Add `AgentTypeRegistry` class with all instance methods.
179
+ - Add `AgentConfigLookup` interface.
180
+ - Keep free functions temporarily (delegation shim during migration).
181
+ - Final step: remove free functions, module-scoped `agents` Map, and `registerAgents`.
182
+
183
+ 2. **`src/types.ts`**
184
+ - Remove `DEFAULT_AGENT_NAMES` constant (moved to `AgentTypeRegistry.DEFAULT_AGENT_NAMES`).
185
+
186
+ 3. **`src/session-config.ts`**
187
+ - `assembleSessionConfig` gains a `registry: AgentConfigLookup` parameter.
188
+ - Remove imports of `resolveAgentConfig`, `getToolNamesForType` from `agent-types.ts`.
189
+
190
+ 4. **`src/agent-runner.ts`**
191
+ - `RunOptions` gains `registry: AgentConfigLookup`.
192
+ - `runAgent` passes `options.registry` to `assembleSessionConfig`.
193
+
194
+ 5. **`src/agent-manager.ts`**
195
+ - `AgentManagerOptions` gains `registry: AgentTypeRegistry`.
196
+ - `AgentManager` stores `this.registry` and passes it into `RunOptions` when calling `runner.run`.
197
+
198
+ 6. **`src/tools/agent-tool.ts`**
199
+ - `AgentToolDeps`: add `registry: AgentTypeRegistry`, remove `reloadCustomAgents`.
200
+ - Replace `resolveType(...)` / `resolveAgentConfig(...)` imports with `deps.registry.resolveType(...)` / `deps.registry.resolveAgentConfig(...)`.
201
+ - Replace `deps.reloadCustomAgents()` with `deps.registry.reload()`.
202
+
203
+ 7. **`src/ui/agent-menu.ts`**
204
+ - `AgentMenuDeps`: add `registry: AgentTypeRegistry`, remove `reloadCustomAgents`.
205
+ - Replace `getAllTypes()`/`resolveAgentConfig()`/`resolveType()` imports with `deps.registry.*` calls.
206
+ - `BUILTIN_TOOL_NAMES` import stays (it is a constant, not a method).
207
+ - Replace `deps.reloadCustomAgents()` with `deps.registry.reload()`.
208
+
209
+ 8. **`src/ui/agent-widget.ts`**
210
+ - `AgentWidget` constructor gains a `registry: AgentTypeRegistry` (or narrow interface) parameter.
211
+ - `getDisplayName(type, registry)` / `getPromptModeLabel(type, registry)` gain a registry parameter.
212
+ - Internal render methods use `this.registry`.
213
+
214
+ 9. **`src/ui/conversation-viewer.ts`**
215
+ - `ConversationViewer` constructor gains a registry parameter.
216
+ - Passes it to `getDisplayName` / `getPromptModeLabel` calls.
217
+
218
+ 10. **`src/tools/get-result-tool.ts`**
219
+ - `GetResultToolDeps` (or equivalent) gains registry.
220
+ - Passes it to `getDisplayName` calls.
221
+
222
+ 11. **`src/index.ts`**
223
+ - Construct `AgentTypeRegistry` with `() => loadCustomAgents(process.cwd())`.
224
+ - Pass registry to `AgentManager`, agent-tool deps, menu deps, widget, get-result-tool deps.
225
+ - Remove `reloadCustomAgents` closure.
226
+ - Remove free-function imports (`registerAgents`, `getDefaultAgentNames`, `getUserAgentNames`, `getAvailableTypes`, `resolveAgentConfig`).
227
+ - Use `registry.*` methods directly for `buildTypeListText`.
228
+
229
+ ### Removed
230
+
231
+ - Free functions from `agent-types.ts`: `registerAgents`, `resolveType`, `resolveAgentConfig`, `getAvailableTypes`, `getAllTypes`, `getDefaultAgentNames`, `getUserAgentNames`, `isValidType`, `getToolNamesForType` (final cleanup step).
232
+ - Module-scoped `agents` Map and `resolveKey` helper.
233
+ - `DEFAULT_AGENT_NAMES` from `types.ts`.
234
+ - `reloadCustomAgents` field from `AgentToolDeps` and `AgentMenuDeps`.
235
+
236
+ ## Test Impact Analysis
237
+
238
+ ### New tests enabled
239
+
240
+ - **Isolation without module resets:** Each test creates its own `AgentTypeRegistry` with a fixture callback, eliminating cross-test state leakage and the `registerAgents(new Map())` ceremony.
241
+ - **Reload behavior:** Tests can verify `registry.reload()` picks up new agents without touching module state.
242
+
243
+ ### Existing tests that become redundant
244
+
245
+ - The existing free-function tests in `agent-types.test.ts` become redundant once the class tests cover the same behavior.
246
+ They can be removed in the final cleanup step.
247
+
248
+ ### Existing tests that must stay
249
+
250
+ - `session-config.test.ts` — tests `assembleSessionConfig` behavior; mock setup changes from `vi.mock("agent-types.js")` to passing a mock `AgentConfigLookup` object.
251
+ - `agent-runner.test.ts`, `agent-runner-extension-tools.test.ts` — test runner behavior; mock setup changes from `vi.mock("agent-types.js")` to providing mock registry in `RunOptions`.
252
+ - `tools/agent-tool.test.ts` — tests tool handler; deps mock changes from `reloadCustomAgents: vi.fn()` to `registry: mockRegistry`.
253
+ - `ui/agent-menu.test.ts` — tests menu handler; deps mock changes similarly.
254
+ - `agent-manager.test.ts` — must add a mock registry to constructor options.
255
+
256
+ ## TDD Order
257
+
258
+ 1. **Create `AgentTypeRegistry` class** — Add class to `agent-types.ts` alongside existing free functions.
259
+ Add `AgentConfigLookup` interface.
260
+ Test all methods in a new `describe('AgentTypeRegistry')` block in `agent-types.test.ts`: construction, `reload()`, `resolveAgentConfig`, `resolveType`, `getAvailableTypes`, `getAllTypes`, `getDefaultAgentNames`, `getUserAgentNames`, `isValidType`, `getToolNamesForType`.
261
+ - Test surface: `agent-types.test.ts` — new describe block
262
+ - Commit: `feat(pi-subagents): add AgentTypeRegistry class (#108)`
263
+
264
+ 2. **Inject through the config-assembly chain** — `assembleSessionConfig` gains `registry: AgentConfigLookup` param.
265
+ `RunOptions` gains `registry: AgentConfigLookup`.
266
+ `AgentManagerOptions` gains `registry: AgentTypeRegistry`.
267
+ Construct registry in `index.ts` and pass through `AgentManager` → `runAgent` → `assembleSessionConfig`.
268
+ Update `session-config.test.ts` (replace `vi.mock("agent-types.js")` with mock `AgentConfigLookup` object), `agent-runner.test.ts` and `agent-runner-extension-tools.test.ts` (provide mock registry in `RunOptions`, remove `vi.mock`), `agent-manager.test.ts` (add registry to constructor options).
269
+ - Test surface: `session-config.test.ts`, `agent-runner.test.ts`, `agent-runner-extension-tools.test.ts`, `agent-manager.test.ts`
270
+ - Commit: `refactor(pi-subagents): inject registry through config-assembly chain (#108)`
271
+
272
+ 3. **Inject into agent tool** — Add `registry: AgentTypeRegistry` to `AgentToolDeps`, remove `reloadCustomAgents`.
273
+ Replace `resolveType` / `resolveAgentConfig` module imports with `deps.registry.*` calls.
274
+ Replace `deps.reloadCustomAgents()` with `deps.registry.reload()`.
275
+ Update `index.ts` agent-tool deps and `tools/agent-tool.test.ts`.
276
+ - Test surface: `tools/agent-tool.test.ts`
277
+ - Commit: `refactor(pi-subagents): inject registry into agent tool (#108)`
278
+
279
+ 4. **Inject into agent menu** — Add `registry: AgentTypeRegistry` to `AgentMenuDeps`, remove `reloadCustomAgents`.
280
+ Replace `getAllTypes` / `resolveAgentConfig` / `resolveType` module imports with `deps.registry.*` calls.
281
+ Replace `deps.reloadCustomAgents()` with `deps.registry.reload()`.
282
+ Update `index.ts` menu deps and `ui/agent-menu.test.ts`.
283
+ - Test surface: `ui/agent-menu.test.ts`
284
+ - Commit: `refactor(pi-subagents): inject registry into agent menu (#108)`
285
+
286
+ 5. **Inject into agent widget and display helpers** — `AgentWidget` constructor gains `registry`.
287
+ `getDisplayName(type, registry)` and `getPromptModeLabel(type, registry)` gain registry parameters.
288
+ `ConversationViewer` constructor gains registry.
289
+ `GetResultToolDeps` gains registry for `getDisplayName` calls.
290
+ Update `index.ts` wiring, `agent-widget.test.ts`, and any test files that call these helpers.
291
+ - Test surface: `agent-widget.test.ts`, related callers
292
+ - Commit: `refactor(pi-subagents): inject registry into agent widget (#108)`
293
+
294
+ 6. **Move `DEFAULT_AGENT_NAMES` to registry** — Add static `DEFAULT_AGENT_NAMES` property on `AgentTypeRegistry`.
295
+ Remove the constant from `types.ts`.
296
+ Grep confirms no import consumers exist — the constant is defined but unused.
297
+ - Test surface: `agent-types.test.ts` — add assertion for static property
298
+ - Commit: `refactor(pi-subagents): move DEFAULT_AGENT_NAMES to registry (#108)`
299
+
300
+ 7. **Remove free-function exports** — Delete `registerAgents`, `resolveType`, `resolveAgentConfig`, `getAvailableTypes`, `getAllTypes`, `getDefaultAgentNames`, `getUserAgentNames`, `isValidType`, `getToolNamesForType`, the module-scoped `agents` Map, and `resolveKey` helper from `agent-types.ts`.
301
+ Remove the free-function tests from `agent-types.test.ts` (now covered by class tests).
302
+ Remove any remaining free-function imports from `index.ts`.
303
+ Verify with `pnpm run check` that no dangling references remain.
304
+ - Test surface: `agent-types.test.ts` — remove old describe block
305
+ - Commit: `refactor(pi-subagents): remove free-function exports from agent-types (#108)`
306
+
307
+ ## Risks and Mitigations
308
+
309
+ | Risk | Impact | Mitigation |
310
+ | --------------------------------------------------------------------------------------------- | ---------------------------------------------- | -------------------------------------------------------------------------------------------- |
311
+ | Large blast radius — 11 source files, 8 test files | Merge conflicts if other PRs land concurrently | Lift-and-shift: free functions keep working until final removal; each step is a valid commit |
312
+ | `vi.mock("agent-types.js")` removal in runner tests changes behavior | Tests may expose latent bugs in session-config | Mock `AgentConfigLookup` with the same values the current `vi.mock` provides |
313
+ | Display helpers (`getDisplayName`, `getPromptModeLabel`) thread registry through many callers | Signature churn in UI layer | These callers already have a deps bag or constructor params — registry fits naturally |
314
+ | `agent-types.test.ts` (333 lines) needs migration from free-function tests to class tests | Large test rewrite in step 7 | Step 1 creates class tests first; step 7 only deletes the now-redundant free-function tests |
315
+ | `AgentRunner` interface change (`RunOptions` gains `registry`) | Breaks callers that construct `RunOptions` | Only `agent-manager.ts` constructs `RunOptions`; single-site change |
316
+
317
+ ## Open Questions
318
+
319
+ - **`getDisplayName` / `getPromptModeLabel` placement:** These are thin display helpers that wrap `resolveAgentConfig`.
320
+ The plan proposes adding a registry parameter.
321
+ An alternative is to make them methods on the registry itself (e.g., `registry.getDisplayName(type)`), trading purity for convenience.
322
+ Decide during implementation based on how natural the call sites feel.
@@ -0,0 +1,36 @@
1
+ ---
2
+ issue: 100
3
+ issue_title: "Replace callback threading with direct session-event subscription"
4
+ ---
5
+
6
+ # Retro: #100 — Replace callback threading with direct session-event subscription
7
+
8
+ ## Final Retrospective (2026-05-20T22:30:00-04:00)
9
+
10
+ ### Session summary
11
+
12
+ Implemented Step 3 of the AgentManager internal decomposition — replacing the 3-layer callback-threading pattern with two independent session observers (`subscribeRecordObserver` and `subscribeUIObserver`).
13
+ Five TDD cycles landed with only one unanticipated test breakage, releasing as `pi-subagents-v6.3.0`.
14
+ `SpawnOptions` dropped 5 `on*` fields, `RunOptions` dropped 5, and `ResumeOptions` dropped 3, with net −220 lines of source code removed.
15
+
16
+ ### Observations
17
+
18
+ #### What went well
19
+
20
+ - The phased plan structure (extract observers → wire AgentManager → wire agent-tool → simplify runner) created clean isolation between cycles.
21
+ Each cycle touched 1–2 source files and 1 test file, making changes easy to review.
22
+ - Upgrading `mockSession()` once in cycle 3 to support `subscribe()` and `emit()` was a one-time investment that made the stat-verification tests more realistic — events now drive record state instead of manually calling callbacks on `RunOptions`.
23
+ - The `resume()` simplification was particularly clean: 10 lines of callback wiring reduced to 2 lines (`subscribeRecordObserver` + `runner.resume` with only `{ signal }`).
24
+ - All 5 TDD cycles except one landed first-try with no rework.
25
+
26
+ #### What caused friction (agent side)
27
+
28
+ - `missing-context` — The plan listed `bindExtensions({ onError })` as part of the unchanged runner code, but the `onError` handler called `options.onToolActivity` which was removed in cycle 5.
29
+ The plan said "grep for `ToolActivity`" but the reference was inside a function literal passed to `bindExtensions`, not a type import.
30
+ Impact: one unexpected test failure in cycle 5 (`bindExtensions` test expected `onError`), caught immediately and fixed in the same commit.
31
+ Noted in commit body as a plan deviation.
32
+
33
+ #### What caused friction (user side)
34
+
35
+ - No friction observed.
36
+ The issue description was thorough and unambiguous, and the user's involvement was limited to triggering each phase (`/plan-issue`, `/tdd-plan`, `/ship-issue`).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gotgenes/pi-subagents",
3
- "version": "6.3.0",
3
+ "version": "6.4.0",
4
4
  "exports": {
5
5
  ".": "./src/service.ts"
6
6
  },
@@ -11,6 +11,7 @@ import type { Model } from "@earendil-works/pi-ai";
11
11
  import type { AgentSession, ExtensionContext } from "@earendil-works/pi-coding-agent";
12
12
  import { AgentRecord } from "./agent-record.js";
13
13
  import type { AgentRunner } from "./agent-runner.js";
14
+ import { AgentTypeRegistry } from "./agent-types.js";
14
15
  import { debugLog } from "./debug.js";
15
16
  import { buildParentSnapshot } from "./parent-snapshot.js";
16
17
  import { subscribeRecordObserver } from "./record-observer.js";
@@ -30,6 +31,7 @@ export interface AgentManagerOptions {
30
31
  runner: AgentRunner;
31
32
  worktrees: WorktreeManager;
32
33
  exec: ShellExec;
34
+ registry: AgentTypeRegistry;
33
35
  maxConcurrent?: number;
34
36
  getRunConfig?: () => RunConfig;
35
37
  onStart?: OnAgentStart;
@@ -81,6 +83,7 @@ export class AgentManager {
81
83
  private readonly runner: AgentRunner;
82
84
  private readonly worktrees: WorktreeManager;
83
85
  private readonly exec: ShellExec;
86
+ private readonly registry: AgentTypeRegistry;
84
87
  private maxConcurrent: number;
85
88
  private getRunConfig?: () => RunConfig;
86
89
 
@@ -93,6 +96,7 @@ export class AgentManager {
93
96
  this.runner = options.runner;
94
97
  this.worktrees = options.worktrees;
95
98
  this.exec = options.exec;
99
+ this.registry = options.registry;
96
100
  this.onComplete = options.onComplete;
97
101
  this.onStart = options.onStart;
98
102
  this.onCompact = options.onCompact;
@@ -203,6 +207,7 @@ export class AgentManager {
203
207
  parentSessionFile: options.parentSessionFile,
204
208
  parentSessionId: options.parentSessionId,
205
209
  signal: record.abortController!.signal,
210
+ registry: this.registry,
206
211
  onSessionCreated: (session) => {
207
212
  record.session = session;
208
213
  // Capture the session file path early so it's available for display
@@ -12,6 +12,7 @@ import {
12
12
  SessionManager,
13
13
  SettingsManager,
14
14
  } from "@earendil-works/pi-coding-agent";
15
+ import type { AgentConfigLookup } from "./agent-types.js";
15
16
  import { extractText } from "./context.js";
16
17
  import { detectEnv } from "./env.js";
17
18
  import { assembleSessionConfig } from "./session-config.js";
@@ -91,6 +92,8 @@ export interface RunOptions {
91
92
  * module-scope `graceTurns` during migration.
92
93
  */
93
94
  graceTurns?: number;
95
+ /** Agent config lookup — provides resolveAgentConfig and getToolNamesForType. */
96
+ registry: AgentConfigLookup;
94
97
  }
95
98
 
96
99
  export interface RunResult {
@@ -189,6 +192,7 @@ export async function runAgent(
189
192
  thinkingLevel: options.thinkingLevel,
190
193
  },
191
194
  env,
195
+ options.registry,
192
196
  );
193
197
 
194
198
  const agentDir = getAgentDir();