@gotgenes/pi-subagents 6.14.0 → 6.15.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.
- package/CHANGELOG.md +26 -0
- package/docs/architecture/architecture.md +11 -25
- package/docs/plans/0145-decompose-execute-push-ctx-to-boundary.md +290 -0
- package/docs/retro/0152-add-prompt-snippet.md +34 -0
- package/package.json +2 -3
- package/src/agent-manager.ts +7 -6
- package/src/handlers/index.ts +2 -6
- package/src/index.ts +21 -7
- package/src/service-adapter.ts +18 -16
- package/src/tools/agent-tool.ts +55 -112
- package/src/tools/background-spawner.ts +33 -51
- package/src/tools/foreground-runner.ts +36 -57
- package/src/tools/spawn-config.ts +146 -0
- package/src/types.ts +0 -1
- package/src/ui/agent-widget.ts +5 -0
- package/src/ui/conversation-viewer.ts +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,32 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [6.15.0](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v6.14.1...pi-subagents-v6.15.0) (2026-05-23)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* extract resolveSpawnConfig pure function ([#145](https://github.com/gotgenes/pi-packages/issues/145)) ([e89724a](https://github.com/gotgenes/pi-packages/commit/e89724a87480713529160d0fa23975becbcfe162))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Documentation
|
|
17
|
+
|
|
18
|
+
* plan decompose execute and push ctx to boundary ([#145](https://github.com/gotgenes/pi-packages/issues/145)) ([aae7d7b](https://github.com/gotgenes/pi-packages/commit/aae7d7b4e04ab0dddedd2a0f9f2b806719956ced))
|
|
19
|
+
* update architecture doc for completed Step M ([#145](https://github.com/gotgenes/pi-packages/issues/145)) ([33ec0c7](https://github.com/gotgenes/pi-packages/commit/33ec0c73479076c180381dcc1cb4106ba635f33f))
|
|
20
|
+
* update plan with injected collaborators for ctx elimination ([#145](https://github.com/gotgenes/pi-packages/issues/145)) ([76bb57b](https://github.com/gotgenes/pi-packages/commit/76bb57b4b5190078ded8685907f0878640031e13))
|
|
21
|
+
|
|
22
|
+
## [6.14.1](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v6.14.0...pi-subagents-v6.14.1) (2026-05-23)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Bug Fixes
|
|
26
|
+
|
|
27
|
+
* resolve fallow dead-code warnings ([2113f6b](https://github.com/gotgenes/pi-packages/commit/2113f6bc49812ce32ac68d0e2dd88e0a60b4474a))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Documentation
|
|
31
|
+
|
|
32
|
+
* **retro:** add retro notes for issue [#152](https://github.com/gotgenes/pi-packages/issues/152) ([7337bc1](https://github.com/gotgenes/pi-packages/commit/7337bc175528b4fb99dbc765eb06f0bcf2accec1))
|
|
33
|
+
|
|
8
34
|
## [6.14.0](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v6.13.1...pi-subagents-v6.14.0) (2026-05-23)
|
|
9
35
|
|
|
10
36
|
|
|
@@ -647,38 +647,24 @@ Apply the dependency bag convention to touched modules: `NotificationDeps` (4 fi
|
|
|
647
647
|
|
|
648
648
|
Impact: eliminates dual counting; removes `??` fallback pattern from widget and conversation viewer; hides `ExecutionState` structure from consumers.
|
|
649
649
|
|
|
650
|
-
### Step M: Decompose execute and push ExtensionContext to the boundary (#145)
|
|
650
|
+
### Step M: Decompose execute and push ExtensionContext to the boundary (#145) ✓
|
|
651
651
|
|
|
652
|
-
|
|
652
|
+
Extracted config resolution into `resolveSpawnConfig` (pure function in `spawn-config.ts`).
|
|
653
|
+
Injected three collaborators (`buildSnapshot`, `getModelInfo`, `getSessionInfo`) into `createAgentTool` so `execute` no longer reads `ctx` beyond `ctx.ui` (already delegated to `widget.setUICtx`).
|
|
654
|
+
`AgentManager.spawn()` and `spawnAndWait()` accept `ParentSnapshot` instead of `ExtensionContext`.
|
|
655
|
+
`service-adapter.ts` calls `buildParentSnapshot(session.ctx)` at its boundary.
|
|
656
|
+
`foreground-runner` and `background-spawner` receive `ResolvedSpawnConfig` + domain values (`snapshot`, `parentSessionFile`, `parentSessionId`) instead of `ctx`.
|
|
653
657
|
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
3. **Dispatch** (~80 lines) - resume / background / foreground, each passing 14-16 field parameter bags.
|
|
657
|
-
|
|
658
|
-
The config resolution section is working for the dependencies: manually unpacking `resolvedConfig` field by field, computing derived values, then repacking everything into massive objects for `spawnBackground` and `runForeground`.
|
|
659
|
-
The 16-field bags are the symptom - they exist because the resolution happened in the wrong place.
|
|
660
|
-
|
|
661
|
-
The fix has two parts:
|
|
662
|
-
|
|
663
|
-
1. **Extract config resolution** into a pure function (e.g. `resolveSpawnConfig`) that accepts the raw tool params, registry, model info, and settings, and returns a single `ResolvedSpawnConfig` object.
|
|
664
|
-
`execute` becomes: extract ctx → resolve config → dispatch.
|
|
665
|
-
`spawnBackground` and `runForeground` receive `ResolvedSpawnConfig` instead of 16 individual fields.
|
|
666
|
-
2. **Push `ctx` to the boundary.**
|
|
667
|
-
`execute` extracts everything from `ctx` in its first few lines.
|
|
668
|
-
`foreground-runner.ts` and `background-spawner.ts` receive domain values (`snapshot`, `parentSessionFile`, `parentSessionId`) instead of `ctx`.
|
|
669
|
-
`AgentManager.spawn()` and `spawnAndWait()` accept `ParentSnapshot` instead of `ExtensionContext`.
|
|
670
|
-
`service-adapter.ts` calls `buildParentSnapshot(session.ctx)` at its boundary.
|
|
658
|
+
Dissolved `ForegroundDeps`, `BackgroundDeps`, and `AdapterDeps` into plain parameters.
|
|
659
|
+
`AgentToolDeps` is destructured in the `createAgentTool` signature.
|
|
671
660
|
|
|
672
661
|
After this step, `ExtensionContext` appears only in:
|
|
673
662
|
|
|
674
|
-
- `
|
|
663
|
+
- `index.ts` closures (wired at extension startup)
|
|
675
664
|
- `service-adapter.ts` (cross-extension boundary)
|
|
676
|
-
- `index.ts` (extension entry point)
|
|
677
665
|
- Menu handlers (addressed by Step N)
|
|
678
666
|
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
Impact: `execute` drops from ~145 to ~30 lines; eliminates 16-field parameter bags; eliminates 1 `vi.mock()` call in `agent-manager.test.ts`; `foreground-runner` and `background-spawner` tests no longer need `ctx` mocks; `AgentManager` operates entirely on domain types.
|
|
667
|
+
Impact: `execute` dropped from ~145 to ~25 lines; eliminated 16-field parameter bags; eliminated `vi.mock("../src/parent-snapshot.js")` in `agent-manager.test.ts`; foreground/background runner tests no longer need `ctx` mocks; `AgentManager` operates entirely on domain types.
|
|
682
668
|
|
|
683
669
|
### Step N: Narrow UI context for menu handlers (#146)
|
|
684
670
|
|
|
@@ -690,7 +676,7 @@ Creation wizard’s `spawnAndWait` call changes: the narrow `AgentMenuManager.sp
|
|
|
690
676
|
|
|
691
677
|
Apply the dependency bag convention to touched modules: `AgentConfigEditorDeps` (4 fields), `SteerToolDeps` (4 fields), and `GetResultDeps` (4 fields) become plain parameters; `AgentMenuDeps` (8 fields) and `AgentCreationWizardDeps` (5 fields) are destructured in the signature.
|
|
692
678
|
|
|
693
|
-
After Steps M and N, `ExtensionContext` appears only at true boundaries: `
|
|
679
|
+
After Steps M and N, `ExtensionContext` appears only at true boundaries: `index.ts` closures, `service-adapter.ts` (cross-extension bridge), and `index.ts` (extension entry point).
|
|
694
680
|
|
|
695
681
|
Impact: eliminates ~43 `ctx as any` casts across menu, editor, and wizard test files; tests construct a plain object satisfying `MenuUI` with no cast.
|
|
696
682
|
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
---
|
|
2
|
+
issue: 145
|
|
3
|
+
issue_title: "Decompose execute and push ExtensionContext to the boundary (Phase 9, Step M)"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Decompose execute and push ctx to the boundary
|
|
7
|
+
|
|
8
|
+
## Problem Statement
|
|
9
|
+
|
|
10
|
+
`agent-tool.ts` `execute` is ~140 lines mixing three concerns: boundary extraction (~5 lines reading `ctx`), config resolution (~60 lines unpacking `resolvedConfig` field by field), and dispatch (~80 lines building 14–16 field parameter bags for `spawnBackground` and `runForeground`).
|
|
11
|
+
The large parameter bags exist because config resolution happens inline instead of in a dedicated function.
|
|
12
|
+
Meanwhile, `ExtensionContext` is threaded from `execute` through `ForegroundParams.ctx` / `BackgroundParams.ctx` into `foreground-runner` and `background-spawner`, where the only thing consumed is `sessionManager.getSessionFile()` and `sessionManager.getSessionId()`.
|
|
13
|
+
`AgentManager.spawn()` and `spawnAndWait()` accept `ExtensionContext` directly and call `buildParentSnapshot(ctx)` internally — but this is already a pure boundary concern that belongs at the call site.
|
|
14
|
+
Additionally, `execute` reaches into `ctx` for model info and session identity — these are session-scoped values that `index.ts` already captures and could inject as collaborators, removing `execute`'s need to read `ctx` beyond the UI context it already delegates to `widget.setUICtx()`.
|
|
15
|
+
|
|
16
|
+
## Goals
|
|
17
|
+
|
|
18
|
+
- Extract config resolution into a pure function (`resolveSpawnConfig`) so `execute` becomes: resolve config → dispatch.
|
|
19
|
+
- Inject three missing collaborators into `createAgentTool` so `execute` no longer extracts values from `ctx`:
|
|
20
|
+
- `buildSnapshot: (inheritContext: boolean) => ParentSnapshot` — closure over `ctx`, wired in `index.ts`.
|
|
21
|
+
- `getModelInfo: () => ModelInfo` — provides `parentModel` and `modelRegistry` for `resolveSpawnConfig`.
|
|
22
|
+
- `getSessionInfo: () => { parentSessionFile: string; parentSessionId: string }` — parent session identity.
|
|
23
|
+
- Replace `ForegroundParams.ctx` and `BackgroundParams.ctx` with plain domain values (`parentSessionFile`, `parentSessionId`, `snapshot`).
|
|
24
|
+
- Change `AgentManager.spawn()` and `spawnAndWait()` to accept `ParentSnapshot` instead of `ExtensionContext`.
|
|
25
|
+
- Move `buildParentSnapshot(ctx)` calls to the two boundaries: `index.ts` (via closure) and `service-adapter.ts`.
|
|
26
|
+
- Eliminate the `vi.mock("../src/parent-snapshot.js")` in `agent-manager.test.ts`.
|
|
27
|
+
- Apply the dependency bag convention: dissolve `ForegroundDeps`, `BackgroundDeps`, `AdapterDeps` (each ≤3 fields) into plain parameters.
|
|
28
|
+
- This is a breaking internal refactor — no public API changes.
|
|
29
|
+
|
|
30
|
+
## Non-Goals
|
|
31
|
+
|
|
32
|
+
- Narrowing menu handler ctx (Step N, #146) — deferred.
|
|
33
|
+
- Injecting text wrapping into ConversationViewer (Step O, #147) — unrelated track.
|
|
34
|
+
- Observation model consolidation (Step L, #144) — independent track.
|
|
35
|
+
- Changing the `SubagentsService` public API in `service.ts`.
|
|
36
|
+
|
|
37
|
+
## Background
|
|
38
|
+
|
|
39
|
+
### Relevant modules
|
|
40
|
+
|
|
41
|
+
| Module | Current role |
|
|
42
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
43
|
+
| `tools/agent-tool.ts` | `execute` callback — 140 lines, mixes boundary extraction, config resolution, dispatch |
|
|
44
|
+
| `tools/foreground-runner.ts` | `runForeground()` — receives 14-field `ForegroundParams` including `ctx` with `sessionManager` |
|
|
45
|
+
| `tools/background-spawner.ts` | `spawnBackground()` — receives 14-field `BackgroundParams` including `ctx` with `sessionManager` |
|
|
46
|
+
| `agent-manager.ts` | `spawn()` / `spawnAndWait()` accept `ExtensionContext`, call `buildParentSnapshot()` internally |
|
|
47
|
+
| `parent-snapshot.ts` | `buildParentSnapshot(ctx)` — pure function capturing `ParentSnapshot` from ctx |
|
|
48
|
+
| `service-adapter.ts` | Cross-extension boundary — calls `manager.spawn(session.ctx, ...)` |
|
|
49
|
+
| `invocation-config.ts` | `resolveAgentInvocationConfig()` — merges agent config with tool params |
|
|
50
|
+
| `model-resolver.ts` | `resolveInvocationModel()` — resolves model strings to model instances |
|
|
51
|
+
| `index.ts` | Extension entry point — wires `createAgentTool` deps, captures `runtime.currentCtx` |
|
|
52
|
+
| `runtime.ts` | `SubagentRuntime` — holds session-scoped mutable state including `currentCtx` |
|
|
53
|
+
|
|
54
|
+
### Constraints from AGENTS.md
|
|
55
|
+
|
|
56
|
+
- Keep modules focused and composable (one concern per file).
|
|
57
|
+
- Prefer explicit configuration over hidden behavior.
|
|
58
|
+
- Keep Pi SDK imports out of business-logic modules.
|
|
59
|
+
- Business logic should be pure functions — keep IO at the edges.
|
|
60
|
+
|
|
61
|
+
### Phase 9 context
|
|
62
|
+
|
|
63
|
+
This is Step M of Phase 9.
|
|
64
|
+
It has no blockers and blocks Step N (#146), which narrows menu handler ctx.
|
|
65
|
+
After this step, `ExtensionContext` appears only at true SDK/extension boundaries: `index.ts` closures, `service-adapter.ts`, and menu handlers.
|
|
66
|
+
|
|
67
|
+
## Design Overview
|
|
68
|
+
|
|
69
|
+
### Part 1: Extract config resolution (done)
|
|
70
|
+
|
|
71
|
+
A new pure function `resolveSpawnConfig` in `spawn-config.ts` encapsulates all config resolution logic previously inline in `execute`.
|
|
72
|
+
`execute` calls `resolveSpawnConfig(params, registry, modelInfo, settings)` and dispatches on the result.
|
|
73
|
+
This is already committed.
|
|
74
|
+
|
|
75
|
+
### Part 2: Inject collaborators and push ctx out of execute
|
|
76
|
+
|
|
77
|
+
`execute` currently reads `ctx.model`, `ctx.modelRegistry`, `ctx.sessionManager`, and passes `ctx` to `buildParentSnapshot`.
|
|
78
|
+
These are all session-scoped values that `index.ts` captures at session start.
|
|
79
|
+
Three collaborators replace the `ctx` reads:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// Injected as plain parameters into createAgentTool:
|
|
83
|
+
buildSnapshot: (inheritContext: boolean) => ParentSnapshot,
|
|
84
|
+
getModelInfo: () => ModelInfo,
|
|
85
|
+
getSessionInfo: () => { parentSessionFile: string; parentSessionId: string },
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`index.ts` wires them as closures over `runtime.currentCtx`:
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
createAgentTool({
|
|
92
|
+
// ... existing params ...
|
|
93
|
+
buildSnapshot: (inheritContext) => buildParentSnapshot(ctx, inheritContext),
|
|
94
|
+
getModelInfo: () => ({
|
|
95
|
+
parentModel: ctx.model,
|
|
96
|
+
modelRegistry: ctx.modelRegistry,
|
|
97
|
+
}),
|
|
98
|
+
getSessionInfo: () => ({
|
|
99
|
+
parentSessionFile: ctx.sessionManager.getSessionFile(),
|
|
100
|
+
parentSessionId: ctx.sessionManager.getSessionId(),
|
|
101
|
+
}),
|
|
102
|
+
})
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
After this, `execute` touches `ctx` only for `ctx.ui` — which is already delegated via `widget.setUICtx()`.
|
|
106
|
+
The `ExtensionContext` import in `agent-tool.ts` is removed entirely.
|
|
107
|
+
|
|
108
|
+
### Part 3: Push ctx out of AgentManager
|
|
109
|
+
|
|
110
|
+
`AgentManager.spawn()` and `spawnAndWait()` accept `ParentSnapshot` instead of `ExtensionContext`.
|
|
111
|
+
The internal `buildParentSnapshot(ctx, ...)` call is removed — `snapshot` arrives pre-built from the call sites.
|
|
112
|
+
`service-adapter.ts` calls `buildParentSnapshot(session.ctx, ...)` at its boundary before delegating.
|
|
113
|
+
|
|
114
|
+
### Part 4: Push ctx out of foreground-runner and background-spawner
|
|
115
|
+
|
|
116
|
+
`ForegroundParams.ctx` and `BackgroundParams.ctx` are replaced by `snapshot: ParentSnapshot`, `parentSessionFile: string`, `parentSessionId: string`.
|
|
117
|
+
The narrow manager interfaces change from `ctx: any` to `snapshot: ParentSnapshot`.
|
|
118
|
+
|
|
119
|
+
### Part 5: Shrink params bags with ResolvedSpawnConfig
|
|
120
|
+
|
|
121
|
+
`ForegroundParams` and `BackgroundParams` carry `ResolvedSpawnConfig` instead of 10+ individual fields that were computed during config resolution.
|
|
122
|
+
Only dispatch-specific fields (`rawType`, `fellBack`, `toolCallId`, `displayName`) remain as separate params fields.
|
|
123
|
+
|
|
124
|
+
### Part 6: Dissolve small dependency bags
|
|
125
|
+
|
|
126
|
+
Per the dependency bag convention:
|
|
127
|
+
|
|
128
|
+
- `ForegroundDeps` (3 fields) → plain parameters on `runForeground`.
|
|
129
|
+
- `BackgroundDeps` (3 fields) → plain parameters on `spawnBackground`.
|
|
130
|
+
- `AdapterDeps` (4 fields) → plain parameters on `createSubagentsService`.
|
|
131
|
+
- `AgentToolDeps` → destructured in the `createAgentTool` signature; the interface stays as a named type for the test factory.
|
|
132
|
+
|
|
133
|
+
The narrow `*ManagerDeps` and `*WidgetDeps` interfaces stay — they define the contract each function needs from its collaborators.
|
|
134
|
+
|
|
135
|
+
## Module-Level Changes
|
|
136
|
+
|
|
137
|
+
### New file: `src/tools/spawn-config.ts` (done)
|
|
138
|
+
|
|
139
|
+
- `ResolvedSpawnConfig` interface.
|
|
140
|
+
- `ModelInfo` interface.
|
|
141
|
+
- `resolveSpawnConfig()` pure function.
|
|
142
|
+
|
|
143
|
+
### Modified: `src/tools/agent-tool.ts`
|
|
144
|
+
|
|
145
|
+
- `execute` shrinks from ~140 to ~20 lines.
|
|
146
|
+
- `ExtensionContext` import removed — `execute` no longer reads `ctx` directly (beyond `ctx.ui` via widget).
|
|
147
|
+
- Three new collaborator parameters: `buildSnapshot`, `getModelInfo`, `getSessionInfo`.
|
|
148
|
+
- Calls `resolveSpawnConfig(params, registry, getModelInfo(), settings)`.
|
|
149
|
+
- Calls `buildSnapshot(config.inheritContext)` for the snapshot.
|
|
150
|
+
- Calls `getSessionInfo()` for parent session identity.
|
|
151
|
+
- Passes domain values (not `ctx`) to `runForeground` / `spawnBackground`.
|
|
152
|
+
- `AgentToolManager.spawn` and `spawnAndWait` signatures change to accept `ParentSnapshot`.
|
|
153
|
+
- `AgentToolDeps` stays as a named type (used by test factory) but its fields are destructured in `createAgentTool`.
|
|
154
|
+
|
|
155
|
+
### Modified: `src/tools/foreground-runner.ts`
|
|
156
|
+
|
|
157
|
+
- `ForegroundDeps` interface removed — `runForeground` accepts `manager`, `widget`, `agentActivity` as plain parameters.
|
|
158
|
+
- `ForegroundParams.ctx` removed — replaced by `snapshot`, `parentSessionFile`, `parentSessionId`.
|
|
159
|
+
- `ForegroundManagerDeps.spawnAndWait` signature changes from `ctx: any` to `snapshot: ParentSnapshot`.
|
|
160
|
+
- Individual config fields move into `ResolvedSpawnConfig`.
|
|
161
|
+
|
|
162
|
+
### Modified: `src/tools/background-spawner.ts`
|
|
163
|
+
|
|
164
|
+
- `BackgroundDeps` interface removed — `spawnBackground` accepts `manager`, `widget`, `agentActivity` as plain parameters.
|
|
165
|
+
- `BackgroundParams.ctx` removed — replaced by `snapshot`, `parentSessionFile`, `parentSessionId`.
|
|
166
|
+
- `BackgroundManagerDeps.spawn` signature changes from `ctx: any` to `snapshot: ParentSnapshot`.
|
|
167
|
+
- Individual config fields move into `ResolvedSpawnConfig`.
|
|
168
|
+
|
|
169
|
+
### Modified: `src/agent-manager.ts`
|
|
170
|
+
|
|
171
|
+
- `spawn()` signature changes from `ctx: ExtensionContext` to `snapshot: ParentSnapshot`.
|
|
172
|
+
- `spawnAndWait()` signature changes from `ctx: ExtensionContext` to `snapshot: ParentSnapshot`.
|
|
173
|
+
- Internal `buildParentSnapshot(ctx, ...)` call removed.
|
|
174
|
+
- Imports of `ExtensionContext` and `buildParentSnapshot` removed.
|
|
175
|
+
|
|
176
|
+
### Modified: `src/service-adapter.ts`
|
|
177
|
+
|
|
178
|
+
- `AdapterDeps` interface removed — `createSubagentsService` accepts plain parameters.
|
|
179
|
+
- `AgentManagerLike.spawn` signature changes from `ctx: unknown` to `snapshot: ParentSnapshot`.
|
|
180
|
+
- `spawn()` method calls `buildParentSnapshot(session.ctx, options?.inheritContext)` before delegating.
|
|
181
|
+
- Adds imports of `buildParentSnapshot` and `ParentSnapshot`.
|
|
182
|
+
|
|
183
|
+
### Modified: `src/index.ts`
|
|
184
|
+
|
|
185
|
+
- Wiring for `createAgentTool` adds three collaborator closures: `buildSnapshot`, `getModelInfo`, `getSessionInfo`.
|
|
186
|
+
- `manager.spawn` / `spawnAndWait` wiring adapters removed (closures no longer need to relay `ctx`).
|
|
187
|
+
- Wiring for `createSubagentsService` changes from bag to plain arguments.
|
|
188
|
+
|
|
189
|
+
## Test Impact Analysis
|
|
190
|
+
|
|
191
|
+
### New unit tests enabled
|
|
192
|
+
|
|
193
|
+
- `spawn-config.test.ts` (done) — pure-function tests for `resolveSpawnConfig`.
|
|
194
|
+
|
|
195
|
+
### Existing tests that simplify
|
|
196
|
+
|
|
197
|
+
- `agent-manager.test.ts` — the `vi.mock("../src/parent-snapshot.js")` block is removed.
|
|
198
|
+
All tests pass a plain `ParentSnapshot` object directly instead of `mockCtx`.
|
|
199
|
+
- `foreground-runner.test.ts` — `makeCtx()` helper removed; plain strings for session identity.
|
|
200
|
+
- `background-spawner.test.ts` — same as foreground.
|
|
201
|
+
- `agent-tool.test.ts` — `makeCtx()` simplified; collaborator stubs replace `ctx.model` / `ctx.modelRegistry` reads.
|
|
202
|
+
- `service-adapter.test.ts` — adapter test setup changes from bag to plain parameters.
|
|
203
|
+
|
|
204
|
+
### Existing tests that stay
|
|
205
|
+
|
|
206
|
+
- `parent-snapshot.test.ts` — unchanged; `buildParentSnapshot` is still a standalone pure function.
|
|
207
|
+
|
|
208
|
+
## TDD Order
|
|
209
|
+
|
|
210
|
+
### Step 1: Extract resolveSpawnConfig (done)
|
|
211
|
+
|
|
212
|
+
1. ~~Write `spawn-config.test.ts`, implement `spawn-config.ts`.~~
|
|
213
|
+
Commit: `feat: extract resolveSpawnConfig pure function (#145)` ✓
|
|
214
|
+
|
|
215
|
+
2. ~~Rewire `execute` to call `resolveSpawnConfig`.~~
|
|
216
|
+
Commit: `refactor: use resolveSpawnConfig in execute (#145)` ✓
|
|
217
|
+
|
|
218
|
+
### Step 2: Push ctx out of AgentManager
|
|
219
|
+
|
|
220
|
+
3. Red: update `agent-manager.test.ts` — replace `mockCtx` with a plain `ParentSnapshot` object, remove `vi.mock("../src/parent-snapshot.js")`.
|
|
221
|
+
Green: change `AgentManager.spawn()` and `spawnAndWait()` to accept `ParentSnapshot`.
|
|
222
|
+
Update `agent-tool.ts` manager interface, `service-adapter.ts` to call `buildParentSnapshot` at its boundary, and `index.ts` wiring.
|
|
223
|
+
Commit: `refactor: AgentManager accepts ParentSnapshot instead of ExtensionContext (#145)`
|
|
224
|
+
|
|
225
|
+
### Step 3: Inject collaborators into createAgentTool
|
|
226
|
+
|
|
227
|
+
4. Red: update `agent-tool.test.ts` — add `buildSnapshot`, `getModelInfo`, `getSessionInfo` stubs to `createToolDeps`; simplify `makeCtx()`.
|
|
228
|
+
Green: add three collaborator parameters to `createAgentTool`; rewrite `execute` to use them instead of `ctx.model` / `ctx.modelRegistry` / `ctx.sessionManager`.
|
|
229
|
+
Remove `ExtensionContext` import from `agent-tool.ts`.
|
|
230
|
+
Update `index.ts` wiring to provide closures.
|
|
231
|
+
Commit: `refactor: inject collaborators into createAgentTool, eliminate ctx reads (#145)`
|
|
232
|
+
|
|
233
|
+
### Step 4: Push ctx out of foreground-runner and background-spawner
|
|
234
|
+
|
|
235
|
+
5. Red: update `foreground-runner.test.ts` — remove `makeCtx()`, replace `ForegroundParams.ctx` with `snapshot` / `parentSessionFile` / `parentSessionId`.
|
|
236
|
+
Green: change `ForegroundParams` to use plain domain values, update `runForeground` accordingly.
|
|
237
|
+
Commit: `refactor: foreground-runner receives domain values instead of ctx (#145)`
|
|
238
|
+
|
|
239
|
+
6. Red: update `background-spawner.test.ts` — remove `makeCtx()`, replace `BackgroundParams.ctx` with `snapshot` / `parentSessionFile` / `parentSessionId`.
|
|
240
|
+
Green: change `BackgroundParams` to use plain domain values, update `spawnBackground` accordingly.
|
|
241
|
+
Commit: `refactor: background-spawner receives domain values instead of ctx (#145)`
|
|
242
|
+
|
|
243
|
+
### Step 5: Shrink params bags with ResolvedSpawnConfig
|
|
244
|
+
|
|
245
|
+
7. Red: update `foreground-runner.test.ts` `makeParams()` to use `ResolvedSpawnConfig` fields.
|
|
246
|
+
Green: change `ForegroundParams` to carry `ResolvedSpawnConfig`.
|
|
247
|
+
Update `agent-tool.ts` dispatch to pass the config through.
|
|
248
|
+
Commit: `refactor: ForegroundParams carries ResolvedSpawnConfig (#145)`
|
|
249
|
+
|
|
250
|
+
8. Red: update `background-spawner.test.ts` `makeParams()` to use `ResolvedSpawnConfig` fields.
|
|
251
|
+
Green: change `BackgroundParams` to carry `ResolvedSpawnConfig`.
|
|
252
|
+
Update `agent-tool.ts` dispatch to pass the config through.
|
|
253
|
+
Commit: `refactor: BackgroundParams carries ResolvedSpawnConfig (#145)`
|
|
254
|
+
|
|
255
|
+
### Step 6: Dissolve small dependency bags
|
|
256
|
+
|
|
257
|
+
9. Red: update `foreground-runner.test.ts` calls to pass `manager`, `widget`, `agentActivity` as plain args.
|
|
258
|
+
Green: remove `ForegroundDeps` interface, change `runForeground` signature.
|
|
259
|
+
Commit: `refactor: dissolve ForegroundDeps into plain parameters (#145)`
|
|
260
|
+
|
|
261
|
+
10. Red: update `background-spawner.test.ts` calls to pass plain args.
|
|
262
|
+
Green: remove `BackgroundDeps` interface, change `spawnBackground` signature.
|
|
263
|
+
Commit: `refactor: dissolve BackgroundDeps into plain parameters (#145)`
|
|
264
|
+
|
|
265
|
+
11. Red: update `service-adapter.test.ts` to pass plain parameters instead of `AdapterDeps` bag.
|
|
266
|
+
Green: remove `AdapterDeps` interface, change `createSubagentsService` signature.
|
|
267
|
+
Update `index.ts` wiring call site.
|
|
268
|
+
Commit: `refactor: dissolve AdapterDeps into plain parameters (#145)`
|
|
269
|
+
|
|
270
|
+
12. Refactor: destructure `AgentToolDeps` in `createAgentTool` signature (keep the named type for test factory).
|
|
271
|
+
Commit: `refactor: destructure AgentToolDeps in createAgentTool (#145)`
|
|
272
|
+
|
|
273
|
+
### Step 7: Final verification
|
|
274
|
+
|
|
275
|
+
13. Run full test suite and type check.
|
|
276
|
+
|
|
277
|
+
## Risks and Mitigations
|
|
278
|
+
|
|
279
|
+
| Risk | Mitigation |
|
|
280
|
+
| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
281
|
+
| Wide blast radius — touches 7+ source files and 5+ test files | Incremental TDD steps; each commit leaves the repo green |
|
|
282
|
+
| `service-adapter.ts` now imports `buildParentSnapshot` — new coupling | Acceptable: the adapter is already a boundary module that bridges `ExtensionContext` to domain types |
|
|
283
|
+
| `ResolvedSpawnConfig` could become a new "god object" | It is a pure data return from a single function; consumers destructure what they need |
|
|
284
|
+
| Three new collaborators grow `AgentToolDeps` from 6 to 9 fields | The deps bag is destructured at the signature; the named type exists only for the test factory. The real dependency count stays the same — previously hidden behind `ctx` reads |
|
|
285
|
+
| `index.ts` closures capture `ctx` — stale reference risk | Same pattern `service-adapter.ts` already uses via `runtime.currentCtx`; session lifecycle clears on shutdown |
|
|
286
|
+
|
|
287
|
+
## Open Questions
|
|
288
|
+
|
|
289
|
+
- The exact boundary between fields that stay in `ForegroundParams` / `BackgroundParams` vs. fields that move into `ResolvedSpawnConfig` may shift during implementation.
|
|
290
|
+
The guiding principle: if the field is computed during config resolution, it belongs in `ResolvedSpawnConfig`; if it is dispatch-specific (e.g., `toolCallId`, `signal`, `onUpdate`), it stays in the params type.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
issue: 152
|
|
3
|
+
issue_title: "Add promptSnippet to pi-subagents tools"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Retro: #152 — Add `promptSnippet` to pi-subagents tools
|
|
7
|
+
|
|
8
|
+
## Final Retrospective (2026-05-22)
|
|
9
|
+
|
|
10
|
+
### Session summary
|
|
11
|
+
|
|
12
|
+
Added `promptSnippet` to the `Agent`, `get_subagent_result`, and `steer_subagent` tool registrations in pi-subagents, matching the convention used by pi-github-tools and pi-colgrep.
|
|
13
|
+
The full plan→TDD→ship pipeline completed in one session with zero rework.
|
|
14
|
+
Released as `pi-subagents-v6.14.0`.
|
|
15
|
+
|
|
16
|
+
### Observations
|
|
17
|
+
|
|
18
|
+
#### What went well
|
|
19
|
+
|
|
20
|
+
- Clean single-cycle execution: the issue was unambiguous, the plan correctly scoped it as one TDD step, and the implementation matched the plan exactly.
|
|
21
|
+
- Cross-package convention check (grepping sibling packages for `promptSnippet` usage) confirmed the `"tool_name: One-liner."` format before writing the plan, avoiding any wording rework.
|
|
22
|
+
|
|
23
|
+
#### What caused friction (agent side)
|
|
24
|
+
|
|
25
|
+
No friction points identified.
|
|
26
|
+
The issue was a straightforward property addition with no design decisions, no interface changes, and no downstream breakage.
|
|
27
|
+
|
|
28
|
+
#### What caused friction (user side)
|
|
29
|
+
|
|
30
|
+
No friction points identified.
|
|
31
|
+
|
|
32
|
+
### Changes made
|
|
33
|
+
|
|
34
|
+
1. Created `packages/pi-subagents/docs/retro/0152-add-prompt-snippet.md` (this file).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gotgenes/pi-subagents",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.15.0",
|
|
4
4
|
"exports": {
|
|
5
5
|
".": "./src/service.ts"
|
|
6
6
|
},
|
|
@@ -35,8 +35,7 @@
|
|
|
35
35
|
"@earendil-works/pi-tui": ">=0.75.0"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@sinclair/typebox": "^0.34.49"
|
|
39
|
-
"nanoid": "^5.0.0"
|
|
38
|
+
"@sinclair/typebox": "^0.34.49"
|
|
40
39
|
},
|
|
41
40
|
"engines": {
|
|
42
41
|
"node": ">=22"
|
package/src/agent-manager.ts
CHANGED
|
@@ -8,14 +8,13 @@
|
|
|
8
8
|
|
|
9
9
|
import { randomUUID } from "node:crypto";
|
|
10
10
|
import type { Model } from "@earendil-works/pi-ai";
|
|
11
|
-
import type { AgentSession
|
|
11
|
+
import type { AgentSession } from "@earendil-works/pi-coding-agent";
|
|
12
12
|
import { AgentRecord } from "./agent-record.js";
|
|
13
13
|
import type { AgentRunner } from "./agent-runner.js";
|
|
14
14
|
import { AgentTypeRegistry } from "./agent-types.js";
|
|
15
15
|
import { debugLog } from "./debug.js";
|
|
16
16
|
import { NotificationState } from "./notification-state.js";
|
|
17
17
|
import type { ParentSnapshot } from "./parent-snapshot.js";
|
|
18
|
-
import { buildParentSnapshot } from "./parent-snapshot.js";
|
|
19
18
|
import { subscribeRecordObserver } from "./record-observer.js";
|
|
20
19
|
import type { RunConfig } from "./runtime.js";
|
|
21
20
|
import type { AgentInvocation, IsolationMode, ShellExec, SubagentType, ThinkingLevel } from "./types.js";
|
|
@@ -141,7 +140,7 @@ export class AgentManager {
|
|
|
141
140
|
* If the concurrency limit is reached, the agent is queued.
|
|
142
141
|
*/
|
|
143
142
|
spawn(
|
|
144
|
-
|
|
143
|
+
snapshot: ParentSnapshot,
|
|
145
144
|
type: SubagentType,
|
|
146
145
|
prompt: string,
|
|
147
146
|
options: AgentSpawnConfig,
|
|
@@ -167,7 +166,6 @@ export class AgentManager {
|
|
|
167
166
|
this.observer?.onAgentCreated(record);
|
|
168
167
|
}
|
|
169
168
|
|
|
170
|
-
const snapshot = buildParentSnapshot(ctx, options.inheritContext);
|
|
171
169
|
const args: SpawnArgs = { snapshot, type, prompt, options };
|
|
172
170
|
|
|
173
171
|
if (options.isBackground && !options.bypassQueue && this.runningBackground >= this._getMaxConcurrent()) {
|
|
@@ -332,12 +330,12 @@ export class AgentManager {
|
|
|
332
330
|
* Foreground agents bypass the concurrency queue.
|
|
333
331
|
*/
|
|
334
332
|
async spawnAndWait(
|
|
335
|
-
|
|
333
|
+
snapshot: ParentSnapshot,
|
|
336
334
|
type: SubagentType,
|
|
337
335
|
prompt: string,
|
|
338
336
|
options: Omit<AgentSpawnConfig, "isBackground">,
|
|
339
337
|
): Promise<AgentRecord> {
|
|
340
|
-
const id = this.spawn(
|
|
338
|
+
const id = this.spawn(snapshot, type, prompt, { ...options, isBackground: false });
|
|
341
339
|
const record = this.agents.get(id)!;
|
|
342
340
|
await record.promise;
|
|
343
341
|
return record;
|
|
@@ -430,6 +428,7 @@ export class AgentManager {
|
|
|
430
428
|
}
|
|
431
429
|
|
|
432
430
|
/** Whether any agents are still running or queued. */
|
|
431
|
+
// fallow-ignore-next-line unused-class-member
|
|
433
432
|
hasRunning(): boolean {
|
|
434
433
|
return [...this.agents.values()].some(
|
|
435
434
|
r => r.status === "running" || r.status === "queued",
|
|
@@ -437,6 +436,7 @@ export class AgentManager {
|
|
|
437
436
|
}
|
|
438
437
|
|
|
439
438
|
/** Abort all running and queued agents immediately. */
|
|
439
|
+
// fallow-ignore-next-line unused-class-member
|
|
440
440
|
abortAll(): number {
|
|
441
441
|
let count = 0;
|
|
442
442
|
// Clear queued agents first
|
|
@@ -460,6 +460,7 @@ export class AgentManager {
|
|
|
460
460
|
}
|
|
461
461
|
|
|
462
462
|
/** Wait for all running and queued agents to complete (including queued ones). */
|
|
463
|
+
// fallow-ignore-next-line unused-class-member
|
|
463
464
|
async waitForAll(): Promise<void> {
|
|
464
465
|
// Loop because drainQueue respects the concurrency limit — as running
|
|
465
466
|
// agents finish they start queued ones, which need awaiting too.
|
package/src/handlers/index.ts
CHANGED
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
export {
|
|
2
|
-
|
|
3
|
-
type LifecycleRuntime,
|
|
4
|
-
SessionLifecycleHandler,
|
|
5
|
-
} from "./lifecycle.js";
|
|
6
|
-
export { ToolStartHandler, type ToolStartRuntime } from "./tool-start.js";
|
|
1
|
+
export { SessionLifecycleHandler } from "./lifecycle.js";
|
|
2
|
+
export { ToolStartHandler } from "./tool-start.js";
|
package/src/index.ts
CHANGED
|
@@ -29,6 +29,7 @@ import { SessionLifecycleHandler, ToolStartHandler } from "./handlers/index.js";
|
|
|
29
29
|
import { buildMemoryBlock, buildReadOnlyMemoryBlock } from "./memory.js";
|
|
30
30
|
import { type ModelRegistry, resolveModel } from "./model-resolver.js";
|
|
31
31
|
import { buildEventData, type NotificationDetails, NotificationManager } from "./notification.js";
|
|
32
|
+
import { buildParentSnapshot } from "./parent-snapshot.js";
|
|
32
33
|
import { buildAgentPrompt } from "./prompts.js";
|
|
33
34
|
import { createNotificationRenderer } from "./renderer.js";
|
|
34
35
|
import { createSubagentRuntime } from "./runtime.js";
|
|
@@ -162,12 +163,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
162
163
|
|
|
163
164
|
// Typed service published via Symbol.for() for cross-extension access.
|
|
164
165
|
// Consumers: const { getSubagentsService } = await import("@gotgenes/pi-subagents");
|
|
165
|
-
const service = createSubagentsService(
|
|
166
|
+
const service = createSubagentsService(
|
|
166
167
|
manager,
|
|
167
168
|
resolveModel,
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
() => runtime.currentCtx,
|
|
170
|
+
() => (runtime.currentCtx?.ctx as { modelRegistry?: ModelRegistry } | undefined)?.modelRegistry,
|
|
171
|
+
);
|
|
171
172
|
publishSubagentsService(service);
|
|
172
173
|
|
|
173
174
|
const lifecycle = new SessionLifecycleHandler(
|
|
@@ -193,8 +194,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
193
194
|
|
|
194
195
|
pi.registerTool(defineTool(createAgentTool({
|
|
195
196
|
manager: {
|
|
196
|
-
spawn: (
|
|
197
|
-
spawnAndWait: (
|
|
197
|
+
spawn: (snapshot, type, prompt, opts) => manager.spawn(snapshot, type, prompt, opts),
|
|
198
|
+
spawnAndWait: (snapshot, type, prompt, opts) => manager.spawnAndWait(snapshot, type, prompt, opts),
|
|
198
199
|
resume: (id, prompt, signal) => manager.resume(id, prompt, signal),
|
|
199
200
|
getRecord: (id) => manager.getRecord(id),
|
|
200
201
|
getMaxConcurrent: () => settings.maxConcurrent,
|
|
@@ -209,6 +210,19 @@ export default function (pi: ExtensionAPI) {
|
|
|
209
210
|
registry,
|
|
210
211
|
agentDir: getAgentDir(),
|
|
211
212
|
settings,
|
|
213
|
+
buildSnapshot: (inheritContext) =>
|
|
214
|
+
buildParentSnapshot(
|
|
215
|
+
runtime.currentCtx?.ctx as import("@earendil-works/pi-coding-agent").ExtensionContext,
|
|
216
|
+
inheritContext,
|
|
217
|
+
),
|
|
218
|
+
getModelInfo: () => ({
|
|
219
|
+
parentModel: (runtime.currentCtx?.ctx as any)?.model,
|
|
220
|
+
modelRegistry: (runtime.currentCtx?.ctx as any)?.modelRegistry,
|
|
221
|
+
}),
|
|
222
|
+
getSessionInfo: () => ({
|
|
223
|
+
parentSessionFile: (runtime.currentCtx?.ctx as any)?.sessionManager?.getSessionFile() ?? "",
|
|
224
|
+
parentSessionId: (runtime.currentCtx?.ctx as any)?.sessionManager?.getSessionId() ?? "",
|
|
225
|
+
}),
|
|
212
226
|
})));
|
|
213
227
|
|
|
214
228
|
// ---- get_subagent_result tool ----
|
|
@@ -235,7 +249,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
235
249
|
manager: {
|
|
236
250
|
listAgents: () => manager.listAgents(),
|
|
237
251
|
getRecord: (id) => manager.getRecord(id),
|
|
238
|
-
spawnAndWait: (ctx, type, prompt, opts) => manager.spawnAndWait(ctx, type, prompt, opts),
|
|
252
|
+
spawnAndWait: (ctx, type, prompt, opts) => manager.spawnAndWait(buildParentSnapshot(ctx), type, prompt, opts),
|
|
239
253
|
},
|
|
240
254
|
registry,
|
|
241
255
|
agentActivity: runtime.agentActivity,
|
package/src/service-adapter.ts
CHANGED
|
@@ -5,13 +5,16 @@
|
|
|
5
5
|
* (stripping non-serializable fields), and session gating.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
8
9
|
import type { ModelRegistry } from "./model-resolver.js";
|
|
10
|
+
import type { ParentSnapshot } from "./parent-snapshot.js";
|
|
11
|
+
import { buildParentSnapshot } from "./parent-snapshot.js";
|
|
9
12
|
import type { SubagentRecord, SubagentsService } from "./service.js";
|
|
10
13
|
import type { AgentRecord } from "./types.js";
|
|
11
14
|
|
|
12
15
|
/** Narrow interface for the AgentManager — avoids coupling to the concrete class. */
|
|
13
16
|
export interface AgentManagerLike {
|
|
14
|
-
spawn(
|
|
17
|
+
spawn(snapshot: ParentSnapshot, type: string, prompt: string, options: unknown): string;
|
|
15
18
|
getRecord(id: string): AgentRecord | undefined;
|
|
16
19
|
listAgents(): AgentRecord[];
|
|
17
20
|
abort(id: string): boolean;
|
|
@@ -20,32 +23,27 @@ export interface AgentManagerLike {
|
|
|
20
23
|
queueSteer(id: string, message: string): boolean;
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
/** Dependencies injected into the adapter factory. */
|
|
24
|
-
export interface AdapterDeps {
|
|
25
|
-
manager: AgentManagerLike;
|
|
26
|
-
resolveModel: (input: string, registry: ModelRegistry) => unknown | string;
|
|
27
|
-
getCtx: () => { pi: unknown; ctx: unknown } | undefined;
|
|
28
|
-
getModelRegistry: () => ModelRegistry | undefined;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
26
|
/** Create a SubagentsService backed by the given dependencies. */
|
|
32
|
-
export function createSubagentsService(
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
export function createSubagentsService(
|
|
28
|
+
manager: AgentManagerLike,
|
|
29
|
+
resolveModel: (input: string, registry: ModelRegistry) => unknown | string,
|
|
30
|
+
getCtx: () => { pi: unknown; ctx: unknown } | undefined,
|
|
31
|
+
getModelRegistry: () => ModelRegistry | undefined,
|
|
32
|
+
): SubagentsService {
|
|
35
33
|
return {
|
|
36
34
|
spawn(type: string, prompt: string, options?) {
|
|
37
|
-
const session =
|
|
35
|
+
const session = getCtx();
|
|
38
36
|
if (!session) {
|
|
39
37
|
throw new Error("No active session — cannot spawn agents outside a session.");
|
|
40
38
|
}
|
|
41
39
|
|
|
42
40
|
let model: unknown;
|
|
43
41
|
if (options?.model) {
|
|
44
|
-
const registry =
|
|
42
|
+
const registry = getModelRegistry();
|
|
45
43
|
if (!registry) {
|
|
46
44
|
throw new Error("No model registry available.");
|
|
47
45
|
}
|
|
48
|
-
const resolved =
|
|
46
|
+
const resolved = resolveModel(options.model, registry);
|
|
49
47
|
if (typeof resolved === "string") {
|
|
50
48
|
throw new Error(resolved);
|
|
51
49
|
}
|
|
@@ -55,7 +53,11 @@ export function createSubagentsService(deps: AdapterDeps): SubagentsService {
|
|
|
55
53
|
const description = options?.description ?? prompt.slice(0, 80);
|
|
56
54
|
const isBackground = !(options?.foreground ?? false);
|
|
57
55
|
|
|
58
|
-
|
|
56
|
+
const snapshot = buildParentSnapshot(
|
|
57
|
+
session.ctx as ExtensionContext,
|
|
58
|
+
options?.inheritContext,
|
|
59
|
+
);
|
|
60
|
+
return manager.spawn(snapshot, type, prompt, {
|
|
59
61
|
description,
|
|
60
62
|
model,
|
|
61
63
|
maxTurns: options?.maxTurns,
|