@jwilger/pi-development-system 0.10.6 → 0.11.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/agents/architect.md +66 -0
- package/agents/coder.md +57 -0
- package/agents/researcher.md +60 -0
- package/agents/reviewer.md +53 -0
- package/agents/tasker.md +58 -0
- package/agents/writer.md +39 -0
- package/extensions/development-system.ts +2 -0
- package/package.json +5 -3
- package/src/subagents/VENDORED.md +38 -0
- package/src/subagents/index.ts +544 -0
- package/src/subagents/orch/inherited-tools.ts +85 -0
- package/src/subagents/orch/mailbox.ts +262 -0
- package/src/subagents/orch/manager.ts +765 -0
- package/src/subagents/orch/paths.ts +74 -0
- package/src/subagents/orch/prompt.ts +25 -0
- package/src/subagents/orch/runtime.ts +784 -0
- package/src/subagents/orch/tools.ts +166 -0
- package/src/subagents/orch/transcript.ts +187 -0
- package/src/subagents/prefs/agent-import.ts +246 -0
- package/src/subagents/prefs/config.ts +1029 -0
- package/src/subagents/prefs/import-discovery.ts +644 -0
- package/src/subagents/prefs/import-instructions.ts +157 -0
- package/src/subagents/prefs/models.ts +78 -0
- package/src/subagents/prefs/settings.ts +371 -0
- package/src/subagents/types.ts +200 -0
- package/src/subagents/ui/agent-navigation-editor.ts +210 -0
- package/src/subagents/ui/dialog.ts +651 -0
- package/src/subagents/ui/import-picker.ts +232 -0
- package/src/subagents/ui/live-agent-view.ts +572 -0
- package/src/subagents/ui/model-picker.ts +452 -0
- package/src/subagents/ui/settings-ui.ts +329 -0
- package/src/subagents/ui/status-ui.ts +545 -0
- package/src/subagents/ui/thread-tree.ts +135 -0
- package/src/subagents/ui/ui.ts +1507 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
// @ts-nocheck: vendored upstream pi-subagent-manager 0.14.0 compiled under looser options; see src/subagents/VENDORED.md
|
|
2
|
+
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import type { ConfigStore } from "../prefs/config.ts";
|
|
4
|
+
import {
|
|
5
|
+
canOpenDialog,
|
|
6
|
+
dialogInput,
|
|
7
|
+
dialogMenu,
|
|
8
|
+
withDialogSession,
|
|
9
|
+
} from "./dialog.ts";
|
|
10
|
+
import {
|
|
11
|
+
DEFAULT_MANAGER_SETTINGS,
|
|
12
|
+
loadManagerSaveScope,
|
|
13
|
+
saveManagerSaveScope,
|
|
14
|
+
saveManagerSettings,
|
|
15
|
+
type ManagerSettings,
|
|
16
|
+
type ModelSelectionMode,
|
|
17
|
+
type SubagentMode,
|
|
18
|
+
type ToolFilteringMode,
|
|
19
|
+
type WidgetMode,
|
|
20
|
+
} from "../prefs/settings.ts";
|
|
21
|
+
import { editAgentTypes } from "./ui.ts";
|
|
22
|
+
|
|
23
|
+
const FIELDS = [
|
|
24
|
+
{
|
|
25
|
+
id: "maxLevels",
|
|
26
|
+
label: "Maximum levels",
|
|
27
|
+
help: "How deep agents can delegate.\nYour main conversation is level 1; 3 allows an agent and its child.\nPositive integer, at most 32.",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "maxConcurrent",
|
|
31
|
+
label: "Concurrent agents",
|
|
32
|
+
help: "How many agents can be active at once across all levels.\nParents waiting for children also count.\nPositive safe integer.",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: "maxThreads",
|
|
36
|
+
label: "Retained threads",
|
|
37
|
+
help: "How many agent sessions can be kept for follow-up work, including completed and paused agents.\nAt the limit, new agents cannot start.\nPositive safe integer.",
|
|
38
|
+
},
|
|
39
|
+
] as const;
|
|
40
|
+
|
|
41
|
+
const MODE_OPTIONS = [
|
|
42
|
+
{
|
|
43
|
+
id: "off",
|
|
44
|
+
label: "Off",
|
|
45
|
+
value: "No subagent tools or prompt guidance",
|
|
46
|
+
help: "Off: hide subagent tools and inject no subagent guidance into the system prompt.\nExisting work and retained sessions are kept.",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: "opportunistic",
|
|
50
|
+
label: "Opportunistic",
|
|
51
|
+
value: "Parallelizable or very large tasks only",
|
|
52
|
+
help: "Opportunistic: make subagent tools available.\nDelegate only when tasks can be parallelized or a task is very large; otherwise work directly.",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: "orchestration",
|
|
56
|
+
label: "Orchestration",
|
|
57
|
+
value: "/root coordinates; subagents execute",
|
|
58
|
+
help: "Orchestration: tell /root to delegate all task execution to subagents and only coordinate and synthesize results.\nThis rule is not inherited by workers.",
|
|
59
|
+
},
|
|
60
|
+
] as const;
|
|
61
|
+
|
|
62
|
+
const MODE_HELP =
|
|
63
|
+
"Off: no subagent tools or prompt guidance.\nOpportunistic: delegate only parallelizable or very large tasks.\nOrchestration: /root delegates all execution and only coordinates and synthesizes results.";
|
|
64
|
+
|
|
65
|
+
const TOOL_FILTERING_OPTIONS = [
|
|
66
|
+
{
|
|
67
|
+
id: "allowed",
|
|
68
|
+
label: "Allowed (except blocked)",
|
|
69
|
+
value: "Allow list minus block list",
|
|
70
|
+
help: "Only tools in the agent YAML allow list are available, minus its block list.\nBlocked tools take precedence. A missing or empty allow list means no tools.",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: "all-except-blocked",
|
|
74
|
+
label: "All except blocked",
|
|
75
|
+
value: "Ignore allow list",
|
|
76
|
+
help: "All available tools except those in the agent YAML block list.\nThe allow list is completely ignored.",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: "all",
|
|
80
|
+
label: "All",
|
|
81
|
+
value: "Ignore both lists",
|
|
82
|
+
help: "All available tools.\nThe agent YAML allow and block lists are completely ignored.",
|
|
83
|
+
},
|
|
84
|
+
] as const;
|
|
85
|
+
|
|
86
|
+
const TOOL_FILTERING_HELP =
|
|
87
|
+
"Allowed (except blocked): only allow-listed tools, minus blocked tools; a missing or empty allow list means no tools.\nAll except blocked: ignore the allow list; block-listed tools remain blocked.\nAll: ignore both lists.\nSave and apply to affect agents when their sessions start.";
|
|
88
|
+
|
|
89
|
+
const WIDGET_MODE_OPTIONS = [
|
|
90
|
+
{
|
|
91
|
+
id: "full",
|
|
92
|
+
label: "Full",
|
|
93
|
+
value: "Detailed agent status rows",
|
|
94
|
+
help: "Full: show the existing agent status widget above the input box, with per-agent details.",
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
id: "minimal",
|
|
98
|
+
label: "Minimal",
|
|
99
|
+
value: "One-line counts and running-agent tokens",
|
|
100
|
+
help: "Minimal: show status counts in one line above the input box.\nStarting agents count as running. Token totals include only active (starting/running) agents.",
|
|
101
|
+
},
|
|
102
|
+
] as const;
|
|
103
|
+
|
|
104
|
+
const WIDGET_MODE_HELP =
|
|
105
|
+
"Full: detailed agent status rows above the input box.\nMinimal: one-line status counts and cumulative input/output tokens for active (starting/running) agents.\nSave and apply to update the widget immediately.";
|
|
106
|
+
|
|
107
|
+
const MODEL_SELECTION_OPTIONS = [
|
|
108
|
+
{
|
|
109
|
+
id: "pick-first-available",
|
|
110
|
+
label: "Pick First (available)",
|
|
111
|
+
value: "First available model in the agent's list",
|
|
112
|
+
help: "Pick First (available):\nPick the first model in the agent's models list available in Pi with an enabled, authenticated provider.\nSkip missing models and providers without credentials; try the next preference.",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
id: "pick-first-scoped",
|
|
116
|
+
label: "Pick First (scoped)",
|
|
117
|
+
value: "First available preference in the session scope",
|
|
118
|
+
help: "Pick First (scoped):\nPick the first available model in the agent's models list that is also selected in the current session's /scoped-models.\nSkip unavailable models and providers without credentials.",
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
id: "use-current",
|
|
122
|
+
label: "Use Current",
|
|
123
|
+
value: "Use the main session's current model",
|
|
124
|
+
help: "Use Current:\nIgnore the agent's models list and use the main session's current model.\nKeep each agent's configured thinking level, not the main session's thinking level.",
|
|
125
|
+
},
|
|
126
|
+
] as const;
|
|
127
|
+
|
|
128
|
+
const MODEL_SELECTION_HELP =
|
|
129
|
+
"Pick First (available): first preference with an enabled, authenticated provider in Pi.\nPick First (scoped): same, limited to the current session's /scoped-models.\nUse Current: ignore models and use the main session's current model; keep the agent's thinking level.\nOnly the models list affects runtime picking; modelSuggestions are search hints.\nSave and apply to affect agents when their sessions start.";
|
|
130
|
+
|
|
131
|
+
export async function configureAgents(
|
|
132
|
+
ctx: ExtensionCommandContext,
|
|
133
|
+
options: {
|
|
134
|
+
store: ConfigStore;
|
|
135
|
+
settings: ManagerSettings;
|
|
136
|
+
agentDir: string;
|
|
137
|
+
apply(): void;
|
|
138
|
+
},
|
|
139
|
+
): Promise<void> {
|
|
140
|
+
if (!canOpenDialog(ctx)) return;
|
|
141
|
+
await withDialogSession(ctx, (scoped) =>
|
|
142
|
+
configureAgentsDialog(scoped, options),
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async function configureAgentsDialog(
|
|
147
|
+
ctx: ExtensionCommandContext,
|
|
148
|
+
options: {
|
|
149
|
+
store: ConfigStore;
|
|
150
|
+
settings: ManagerSettings;
|
|
151
|
+
agentDir: string;
|
|
152
|
+
apply(): void;
|
|
153
|
+
},
|
|
154
|
+
): Promise<void> {
|
|
155
|
+
let draft = { ...options.settings };
|
|
156
|
+
let scope = loadManagerSaveScope({
|
|
157
|
+
agentDir: options.agentDir,
|
|
158
|
+
includeProject: ctx.isProjectTrusted(),
|
|
159
|
+
});
|
|
160
|
+
let selectedId: string | undefined;
|
|
161
|
+
while (true) {
|
|
162
|
+
const dirty = JSON.stringify(draft) !== JSON.stringify(options.settings);
|
|
163
|
+
const action = await dialogMenu(
|
|
164
|
+
ctx,
|
|
165
|
+
`Agents settings${dirty ? " · unsaved" : ""}`,
|
|
166
|
+
[
|
|
167
|
+
{
|
|
168
|
+
id: "subagentMode",
|
|
169
|
+
label: "Subagent Mode",
|
|
170
|
+
value: MODE_OPTIONS.find((mode) => mode.id === draft.subagentMode)!.label,
|
|
171
|
+
help: MODE_HELP,
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: "toolFiltering",
|
|
175
|
+
label: "Tool Filtering",
|
|
176
|
+
value: TOOL_FILTERING_OPTIONS.find((mode) => mode.id === draft.toolFiltering)!.label,
|
|
177
|
+
help: TOOL_FILTERING_HELP,
|
|
178
|
+
},
|
|
179
|
+
...FIELDS.map((field) => ({
|
|
180
|
+
...field,
|
|
181
|
+
value: String(draft[field.id]),
|
|
182
|
+
})),
|
|
183
|
+
{
|
|
184
|
+
id: "modelSelection",
|
|
185
|
+
label: "Model Picking",
|
|
186
|
+
value: MODEL_SELECTION_OPTIONS.find((mode) => mode.id === draft.modelSelection)!.label,
|
|
187
|
+
help: MODEL_SELECTION_HELP,
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
id: "widgetMode",
|
|
191
|
+
label: "Status Widget",
|
|
192
|
+
value: WIDGET_MODE_OPTIONS.find((mode) => mode.id === draft.widgetMode)!.label,
|
|
193
|
+
help: WIDGET_MODE_HELP,
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
id: "nerdFontIcons",
|
|
197
|
+
label: "[labs] Nerd Font icons",
|
|
198
|
+
value: draft.nerdFontIcons ? "On" : "Off",
|
|
199
|
+
help: "Experimental: display each agent type’s optional icon.\nRequires a Nerd Font configured in your terminal; otherwise glyphs may appear as boxes.\nOff by default. Save and apply to update the widget immediately.",
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
id: "finalRecap",
|
|
203
|
+
label: "[labs] Final Recap",
|
|
204
|
+
value: draft.finalRecap ? "On" : "Off",
|
|
205
|
+
help: "Experimental: when detached agents finish or fail and the main agent is idle, automatically ask the main agent to summarize their results.\nEnabling this may cause extra model turns and uses more tokens and context.\nOff by default. Subagent Mode Off suppresses automatic summaries.",
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
id: "scope",
|
|
209
|
+
label: "Save scope",
|
|
210
|
+
value: scope === "user" ? "Global" : "Current Project",
|
|
211
|
+
help: "Global: save all values shown as your defaults for every project. Existing project settings still override them, including here.\nCurrent Project: save all values shown for this project only, overriding your global defaults here. Other projects are unchanged. Requires a trusted project.\nSwitching scope only changes where you save, not the values shown. Your choice is remembered across projects and restarts, even if you cancel.",
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
id: "types",
|
|
215
|
+
label: "Agent definitions",
|
|
216
|
+
value: `${options.store.list().length} types`,
|
|
217
|
+
help: "Create or edit agent definitions.\nConfigure model preferences and tool policy for each agent type.",
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
id: "defaults",
|
|
221
|
+
label: "Restore defaults",
|
|
222
|
+
help: "Replace all values shown with built-in defaults.\nNothing is saved until you choose Save and apply.",
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
id: "save",
|
|
226
|
+
label: "Save and apply",
|
|
227
|
+
value: dirty ? "(changes)" : undefined,
|
|
228
|
+
valueColor: dirty ? "warning" as const : undefined,
|
|
229
|
+
help: "Save all values to the selected scope and reload settings now.\nProject overrides still take precedence.\nRunning agents and retained sessions are kept.",
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
id: "cancel",
|
|
233
|
+
label: "Cancel",
|
|
234
|
+
help: "Close without saving manager settings.",
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
{
|
|
238
|
+
selectedId,
|
|
239
|
+
saveId: "save",
|
|
240
|
+
footer: "↑↓/Tab navigate · Enter edit · Ctrl+S save · Esc cancel",
|
|
241
|
+
},
|
|
242
|
+
);
|
|
243
|
+
if (!action || action === "cancel") return;
|
|
244
|
+
selectedId = action;
|
|
245
|
+
try {
|
|
246
|
+
const field = FIELDS.find((field) => field.id === action);
|
|
247
|
+
if (field) {
|
|
248
|
+
const value = await dialogInput(
|
|
249
|
+
ctx,
|
|
250
|
+
field.label,
|
|
251
|
+
String(draft[field.id]),
|
|
252
|
+
field.help,
|
|
253
|
+
);
|
|
254
|
+
if (value === undefined) continue;
|
|
255
|
+
const number = Number(value.trim());
|
|
256
|
+
if (
|
|
257
|
+
!/^\d+$/.test(value.trim()) ||
|
|
258
|
+
!Number.isSafeInteger(number) ||
|
|
259
|
+
number < 1 ||
|
|
260
|
+
(field.id === "maxLevels" && number > 32)
|
|
261
|
+
)
|
|
262
|
+
throw new Error(field.help);
|
|
263
|
+
draft[field.id] = number;
|
|
264
|
+
} else if (action === "subagentMode") {
|
|
265
|
+
const mode = await dialogMenu(ctx, "Subagent Mode", [...MODE_OPTIONS], {
|
|
266
|
+
selectedId: draft.subagentMode,
|
|
267
|
+
});
|
|
268
|
+
if (MODE_OPTIONS.some((option) => option.id === mode))
|
|
269
|
+
draft.subagentMode = mode as SubagentMode;
|
|
270
|
+
} else if (action === "toolFiltering") {
|
|
271
|
+
const mode = await dialogMenu(ctx, "Tool Filtering", [...TOOL_FILTERING_OPTIONS], {
|
|
272
|
+
selectedId: draft.toolFiltering,
|
|
273
|
+
});
|
|
274
|
+
if (TOOL_FILTERING_OPTIONS.some((option) => option.id === mode))
|
|
275
|
+
draft.toolFiltering = mode as ToolFilteringMode;
|
|
276
|
+
} else if (action === "modelSelection") {
|
|
277
|
+
const mode = await dialogMenu(ctx, "Model Picking", [...MODEL_SELECTION_OPTIONS], {
|
|
278
|
+
selectedId: draft.modelSelection,
|
|
279
|
+
});
|
|
280
|
+
if (MODEL_SELECTION_OPTIONS.some((option) => option.id === mode))
|
|
281
|
+
draft.modelSelection = mode as ModelSelectionMode;
|
|
282
|
+
} else if (action === "widgetMode") {
|
|
283
|
+
const mode = await dialogMenu(ctx, "Status Widget", [...WIDGET_MODE_OPTIONS], {
|
|
284
|
+
selectedId: draft.widgetMode,
|
|
285
|
+
});
|
|
286
|
+
if (WIDGET_MODE_OPTIONS.some((option) => option.id === mode))
|
|
287
|
+
draft.widgetMode = mode as WidgetMode;
|
|
288
|
+
} else if (action === "nerdFontIcons") {
|
|
289
|
+
draft.nerdFontIcons = !draft.nerdFontIcons;
|
|
290
|
+
} else if (action === "finalRecap") {
|
|
291
|
+
draft.finalRecap = !draft.finalRecap;
|
|
292
|
+
} else if (action === "scope") {
|
|
293
|
+
if (!ctx.isProjectTrusted())
|
|
294
|
+
ctx.ui.notify(
|
|
295
|
+
"Project settings require a trusted project; saving globally.",
|
|
296
|
+
"warning",
|
|
297
|
+
);
|
|
298
|
+
else {
|
|
299
|
+
const nextScope = scope === "user" ? "project" : "user";
|
|
300
|
+
saveManagerSaveScope(options.agentDir, nextScope);
|
|
301
|
+
scope = nextScope;
|
|
302
|
+
}
|
|
303
|
+
} else if (action === "defaults") draft = { ...DEFAULT_MANAGER_SETTINGS };
|
|
304
|
+
else if (action === "types") {
|
|
305
|
+
await editAgentTypes(ctx, options.store, draft.nerdFontIcons);
|
|
306
|
+
options.store.reload();
|
|
307
|
+
} else if (action === "save") {
|
|
308
|
+
const file = saveManagerSettings({
|
|
309
|
+
cwd: ctx.cwd,
|
|
310
|
+
agentDir: options.agentDir,
|
|
311
|
+
includeProject: ctx.isProjectTrusted(),
|
|
312
|
+
scope,
|
|
313
|
+
settings: draft,
|
|
314
|
+
});
|
|
315
|
+
options.apply();
|
|
316
|
+
ctx.ui.notify(
|
|
317
|
+
`Saved ${file}. Settings reloaded; project overrides take precedence.`,
|
|
318
|
+
"info",
|
|
319
|
+
);
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
} catch (error) {
|
|
323
|
+
ctx.ui.notify(
|
|
324
|
+
error instanceof Error ? error.message : String(error),
|
|
325
|
+
"error",
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|