@ferris1225/pi-subagents 4.1.12 → 4.1.13
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/README.md +6 -3
- package/package.json +55 -55
- package/src/setup.ts +109 -15
package/README.md
CHANGED
|
@@ -203,7 +203,9 @@ Each agent runs on the current main model or one picked in `/subagents-setup`
|
|
|
203
203
|
or fails at the provider level, the **same retained session** continues on the
|
|
204
204
|
main model — finished searches, reads, and edits are preserved; ordinary task
|
|
205
205
|
failures do not trigger a handoff. Thinking defaults to **Auto**: the role's
|
|
206
|
-
preference, clamped to what the effective model supports.
|
|
206
|
+
preference, clamped to what the effective model supports. `/subagents-setup` →
|
|
207
|
+
*Configure an agent* also offers a manual strength per agent, listing only the
|
|
208
|
+
levels that model supports. There is no separate
|
|
207
209
|
vision mode: assign a multimodal model and name the image paths in the task.
|
|
208
210
|
|
|
209
211
|
Every dispatch, managed stage, resume, retry, and fallback snapshots the
|
|
@@ -216,8 +218,9 @@ stripped so children stay leaves. An empty snapshot starts the child with
|
|
|
216
218
|
|
|
217
219
|
## Configuration
|
|
218
220
|
|
|
219
|
-
`/subagents-setup` stays one level deep: enabled agents, per-agent models
|
|
220
|
-
the delegation-injection toggle. Everything else is
|
|
221
|
+
`/subagents-setup` stays one level deep: enabled agents, per-agent models and
|
|
222
|
+
thinking strengths, and the delegation-injection toggle. Everything else is
|
|
223
|
+
config-file only, stored at
|
|
221
224
|
`~/.pi/agent/pi-subagents.json` (follows `PI_CODING_AGENT_DIR`):
|
|
222
225
|
|
|
223
226
|
```json
|
package/package.json
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@ferris1225/pi-subagents",
|
|
3
|
-
"version": "4.1.
|
|
4
|
-
"description": "A managed sub-agent team for pi: specialized roles, pre-commit documentation sync, retained threads, auto-fix chains, model fallback, and Git worktree isolation.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"publishConfig": {
|
|
8
|
-
"access": "public"
|
|
9
|
-
},
|
|
10
|
-
"keywords": [
|
|
11
|
-
"pi-package",
|
|
12
|
-
"pi-extension",
|
|
13
|
-
"subagent",
|
|
14
|
-
"sub-agent",
|
|
15
|
-
"delegation",
|
|
16
|
-
"code-cleanup",
|
|
17
|
-
"dead-code"
|
|
18
|
-
],
|
|
19
|
-
"files": [
|
|
20
|
-
"src",
|
|
21
|
-
"agents",
|
|
22
|
-
"README.md",
|
|
23
|
-
"LICENSE"
|
|
24
|
-
],
|
|
25
|
-
"pi": {
|
|
26
|
-
"extensions": [
|
|
27
|
-
"./src/index.ts"
|
|
28
|
-
]
|
|
29
|
-
},
|
|
30
|
-
"scripts": {
|
|
31
|
-
"check": "tsc --noEmit",
|
|
32
|
-
"test": "vitest run tests",
|
|
33
|
-
"prepack": "npm run check && npm test"
|
|
34
|
-
},
|
|
35
|
-
"peerDependencies": {
|
|
36
|
-
"@earendil-works/pi-agent-core": ">=0.83.0",
|
|
37
|
-
"@earendil-works/pi-ai": ">=0.83.0",
|
|
38
|
-
"@earendil-works/pi-coding-agent": ">=0.83.0",
|
|
39
|
-
"@earendil-works/pi-tui": ">=0.83.0",
|
|
40
|
-
"typebox": "*"
|
|
41
|
-
},
|
|
42
|
-
"devDependencies": {
|
|
43
|
-
"@earendil-works/pi-agent-core": "^0.83.0",
|
|
44
|
-
"@earendil-works/pi-ai": "^0.83.0",
|
|
45
|
-
"@earendil-works/pi-coding-agent": "^0.83.0",
|
|
46
|
-
"@earendil-works/pi-tui": "^0.83.0",
|
|
47
|
-
"@types/node": "^22.10.0",
|
|
48
|
-
"typebox": "^1.3.9",
|
|
49
|
-
"typescript": "^5.9.0",
|
|
50
|
-
"vitest": "^4.1.0"
|
|
51
|
-
},
|
|
52
|
-
"engines": {
|
|
53
|
-
"node": ">=22.19.0"
|
|
54
|
-
}
|
|
55
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@ferris1225/pi-subagents",
|
|
3
|
+
"version": "4.1.13",
|
|
4
|
+
"description": "A managed sub-agent team for pi: specialized roles, pre-commit documentation sync, retained threads, auto-fix chains, model fallback, and Git worktree isolation.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"pi-package",
|
|
12
|
+
"pi-extension",
|
|
13
|
+
"subagent",
|
|
14
|
+
"sub-agent",
|
|
15
|
+
"delegation",
|
|
16
|
+
"code-cleanup",
|
|
17
|
+
"dead-code"
|
|
18
|
+
],
|
|
19
|
+
"files": [
|
|
20
|
+
"src",
|
|
21
|
+
"agents",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"pi": {
|
|
26
|
+
"extensions": [
|
|
27
|
+
"./src/index.ts"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"check": "tsc --noEmit",
|
|
32
|
+
"test": "vitest run tests",
|
|
33
|
+
"prepack": "npm run check && npm test"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@earendil-works/pi-agent-core": ">=0.83.0",
|
|
37
|
+
"@earendil-works/pi-ai": ">=0.83.0",
|
|
38
|
+
"@earendil-works/pi-coding-agent": ">=0.83.0",
|
|
39
|
+
"@earendil-works/pi-tui": ">=0.83.0",
|
|
40
|
+
"typebox": "*"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@earendil-works/pi-agent-core": "^0.83.0",
|
|
44
|
+
"@earendil-works/pi-ai": "^0.83.0",
|
|
45
|
+
"@earendil-works/pi-coding-agent": "^0.83.0",
|
|
46
|
+
"@earendil-works/pi-tui": "^0.83.0",
|
|
47
|
+
"@types/node": "^22.10.0",
|
|
48
|
+
"typebox": "^1.3.9",
|
|
49
|
+
"typescript": "^5.9.0",
|
|
50
|
+
"vitest": "^4.1.0"
|
|
51
|
+
},
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=22.19.0"
|
|
54
|
+
}
|
|
55
|
+
}
|
package/src/setup.ts
CHANGED
|
@@ -2,20 +2,24 @@
|
|
|
2
2
|
* Interactive configuration wizard for /subagents-setup.
|
|
3
3
|
*
|
|
4
4
|
* The wizard stays one level deep and exposes only what most users touch:
|
|
5
|
-
* which agents run, the model each runs on, and the
|
|
6
|
-
* toggle. Everything else (
|
|
5
|
+
* which agents run, the model and thinking strength each runs on, and the
|
|
6
|
+
* delegation directive toggle. Everything else (agent scope, idle timeout,
|
|
7
7
|
* result lines, notifications) is config-file-only; model failures hand
|
|
8
8
|
* directly to the current main model, and thinking defaults to capability-
|
|
9
9
|
* aware Auto.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { stat } from "node:fs/promises";
|
|
13
|
+
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
13
14
|
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
15
|
+
import { discoverAgents } from "./agents.ts";
|
|
14
16
|
import {
|
|
15
17
|
BUILTIN_AGENT_NAMES,
|
|
16
18
|
DEFAULT_CONFIG,
|
|
17
19
|
DEFAULT_ENABLED_AGENTS,
|
|
20
|
+
DEFAULT_THINKING_LEVEL,
|
|
18
21
|
type SubagentsConfig,
|
|
22
|
+
type ThinkingLevel,
|
|
19
23
|
errorMessage,
|
|
20
24
|
getConfigPath,
|
|
21
25
|
loadConfig,
|
|
@@ -27,7 +31,10 @@ import {
|
|
|
27
31
|
availableModelsInScope,
|
|
28
32
|
buildModelPickerItems,
|
|
29
33
|
currentModelRef,
|
|
34
|
+
findModelByRef,
|
|
30
35
|
modelRef,
|
|
36
|
+
resolveThinkingLevel,
|
|
37
|
+
supportedThinkingLevels,
|
|
31
38
|
} from "./models.ts";
|
|
32
39
|
import { promptSelectMany, promptSelectOne } from "./ui.ts";
|
|
33
40
|
|
|
@@ -98,6 +105,76 @@ async function pickAgentModel(
|
|
|
98
105
|
return pickConfiguredModel(ctx, `Model for "${agentName}"?`, currentRef, escNote);
|
|
99
106
|
}
|
|
100
107
|
|
|
108
|
+
const AUTO_THINKING = "__auto_thinking__";
|
|
109
|
+
|
|
110
|
+
function actualAgentThinkingDefault(
|
|
111
|
+
ctx: ExtensionCommandContext,
|
|
112
|
+
config: SubagentsConfig,
|
|
113
|
+
agentName: string,
|
|
114
|
+
): ThinkingLevel {
|
|
115
|
+
const { agents } = discoverAgents(ctx.cwd, {
|
|
116
|
+
scope: config.agentScope,
|
|
117
|
+
enabledNames: config.enabledAgents,
|
|
118
|
+
projectTrusted: ctx.isProjectTrusted(),
|
|
119
|
+
});
|
|
120
|
+
return agents.find((agent) => agent.name === agentName)?.thinking ?? DEFAULT_THINKING_LEVEL;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const THINKING_LEVEL_HINTS: Record<ThinkingLevel, string> = {
|
|
124
|
+
off: "no reasoning tokens",
|
|
125
|
+
minimal: "minimal reasoning",
|
|
126
|
+
low: "light reasoning",
|
|
127
|
+
medium: "balanced reasoning",
|
|
128
|
+
high: "deep reasoning",
|
|
129
|
+
xhigh: "extra-deep reasoning",
|
|
130
|
+
max: "strongest reasoning",
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
function effectiveModelForChoice(
|
|
134
|
+
ctx: ExtensionCommandContext,
|
|
135
|
+
choice: string,
|
|
136
|
+
): Model<Api> | undefined {
|
|
137
|
+
if (choice === CURRENT_MAIN_MODEL) return ctx.model;
|
|
138
|
+
return findModelByRef(availableModelsInScope(ctx), choice);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Auto is the default. Manual rows are exactly the levels Pi exposes for the
|
|
142
|
+
* selected model; unsupported xhigh/max entries never appear. */
|
|
143
|
+
async function pickAgentStrength(
|
|
144
|
+
ctx: ExtensionCommandContext,
|
|
145
|
+
agentName: string,
|
|
146
|
+
model: Model<Api> | undefined,
|
|
147
|
+
current: ThinkingLevel | undefined,
|
|
148
|
+
agentDefault: ThinkingLevel,
|
|
149
|
+
escNote = "cancels this setup pass",
|
|
150
|
+
): Promise<ThinkingLevel | typeof AUTO_THINKING | undefined> {
|
|
151
|
+
const supported = supportedThinkingLevels(model);
|
|
152
|
+
const automatic = resolveThinkingLevel(model, agentDefault);
|
|
153
|
+
// No model metadata, or a non-reasoning model whose only valid value is off:
|
|
154
|
+
// Auto is already the complete and least surprising choice.
|
|
155
|
+
if (supported.length <= 1) return AUTO_THINKING;
|
|
156
|
+
|
|
157
|
+
const currentEffective = current ? resolveThinkingLevel(model, current) : undefined;
|
|
158
|
+
const modelName = model ? modelRef(model) : "current main model";
|
|
159
|
+
const options = [
|
|
160
|
+
{
|
|
161
|
+
value: AUTO_THINKING,
|
|
162
|
+
label: `auto — ${automatic} for ${modelName}${current === undefined ? " (current, recommended)" : " (recommended)"}`,
|
|
163
|
+
},
|
|
164
|
+
...supported.map((level) => ({
|
|
165
|
+
value: level,
|
|
166
|
+
label: `${level} — ${THINKING_LEVEL_HINTS[level]}${current !== undefined && currentEffective === level ? " (current)" : ""}`,
|
|
167
|
+
})),
|
|
168
|
+
];
|
|
169
|
+
return promptSelectOne(
|
|
170
|
+
ctx,
|
|
171
|
+
`Thinking for "${agentName}"?`,
|
|
172
|
+
`Only levels supported by ${modelName} are shown • Enter selects • Esc ${escNote}`,
|
|
173
|
+
options,
|
|
174
|
+
current === undefined ? AUTO_THINKING : currentEffective,
|
|
175
|
+
) as Promise<ThinkingLevel | typeof AUTO_THINKING | undefined>;
|
|
176
|
+
}
|
|
177
|
+
|
|
101
178
|
async function pickAgentToConfigure(
|
|
102
179
|
ctx: ExtensionCommandContext,
|
|
103
180
|
enabledAgents: readonly string[],
|
|
@@ -117,10 +194,11 @@ async function pickAgentToConfigure(
|
|
|
117
194
|
interface ConfiguredAgentChoice {
|
|
118
195
|
name: string;
|
|
119
196
|
model: string;
|
|
197
|
+
strength: ThinkingLevel | typeof AUTO_THINKING;
|
|
120
198
|
}
|
|
121
199
|
|
|
122
|
-
/** Configure
|
|
123
|
-
*
|
|
200
|
+
/** Configure one agent while preserving the UI back stack: thinking → model →
|
|
201
|
+
* agent selection. Esc from agent selection ends this configuration pass. */
|
|
124
202
|
async function configureOneAgent(
|
|
125
203
|
ctx: ExtensionCommandContext,
|
|
126
204
|
config: SubagentsConfig,
|
|
@@ -128,14 +206,27 @@ async function configureOneAgent(
|
|
|
128
206
|
while (true) {
|
|
129
207
|
const name = await pickAgentToConfigure(ctx, config.enabledAgents);
|
|
130
208
|
if (name === undefined) return undefined;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
209
|
+
|
|
210
|
+
while (true) {
|
|
211
|
+
const modelChoice = await pickAgentModel(
|
|
212
|
+
ctx,
|
|
213
|
+
name,
|
|
214
|
+
config.agentModels[name],
|
|
215
|
+
"returns to agent selection",
|
|
216
|
+
);
|
|
217
|
+
if (modelChoice === undefined) break;
|
|
218
|
+
const model = effectiveModelForChoice(ctx, modelChoice);
|
|
219
|
+
const strength = await pickAgentStrength(
|
|
220
|
+
ctx,
|
|
221
|
+
name,
|
|
222
|
+
model,
|
|
223
|
+
config.agentThinkingLevels[name],
|
|
224
|
+
actualAgentThinkingDefault(ctx, config, name),
|
|
225
|
+
"returns to model selection",
|
|
226
|
+
);
|
|
227
|
+
if (strength === undefined) continue;
|
|
228
|
+
return { name, model: modelChoice, strength };
|
|
229
|
+
}
|
|
139
230
|
}
|
|
140
231
|
}
|
|
141
232
|
|
|
@@ -186,7 +277,7 @@ async function runMenu(ctx: ExtensionCommandContext, configPath: string, config:
|
|
|
186
277
|
while (true) {
|
|
187
278
|
const choice = await ctx.ui.select("pi-subagents settings", [
|
|
188
279
|
"Enable/disable agents",
|
|
189
|
-
"Configure agent
|
|
280
|
+
"Configure an agent (model + thinking)",
|
|
190
281
|
"Proactive injection",
|
|
191
282
|
"Full re-setup",
|
|
192
283
|
]);
|
|
@@ -230,14 +321,17 @@ async function runMenu(ctx: ExtensionCommandContext, configPath: string, config:
|
|
|
230
321
|
next.agentModels = keepAgentEntries(next.agentModels, enabled);
|
|
231
322
|
next.agentThinkingLevels = keepAgentEntries(next.agentThinkingLevels, enabled);
|
|
232
323
|
} else if (choice.startsWith("Configure")) {
|
|
233
|
-
// Per-agent loop:
|
|
234
|
-
// Esc
|
|
324
|
+
// Per-agent loop: thinking Esc returns to that agent's model picker;
|
|
325
|
+
// model Esc returns to the agent picker; agent-picker Esc saves completed
|
|
326
|
+
// choices and returns to this settings menu.
|
|
235
327
|
let configuredAny = false;
|
|
236
328
|
while (true) {
|
|
237
329
|
const picked = await configureOneAgent(ctx, next);
|
|
238
330
|
if (!picked) break;
|
|
239
331
|
configuredAny = true;
|
|
240
332
|
next.agentModels = applyAgentModelChoice(next.agentModels, picked.name, picked.model);
|
|
333
|
+
if (picked.strength === AUTO_THINKING) delete next.agentThinkingLevels[picked.name];
|
|
334
|
+
else next.agentThinkingLevels[picked.name] = picked.strength;
|
|
241
335
|
}
|
|
242
336
|
if (!configuredAny) continue;
|
|
243
337
|
await saveConfig(next, configPath);
|