@gotgenes/pi-subagents 6.16.0 → 6.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/docs/architecture/architecture.md +27 -24
- package/docs/plans/0146-narrow-ui-context.md +319 -0
- package/docs/plans/0148-split-agent-widget-rendering.md +255 -0
- package/docs/retro/0144-consolidate-observation-model.md +39 -0
- package/docs/retro/0148-split-agent-widget-rendering.md +39 -0
- package/package.json +1 -1
- package/src/index.ts +19 -13
- package/src/tools/get-result-tool.ts +11 -14
- package/src/tools/steer-tool.ts +12 -15
- package/src/ui/agent-config-editor.ts +63 -67
- package/src/ui/agent-creation-wizard.ts +50 -39
- package/src/ui/agent-menu.ts +118 -74
- package/src/ui/agent-widget.ts +12 -188
- package/src/ui/display.ts +2 -1
- package/src/ui/widget-renderer.ts +236 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,30 @@ 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.16.2](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v6.16.1...pi-subagents-v6.16.2) (2026-05-23)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Documentation
|
|
12
|
+
|
|
13
|
+
* fix plan for narrow UI context ([#146](https://github.com/gotgenes/pi-packages/issues/146)) ([3d5b591](https://github.com/gotgenes/pi-packages/commit/3d5b591c0668ffcd9f66a6fc9a2c5d57236865af))
|
|
14
|
+
* mark Step N complete in architecture doc ([#146](https://github.com/gotgenes/pi-packages/issues/146)) ([9948869](https://github.com/gotgenes/pi-packages/commit/9948869b849817dac6f221f1e90db5e47fd12d31))
|
|
15
|
+
* plan narrow UI context for menu handlers ([#146](https://github.com/gotgenes/pi-packages/issues/146)) ([88318b4](https://github.com/gotgenes/pi-packages/commit/88318b4550fe95fc70b1a9ee1e904c608a2189a3))
|
|
16
|
+
* **retro:** add retro notes for issue [#148](https://github.com/gotgenes/pi-packages/issues/148) ([982fe51](https://github.com/gotgenes/pi-packages/commit/982fe51d7e27b7a127605710ced709bbd6291a0f))
|
|
17
|
+
|
|
18
|
+
## [6.16.1](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v6.16.0...pi-subagents-v6.16.1) (2026-05-23)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Bug Fixes
|
|
22
|
+
|
|
23
|
+
* **pi-subagents:** theme parentheses and separator in formatSessionTokens ([33b67f6](https://github.com/gotgenes/pi-packages/commit/33b67f63915563c41605addb885af52b47844e96))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### Documentation
|
|
27
|
+
|
|
28
|
+
* plan split AgentWidget rendering from lifecycle ([#148](https://github.com/gotgenes/pi-packages/issues/148)) ([24c11d5](https://github.com/gotgenes/pi-packages/commit/24c11d51f2b6c9d2712815fbe46ede72084ffcbb))
|
|
29
|
+
* **retro:** add retro notes for issue [#144](https://github.com/gotgenes/pi-packages/issues/144) ([f3cdfd4](https://github.com/gotgenes/pi-packages/commit/f3cdfd46fe223d6cecb5dad0d739f053e7468433))
|
|
30
|
+
* update architecture for widget rendering extraction ([#148](https://github.com/gotgenes/pi-packages/issues/148)) ([450707e](https://github.com/gotgenes/pi-packages/commit/450707e1d0f41ae78f1a655ab350fd8f4fd64125))
|
|
31
|
+
|
|
8
32
|
## [6.16.0](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v6.15.0...pi-subagents-v6.16.0) (2026-05-23)
|
|
9
33
|
|
|
10
34
|
|
|
@@ -69,7 +69,8 @@ renderer.ts - notification TUI component
|
|
|
69
69
|
record-observer.ts - session-event observer for record statistics
|
|
70
70
|
|
|
71
71
|
ui/display.ts - pure formatters, display helpers, and shared types (Theme, AgentDetails)
|
|
72
|
-
ui/agent-widget.ts - above-editor live status widget
|
|
72
|
+
ui/agent-widget.ts - above-editor live status widget (thin lifecycle wrapper)
|
|
73
|
+
ui/widget-renderer.ts - pure rendering functions for agent widget
|
|
73
74
|
ui/agent-menu.ts - /agents slash command menu
|
|
74
75
|
ui/conversation-viewer.ts - scrollable session overlay
|
|
75
76
|
ui/ui-observer.ts - session-event observer for UI streaming
|
|
@@ -615,20 +616,20 @@ Phase 9 targets the next layer: observation model consolidation, `ExtensionConte
|
|
|
615
616
|
|
|
616
617
|
### Current smells
|
|
617
618
|
|
|
618
|
-
| Smell | Location
|
|
619
|
-
| ------------------------------------------------ |
|
|
620
|
-
| `execute` does config resolution for its callees | `agent-tool.ts` (145-line `execute`)
|
|
621
|
-
| Wide `ctx` in menu handlers
|
|
622
|
-
| Direct SDK import in `conversation-viewer.ts` | `conversation-viewer.test.ts`
|
|
623
|
-
| Widget mixes rendering, lifecycle, and state
|
|
624
|
-
| `deps.` prefix noise in function bodies | remaining modules across tools, UI, service-adapter
|
|
619
|
+
| Smell | Location | Evidence | Severity |
|
|
620
|
+
| ------------------------------------------------ | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------- |
|
|
621
|
+
| `execute` does config resolution for its callees | `agent-tool.ts` (145-line `execute`) | ~60 lines unpack config, resolve model, compute metadata, repack into 16-field bags for spawners; `ctx` threaded 4 layers deep | Medium |
|
|
622
|
+
| ~~Wide `ctx` in menu handlers~~ | ~~`agent-menu.ts`, `agent-config-editor.ts`, `agent-creation-wizard.ts`~~ | Resolved by #146: `MenuUI` interface introduced; 42 `ctx as any` casts eliminated across 5 test files | Done |
|
|
623
|
+
| Direct SDK import in `conversation-viewer.ts` | `conversation-viewer.test.ts` | Hoisted `vi.mock("@earendil-works/pi-tui")` to intercept `wrapTextWithAnsi` | Low |
|
|
624
|
+
| ~~Widget mixes rendering, lifecycle, and state~~ | ~~`agent-widget.ts` (370 lines)~~ | Resolved by #148: rendering extracted to `widget-renderer.ts`; widget is now 198 lines | Done |
|
|
625
|
+
| `deps.` prefix noise in function bodies | remaining modules across tools, UI, service-adapter | Functions accept a `deps` bag and access every field as `deps.foo`; hides real dependencies and lengthens every call line | Low |
|
|
625
626
|
|
|
626
627
|
### Dependency bag convention
|
|
627
628
|
|
|
628
629
|
Applied incrementally as each step touches a module:
|
|
629
630
|
|
|
630
|
-
- **≤4 fields**
|
|
631
|
-
- **≥5 fields**
|
|
631
|
+
- **≤4 fields** - accept as plain parameters; drop the interface.
|
|
632
|
+
- **≥5 fields** - keep a named interface but destructure in the function signature (`{ manager, widget }: ForegroundDeps`) so the function body uses bare names, not `deps.foo`.
|
|
632
633
|
|
|
633
634
|
This eliminates the `deps.` prefix noise across ~124 callsites in 12 modules.
|
|
634
635
|
|
|
@@ -664,19 +665,23 @@ After this step, `ExtensionContext` appears only in:
|
|
|
664
665
|
|
|
665
666
|
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.
|
|
666
667
|
|
|
667
|
-
### Step N: Narrow UI context for menu handlers (#146)
|
|
668
|
+
### Step N: Narrow UI context for menu handlers (#146) ✓
|
|
668
669
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
`index.ts` passes `ctx.ui`
|
|
670
|
+
Defined `MenuUI` interface (exported from `agent-menu.ts`) with `select`, `confirm`, `input`, `notify`, `editor`, and `custom` methods — the exact subset `ctx.ui` methods used by menu handlers.
|
|
671
|
+
All inner functions in `agent-menu.ts`, `agent-config-editor.ts`, and `agent-creation-wizard.ts` now accept `(ui: MenuUI)` instead of `(ctx: ExtensionContext)`.
|
|
672
|
+
`index.ts` passes `ctx.ui`, `ctx.modelRegistry`, and `buildParentSnapshot(ctx)` to the handler.
|
|
672
673
|
|
|
673
|
-
|
|
674
|
+
`AgentMenuManager.spawnAndWait` and `WizardManager.spawnAndWait` both accept `ParentSnapshot` (enabled by Step M).
|
|
675
|
+
Creation wizard threads `parentSnapshot` from `showCreateWizard(ui, parentSnapshot)` → `showGenerateWizard(ui, parentSnapshot, targetDir)` → `manager.spawnAndWait(parentSnapshot, ...)`.
|
|
674
676
|
|
|
675
|
-
|
|
677
|
+
Applied the dependency bag convention:
|
|
676
678
|
|
|
677
|
-
|
|
679
|
+
- `AgentConfigEditorDeps` (4 fields), `GetResultDeps` (4 fields), `SteerToolDeps` (4 fields) dissolved into plain parameters.
|
|
680
|
+
- `AgentMenuDeps` (8 fields) and `AgentCreationWizardDeps` (5 fields) kept as interfaces, destructured in the function signature.
|
|
678
681
|
|
|
679
|
-
|
|
682
|
+
After Steps M and N, `ExtensionContext` appears only at true boundaries: `index.ts` closures and `service-adapter.ts` (cross-extension bridge).
|
|
683
|
+
|
|
684
|
+
Impact: eliminated 42 `ctx as any` casts across 5 test files (`agent-menu.test.ts`: 8, `agent-config-editor.test.ts`: 20, `agent-creation-wizard.test.ts`: 14); tests construct plain `MenuUI`-shaped objects with no cast.
|
|
680
685
|
|
|
681
686
|
### Step O: Inject text wrapping into ConversationViewer (#147)
|
|
682
687
|
|
|
@@ -688,13 +693,11 @@ Apply the dependency bag convention: `ConversationViewerOptions` is destructured
|
|
|
688
693
|
|
|
689
694
|
Impact: eliminates the hoisted `vi.mock("@earendil-works/pi-tui")` in `conversation-viewer.test.ts`.
|
|
690
695
|
|
|
691
|
-
### Step P: Split AgentWidget rendering (#148)
|
|
692
|
-
|
|
693
|
-
Extract pure rendering functions from `AgentWidget` into `ui/widget-renderer.ts`.
|
|
694
|
-
The widget becomes a thin lifecycle/polling wrapper that calls pure render functions.
|
|
695
|
-
Rendering functions receive data (agent list, activity map, registry) and return formatted strings - testable without widget lifecycle.
|
|
696
|
+
### Step P: Split AgentWidget rendering (#148) ✓
|
|
696
697
|
|
|
697
|
-
|
|
698
|
+
Extracted pure rendering functions (`renderWidgetLines`, `renderFinishedLine`, `renderRunningLines`) from `AgentWidget` into `ui/widget-renderer.ts`.
|
|
699
|
+
The widget is now a thin lifecycle/polling wrapper (198 lines, down from 374) that delegates to pure render functions.
|
|
700
|
+
Rendering functions receive data (agent list, activity map, registry) and return formatted strings - testable without widget lifecycle. 23 new unit tests cover all status variants, overflow, tree connectors, and empty states.
|
|
698
701
|
|
|
699
702
|
### Step dependencies
|
|
700
703
|
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
---
|
|
2
|
+
issue: 146
|
|
3
|
+
issue_title: "Narrow UI context for menu handlers (Phase 9, Step N)"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Narrow UI context for menu handlers
|
|
7
|
+
|
|
8
|
+
## Problem Statement
|
|
9
|
+
|
|
10
|
+
Menu handler functions (`showAgentsMenu`, `showAgentDetail`, `showCreateWizard`, etc.) declare `ctx: ExtensionContext` but only call `ctx.ui.select/confirm/input/notify/editor/custom` and `ctx.modelRegistry`.
|
|
11
|
+
This forces 42 `ctx as any` casts across 3 test files (`agent-menu.test.ts`: 8, `agent-config-editor.test.ts`: 20, `agent-creation-wizard.test.ts`: 14) because tests cannot construct a full `ExtensionContext`.
|
|
12
|
+
|
|
13
|
+
## Goals
|
|
14
|
+
|
|
15
|
+
- Define a `MenuUI` interface with the subset of `ctx.ui` methods that menu handlers actually use (`select`, `confirm`, `input`, `notify`, `editor`, `custom`).
|
|
16
|
+
- Menu handler functions accept `MenuUI` (plus `modelRegistry` passed separately) instead of `ExtensionContext`.
|
|
17
|
+
- `index.ts` handler registration extracts `ctx.ui` and `ctx.modelRegistry` from the SDK `ExtensionContext`.
|
|
18
|
+
- Change `WizardManager.spawnAndWait` to accept `ParentSnapshot` (introduced by #145) instead of `ExtensionContext`.
|
|
19
|
+
- Apply dependency bag convention: dissolve ≤4-field deps into plain parameters; keep ≥5-field interfaces but destructure in signature.
|
|
20
|
+
- Eliminate all 42 `ctx as any` casts from menu, editor, and wizard test files.
|
|
21
|
+
|
|
22
|
+
## Non-Goals
|
|
23
|
+
|
|
24
|
+
- Changing the behavior of `ctx.ui.custom` — pass-through only.
|
|
25
|
+
- Narrowing `ExtensionContext` usage in `index.ts` closures (the `as any` casts for `runtime.currentCtx?.ctx` are addressed separately).
|
|
26
|
+
- Injecting `modelRegistry` further (already a narrow interface from `model-resolver.ts`).
|
|
27
|
+
|
|
28
|
+
## Background
|
|
29
|
+
|
|
30
|
+
### Dependency: #145 (Step M) — Decompose execute
|
|
31
|
+
|
|
32
|
+
Issue #145 is **closed/implemented**.
|
|
33
|
+
`buildParentSnapshot(ctx)` converts `ExtensionContext` → `ParentSnapshot` at the call site.
|
|
34
|
+
This enables `WizardManager.spawnAndWait` to accept `ParentSnapshot` instead of `ExtensionContext`.
|
|
35
|
+
|
|
36
|
+
### Existing modules
|
|
37
|
+
|
|
38
|
+
- `agent-menu.ts` (296 lines) — menu handler factory, 8-field `AgentMenuDeps`, all inner functions take `ctx: ExtensionContext`
|
|
39
|
+
- `agent-config-editor.ts` (202 lines) — `AgentConfigEditorDeps` (4 fields), `showAgentDetail` takes `ctx: ExtensionContext`
|
|
40
|
+
- `agent-creation-wizard.ts` (246 lines) — `AgentCreationWizardDeps` (5 fields), `WizardManager.spawnAndWait` takes `ctx: ExtensionContext`
|
|
41
|
+
- `tools/get-result-tool.ts` — `GetResultDeps` (4 fields)
|
|
42
|
+
- `tools/steer-tool.ts` — `SteerToolDeps` (4 fields)
|
|
43
|
+
- `index.ts` — wires everything, handler registration extracts `ctx.ui` and passes `ExtensionContext`
|
|
44
|
+
|
|
45
|
+
### ExtensionContext usage in menu handlers
|
|
46
|
+
|
|
47
|
+
Every `ctx` reference in the three menu UI modules maps to exactly one of:
|
|
48
|
+
|
|
49
|
+
- `ctx.ui.select(...)` — 9 call sites
|
|
50
|
+
- `ctx.ui.confirm(...)` — 5 call sites
|
|
51
|
+
- `ctx.ui.input(...)` — 7 call sites
|
|
52
|
+
- `ctx.ui.notify(...)` — 15 call sites
|
|
53
|
+
- `ctx.ui.editor(...)` — 2 call sites
|
|
54
|
+
- `ctx.ui.custom(...)` — 1 call site (conversation viewer overlay)
|
|
55
|
+
- `ctx.modelRegistry` — 1 call site (model label resolution in `showAllAgentsList`)
|
|
56
|
+
|
|
57
|
+
No other `ExtensionContext` properties (session, tools, hooks, etc.) are accessed.
|
|
58
|
+
|
|
59
|
+
## Design Overview
|
|
60
|
+
|
|
61
|
+
### MenuUI interface
|
|
62
|
+
|
|
63
|
+
A narrow interface capturing only the `ctx.ui` methods used by menu handlers:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
export interface MenuUI {
|
|
67
|
+
select(title: string, options: string[]): Promise<string | undefined>;
|
|
68
|
+
confirm(title: string, message: string): Promise<boolean>;
|
|
69
|
+
input(title: string, defaultValue?: string): Promise<string | undefined>;
|
|
70
|
+
notify(message: string, level: "info" | "warning" | "error"): void;
|
|
71
|
+
editor(title: string, content: string): Promise<string | undefined>;
|
|
72
|
+
custom<R>(component: any, options?: any): Promise<R>;
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`select` uses a plain `string` return (not a generic `<T extends string>`) to match the SDK's structural signature.
|
|
77
|
+
|
|
78
|
+
`modelRegistry` is not included in `MenuUI` — it is not a UI concern.
|
|
79
|
+
Instead, the handler registration in `index.ts` passes it separately.
|
|
80
|
+
|
|
81
|
+
### Handler signature change
|
|
82
|
+
|
|
83
|
+
The menu handler currently receives `ExtensionContext` directly:
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// index.ts — before
|
|
87
|
+
handler: async (_args, ctx) => { await agentsMenuHandler(ctx); },
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
After this change, `index.ts` destructures what each handler needs:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// index.ts — after
|
|
94
|
+
handler: async (_args, ctx) => {
|
|
95
|
+
await agentsMenuHandler({
|
|
96
|
+
ui: ctx.ui,
|
|
97
|
+
modelRegistry: ctx.modelRegistry,
|
|
98
|
+
parentSnapshot: buildParentSnapshot(ctx),
|
|
99
|
+
});
|
|
100
|
+
},
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
In `agent-menu.ts`, the return type changes from `(ctx: ExtensionContext) => Promise<void>` to a function that accepts `{ ui: MenuUI; modelRegistry: ModelRegistry; parentSnapshot: ParentSnapshot }`.
|
|
104
|
+
The `ExtensionContext` import is removed from `agent-menu.ts`, `agent-config-editor.ts`, and `agent-creation-wizard.ts`.
|
|
105
|
+
|
|
106
|
+
`modelRegistry` is threaded from the handler through `showAgentsMenu` → `showAllAgentsList` (the only consumer).
|
|
107
|
+
`parentSnapshot` is threaded from the handler through `showAgentsMenu` → `wizard.showCreateWizard` → `showGenerateWizard` (the only consumer).
|
|
108
|
+
|
|
109
|
+
### Wizard spawnAndWait — drop ctx parameter
|
|
110
|
+
|
|
111
|
+
`WizardManager.spawnAndWait` currently takes `ctx: ExtensionContext` as its first parameter and passes it to `deps.manager.spawnAndWait(ctx, ...)`.
|
|
112
|
+
Once the menu handler no longer receives `ExtensionContext`, the wizard has no `ctx` to pass.
|
|
113
|
+
|
|
114
|
+
Thread `parentSnapshot` as a parameter from the handler through the wizard, keeping `AgentMenuManager.spawnAndWait` accepting `ParentSnapshot` as its first parameter (consistent with `AgentManager.spawnAndWait`).
|
|
115
|
+
The wizard's `showGenerateWizard` receives `parentSnapshot` and passes it to `deps.manager.spawnAndWait(parentSnapshot, ...)`.
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// agent-creation-wizard.ts — after
|
|
119
|
+
async function showGenerateWizard(
|
|
120
|
+
ui: MenuUI,
|
|
121
|
+
parentSnapshot: ParentSnapshot,
|
|
122
|
+
targetDir: string,
|
|
123
|
+
) {
|
|
124
|
+
// ...
|
|
125
|
+
const record = await deps.manager.spawnAndWait(
|
|
126
|
+
parentSnapshot, "general-purpose", generatePrompt, { ... },
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The creation wizard no longer imports `ExtensionContext`.
|
|
132
|
+
|
|
133
|
+
### Dependency bag convention
|
|
134
|
+
|
|
135
|
+
Per `docs/architecture/architecture.md` § Dependency bag convention:
|
|
136
|
+
|
|
137
|
+
- **≤4 fields** → dissolve the interface, accept as plain parameters.
|
|
138
|
+
- **≥5 fields** → keep the interface but destructure in the function signature.
|
|
139
|
+
|
|
140
|
+
#### Dissolve (≤4 fields)
|
|
141
|
+
|
|
142
|
+
`AgentConfigEditorDeps` (4 fields: `fileOps`, `registry`, `personalAgentsDir`, `projectAgentsDir`) → plain parameters on `createAgentConfigEditor`.
|
|
143
|
+
|
|
144
|
+
`GetResultDeps` (4 fields: `getRecord`, `cancelNudge`, `getConversation`, `registry`) → plain parameters on `createGetResultTool`.
|
|
145
|
+
|
|
146
|
+
`SteerToolDeps` (4 fields: `getRecord`, `emitEvent`, `steerAgent`, `queueSteer`) → plain parameters on `createSteerTool`.
|
|
147
|
+
|
|
148
|
+
#### Keep + destructure (≥5 fields)
|
|
149
|
+
|
|
150
|
+
`AgentMenuDeps` (8 fields) — keep the interface, destructure in `createAgentsMenuHandler({ manager, registry, ... })`.
|
|
151
|
+
|
|
152
|
+
`AgentCreationWizardDeps` (5 fields) — keep the interface, destructure in `createAgentCreationWizard({ fileOps, manager, ... })`.
|
|
153
|
+
|
|
154
|
+
### Consumer call-site sketch (menu handler registration)
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
// index.ts
|
|
158
|
+
pi.registerCommand('agents', {
|
|
159
|
+
description: 'Manage agents',
|
|
160
|
+
handler: async (_args, ctx) => {
|
|
161
|
+
await agentsMenuHandler({
|
|
162
|
+
ui: ctx.ui,
|
|
163
|
+
modelRegistry: ctx.modelRegistry,
|
|
164
|
+
parentSnapshot: buildParentSnapshot(ctx),
|
|
165
|
+
});
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Extracted module interaction sketch (agent-config-editor)
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// agent-config-editor.ts — after dissolving deps
|
|
174
|
+
export function createAgentConfigEditor(
|
|
175
|
+
fileOps: AgentFileOps,
|
|
176
|
+
registry: AgentTypeRegistry,
|
|
177
|
+
personalAgentsDir: string,
|
|
178
|
+
projectAgentsDir: string,
|
|
179
|
+
) {
|
|
180
|
+
// ... closures capture these directly; no deps.foo indirection
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
No Tell-Don't-Ask violations — each parameter is a primitive or injectable collaborator.
|
|
185
|
+
No output-argument mutations — pure closure capture.
|
|
186
|
+
|
|
187
|
+
## Module-Level Changes
|
|
188
|
+
|
|
189
|
+
### New file: none
|
|
190
|
+
|
|
191
|
+
All changes are modifications to existing files.
|
|
192
|
+
|
|
193
|
+
### Modified: `src/ui/agent-menu.ts`
|
|
194
|
+
|
|
195
|
+
- Add `MenuUI` interface export (the new narrow type).
|
|
196
|
+
- Import `ModelRegistry` from `model-resolver.js`.
|
|
197
|
+
- Remove `ExtensionContext` import.
|
|
198
|
+
- Change all inner function signatures from `(ctx: ExtensionContext)` to `(ui: MenuUI)`.
|
|
199
|
+
- Replace `ctx.ui.xxx(...)` → `ui.xxx(...)`.
|
|
200
|
+
- Replace `ctx.modelRegistry` → parameter `modelRegistry` threaded to `showAllAgentsList`.
|
|
201
|
+
- Change `AgentMenuDeps` usage: destructure in `createAgentsMenuHandler` signature.
|
|
202
|
+
- Change return type from `(ctx: ExtensionContext) => Promise<void>` to `(params: { ui: MenuUI; modelRegistry: ModelRegistry; parentSnapshot: ParentSnapshot }) => Promise<void>`.
|
|
203
|
+
- Thread `modelRegistry` from handler through `showAgentsMenu` → `showAllAgentsList`.
|
|
204
|
+
- Thread `parentSnapshot` from handler through `showAgentsMenu` → `wizard.showCreateWizard` → `showGenerateWizard`.
|
|
205
|
+
- Update `AgentMenuManager.spawnAndWait` to accept `ParentSnapshot` instead of `ExtensionContext`.
|
|
206
|
+
- Remove `Omit<AgentSpawnConfig, "isBackground">` in favor of plain inline type.
|
|
207
|
+
|
|
208
|
+
### Modified: `src/ui/agent-config-editor.ts`
|
|
209
|
+
|
|
210
|
+
- Remove `ExtensionContext` import.
|
|
211
|
+
- Add `MenuUI` import from `agent-menu.js`.
|
|
212
|
+
- Change all inner function signatures from `(ctx: ExtensionContext)` to `(ui: MenuUI)`.
|
|
213
|
+
- Replace `ctx.ui.xxx(...)` → `ui.xxx(...)`.
|
|
214
|
+
- Dissolve `AgentConfigEditorDeps`: replace single deps parameter with 4 plain parameters.
|
|
215
|
+
|
|
216
|
+
### Modified: `src/ui/agent-creation-wizard.ts`
|
|
217
|
+
|
|
218
|
+
- Remove `ExtensionContext` import.
|
|
219
|
+
- Add `MenuUI` import from `agent-menu.js`.
|
|
220
|
+
- Add `ParentSnapshot` import from `parent-snapshot.js`.
|
|
221
|
+
- Change all inner function signatures from `(ctx: ExtensionContext)` to `(ui: MenuUI)`.
|
|
222
|
+
- Replace `ctx.ui.xxx(...)` → `ui.xxx(...)`.
|
|
223
|
+
- Change `WizardManager.spawnAndWait` to accept `ParentSnapshot` instead of `ExtensionContext`.
|
|
224
|
+
- Thread `parentSnapshot` as a parameter from `showCreateWizard(ui, parentSnapshot)` → `showGenerateWizard(ui, parentSnapshot, targetDir)`.
|
|
225
|
+
- Destructure `AgentCreationWizardDeps` in signature.
|
|
226
|
+
|
|
227
|
+
### Modified: `src/tools/get-result-tool.ts`
|
|
228
|
+
|
|
229
|
+
- Dissolve `GetResultDeps`: replace single deps parameter with 4 plain parameters.
|
|
230
|
+
|
|
231
|
+
### Modified: `src/tools/steer-tool.ts`
|
|
232
|
+
|
|
233
|
+
- Dissolve `SteerToolDeps`: replace single deps parameter with 4 plain parameters.
|
|
234
|
+
|
|
235
|
+
### Modified: `src/index.ts`
|
|
236
|
+
|
|
237
|
+
- Update `createAgentConfigEditor` call: pass 4 plain args instead of `AgentConfigEditorDeps`.
|
|
238
|
+
- Update `createAgentCreationWizard` call: pass 4 plain args instead of `AgentCreationWizardDeps` (registry is the `WizardRegistry`, not the full `AgentTypeRegistry` — pass `{ reload: () => registry.reload() }`).
|
|
239
|
+
- Update `createGetResultTool` call: pass 4 plain args instead of `GetResultDeps`.
|
|
240
|
+
- Update `createSteerTool` call: pass 4 plain args instead of `SteerToolDeps`.
|
|
241
|
+
- Update `spawnAndWait` in menu handler deps: keep `ParentSnapshot` as first parameter.
|
|
242
|
+
- Update `/agents` command handler to destructure `ctx.ui`, `ctx.modelRegistry`, and `buildParentSnapshot(ctx)`.
|
|
243
|
+
|
|
244
|
+
### Modified: test files
|
|
245
|
+
|
|
246
|
+
- `test/ui/agent-menu.test.ts` — remove `ctx as any` casts; pass `{ ui: { ... }, modelRegistry: {}, parentSnapshot: {} }`.
|
|
247
|
+
- `test/ui/agent-config-editor.test.ts` — remove `ctx as any` casts; pass `MenuUI` objects directly.
|
|
248
|
+
- `test/ui/agent-creation-wizard.test.ts` — remove `ctx as any` casts; pass `MenuUI` and stub `ParentSnapshot`.
|
|
249
|
+
- `test/tools/get-result-tool.test.ts` — update `makeDeps` and `execute` helpers for dissolved parameters.
|
|
250
|
+
- `test/tools/steer-tool.test.ts` — update `makeDeps` and `execute` helpers for dissolved parameters.
|
|
251
|
+
|
|
252
|
+
### Unchanged
|
|
253
|
+
|
|
254
|
+
- `src/ui/conversation-viewer.ts` — unrelated; uses its own deps.
|
|
255
|
+
- `src/ui/agent-widget.ts` — already narrow (no `ExtensionContext`).
|
|
256
|
+
- `src/agent-manager.ts` — already accepts `ParentSnapshot` from #145.
|
|
257
|
+
- `src/parent-snapshot.ts` — unchanged.
|
|
258
|
+
|
|
259
|
+
## Test Impact Analysis
|
|
260
|
+
|
|
261
|
+
1. **New unit tests enabled:** None — this is a signature change, not an extraction.
|
|
262
|
+
The existing test coverage already exercises menu navigation, editing, creation, and tool operations.
|
|
263
|
+
|
|
264
|
+
2. **Existing tests that simplify:** All 42 `ctx as any` casts are removed from the three test files.
|
|
265
|
+
`makeCtx()` returns a plain `MenuUI`-shaped object (already structurally compatible).
|
|
266
|
+
The `makeCtx` helper in `agent-menu.test.ts` already returns the right shape — it just needs the cast removed and the handler-call interface updated.
|
|
267
|
+
|
|
268
|
+
3. **Tests that must stay:** All existing test assertions stay — only the method of constructing the handler input changes.
|
|
269
|
+
`get-result-tool.test.ts` and `steer-tool.test.ts` may need minor updates if the deps dissolve changes the factory call signature, but no assertion changes.
|
|
270
|
+
|
|
271
|
+
## TDD Order
|
|
272
|
+
|
|
273
|
+
Each step must leave `pnpm run check` green.
|
|
274
|
+
When a step changes a factory signature, it must also update the corresponding `index.ts` call site in the same commit.
|
|
275
|
+
|
|
276
|
+
1. **Refactor:** Define and export `MenuUI` interface in `agent-menu.ts`.
|
|
277
|
+
No other changes — just add the interface alongside the existing code.
|
|
278
|
+
Commit: `refactor: add MenuUI interface (#146)`
|
|
279
|
+
|
|
280
|
+
2. **Refactor:** Update `agent-config-editor.ts` — dissolve `AgentConfigEditorDeps` into 4 plain parameters; change `showAgentDetail(ctx)` to `showAgentDetail(ui: MenuUI)`; replace `ctx.ui.xxx` → `ui.xxx`.
|
|
281
|
+
Update `agent-config-editor.test.ts` — remove `ctx as any` casts, pass `MenuUI` objects directly.
|
|
282
|
+
Update `index.ts` — update `createAgentConfigEditor` call to pass 4 plain args.
|
|
283
|
+
Commit: `refactor: dissolve AgentConfigEditorDeps and narrow to MenuUI (#146)`
|
|
284
|
+
|
|
285
|
+
3. **Refactor:** Update `agent-creation-wizard.ts` — destructure `AgentCreationWizardDeps`; change `showCreateWizard(ctx)` to `showCreateWizard(ui: MenuUI, parentSnapshot: ParentSnapshot)`; thread `parentSnapshot` to `showGenerateWizard`; change `WizardManager.spawnAndWait` to accept `ParentSnapshot`; replace `ctx.ui.xxx` → `ui.xxx`.
|
|
286
|
+
Update `agent-creation-wizard.test.ts` — remove `ctx as any` casts, pass `MenuUI` and stub `ParentSnapshot`.
|
|
287
|
+
Update `index.ts` — update `createAgentCreationWizard` call for destructured params.
|
|
288
|
+
Commit: `refactor: narrow creation wizard to MenuUI and ParentSnapshot (#146)`
|
|
289
|
+
|
|
290
|
+
4. **Refactor:** Update `agent-menu.ts` — destructure `AgentMenuDeps`; change handler return type to accept `{ ui: MenuUI; modelRegistry: ModelRegistry; parentSnapshot: ParentSnapshot }`; thread `modelRegistry` to `showAllAgentsList`; thread `parentSnapshot` to `wizard.showCreateWizard`; update `AgentMenuManager.spawnAndWait` to accept `ParentSnapshot`; replace `ctx.ui.xxx` → `ui.xxx`.
|
|
291
|
+
Update `agent-menu.test.ts` — remove `ctx as any` casts, pass `{ ui, modelRegistry, parentSnapshot }`.
|
|
292
|
+
Update `index.ts` — update `/agents` handler to destructure `ctx.ui`, `ctx.modelRegistry`, and `buildParentSnapshot(ctx)`.
|
|
293
|
+
Commit: `refactor: narrow agent menu to MenuUI interface (#146)`
|
|
294
|
+
|
|
295
|
+
5. **Refactor:** Update `get-result-tool.ts` — dissolve `GetResultDeps` into 4 plain parameters.
|
|
296
|
+
Update `test/tools/get-result-tool.test.ts` — update `makeDeps` and `execute` helpers.
|
|
297
|
+
Update `index.ts` — update `createGetResultTool` call to pass 4 plain args.
|
|
298
|
+
Commit: `refactor: dissolve GetResultDeps into plain parameters (#146)`
|
|
299
|
+
|
|
300
|
+
6. **Refactor:** Update `steer-tool.ts` — dissolve `SteerToolDeps` into 4 plain parameters.
|
|
301
|
+
Update `test/tools/steer-tool.test.ts` — update `makeDeps` and `execute` helpers.
|
|
302
|
+
Update `index.ts` — update `createSteerTool` call to pass 4 plain args.
|
|
303
|
+
Commit: `refactor: dissolve SteerToolDeps into plain parameters (#146)`
|
|
304
|
+
|
|
305
|
+
7. **Verify:** Run full test suite (`pnpm vitest run`) and type check (`pnpm run check`).
|
|
306
|
+
Confirm zero `ctx as any` in the three menu test files.
|
|
307
|
+
Commit: none (verification only).
|
|
308
|
+
|
|
309
|
+
## Risks and Mitigations
|
|
310
|
+
|
|
311
|
+
| Risk | Mitigation |
|
|
312
|
+
| ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
313
|
+
| `ctx.ui.custom` signature mismatch between `MenuUI` and real `ExtensionContext.ui` | `MenuUI.custom` uses `any` for the component and options parameters since these are opaque TUI types internal to the SDK. This matches the existing usage where `ctx.ui.custom<undefined>(...)` passes a TUI component constructor. |
|
|
314
|
+
| `ParentSnapshot` threading through menu → wizard call chain | The handler receives `parentSnapshot` from `index.ts` and threads it through `showAgentsMenu` → `showCreateWizard` → `showGenerateWizard`. Only `showGenerateWizard` uses it; the other functions relay it. This is acceptable since the parameter follows the existing `targetDir` threading pattern already in the wizard. |
|
|
315
|
+
| Deps dissolution breaks `index.ts` type check mid-sequence | Each TDD step updates the factory, its test file, AND the `index.ts` call site together, keeping `pnpm run check` green after every commit. |
|
|
316
|
+
|
|
317
|
+
## Open Questions
|
|
318
|
+
|
|
319
|
+
- None — the design follows the architecture doc's Step N specification and the dependency (#145) is already implemented.
|