@narumitw/pi-subagents 0.49.2 → 0.51.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/README.md +313 -53
- package/package.json +11 -8
- package/src/adaptive-scheduler.ts +196 -0
- package/src/admission-benchmark.ts +95 -0
- package/src/admission-policy.ts +78 -0
- package/src/agent-projection.ts +53 -0
- package/src/agents.ts +58 -1
- package/src/auto-transport.ts +114 -0
- package/src/blocking-status.ts +63 -0
- package/src/capabilities.ts +145 -0
- package/src/capability-grant.ts +115 -0
- package/src/capability-router.ts +107 -0
- package/src/completion-delivery.ts +257 -0
- package/src/config-status.ts +221 -0
- package/src/config-ui.ts +215 -236
- package/src/consult-resources.ts +4 -27
- package/src/consult.ts +9 -1
- package/src/create-stateful-transport.ts +55 -0
- package/src/delegation-contract.ts +417 -0
- package/src/execution-plan.ts +322 -0
- package/src/execution-profiles.ts +95 -0
- package/src/execution-ui.ts +320 -0
- package/src/execution.ts +848 -158
- package/src/in-process-transport.ts +269 -25
- package/src/inspect-render.ts +101 -1
- package/src/inspect.ts +296 -3
- package/src/integration-controller.ts +98 -0
- package/src/limits.ts +3 -0
- package/src/orchestration-metrics.ts +78 -0
- package/src/outcome.ts +61 -0
- package/src/panel-child-group.ts +35 -0
- package/src/panel-contract.ts +343 -0
- package/src/panel-evidence.ts +59 -0
- package/src/panel-execution.ts +772 -0
- package/src/panel-failure.ts +56 -0
- package/src/panel-planning.ts +175 -0
- package/src/panel-prompts.ts +132 -0
- package/src/panel-reconciliation.ts +57 -0
- package/src/panel-render.ts +103 -0
- package/src/parallel-limit-ui.ts +112 -0
- package/src/params.ts +172 -3
- package/src/persistence.ts +182 -32
- package/src/prompt-resources.ts +38 -0
- package/src/registry-types.ts +175 -0
- package/src/registry.ts +466 -143
- package/src/render.ts +72 -6
- package/src/result-contract.ts +416 -0
- package/src/retained-semantic-state.ts +100 -0
- package/src/rpc-timeout-finalization.ts +207 -0
- package/src/rpc-transport-metadata.ts +65 -0
- package/src/rpc-transport.ts +990 -0
- package/src/rpc-turn-capture.ts +142 -0
- package/src/runner-result.ts +55 -0
- package/src/runner-usage.ts +48 -0
- package/src/runner.ts +325 -73
- package/src/semantic-snapshot.ts +214 -0
- package/src/settings.ts +254 -35
- package/src/spawn-idempotency.ts +61 -0
- package/src/stateful-config.ts +13 -0
- package/src/stateful-guidance.ts +1 -0
- package/src/stateful-lifecycle.ts +45 -2
- package/src/stateful-limit-ui.ts +246 -0
- package/src/stateful-limits.ts +96 -0
- package/src/stateful-prompt.ts +11 -2
- package/src/stateful-render.ts +48 -3
- package/src/stateful.ts +467 -357
- package/src/subagents.ts +114 -46
- package/src/subprocess-transport.ts +64 -5
- package/src/supervision.ts +103 -0
- package/src/timeout-checkpoint.ts +305 -0
- package/src/timeout-finalization.ts +75 -0
- package/src/transport-types.ts +68 -0
- package/src/transport-ui.ts +169 -0
- package/src/transport.ts +16 -4
- package/src/turn-budget.ts +109 -0
- package/src/verification-policy.ts +17 -0
- package/src/work-item-ledger.ts +682 -0
- package/src/work-item-persistence.ts +218 -0
- package/src/workflow-planning.ts +150 -0
- package/src/workflow-ui.ts +61 -0
- package/src/workspace.ts +69 -12
package/src/config-ui.ts
CHANGED
|
@@ -6,10 +6,42 @@ import {
|
|
|
6
6
|
type DelegationCwdPolicy,
|
|
7
7
|
discoverAgents,
|
|
8
8
|
} from "./agents.js";
|
|
9
|
+
import {
|
|
10
|
+
completionLabel,
|
|
11
|
+
consultationCwdLabel,
|
|
12
|
+
consultResourceLabel,
|
|
13
|
+
currentWorkflow,
|
|
14
|
+
delegationCwdLabel,
|
|
15
|
+
formatManagerSummary,
|
|
16
|
+
helpLines,
|
|
17
|
+
showSubagentHelp,
|
|
18
|
+
showSubagentStatus,
|
|
19
|
+
statusLines,
|
|
20
|
+
} from "./config-status.js";
|
|
21
|
+
import {
|
|
22
|
+
applyAgentModel,
|
|
23
|
+
applyAgentThinking,
|
|
24
|
+
applyAgentTimeout,
|
|
25
|
+
applyExecutionProfileFromUi,
|
|
26
|
+
executionAgentPickerScreen,
|
|
27
|
+
executionAgentScreen,
|
|
28
|
+
executionModelInputScreen,
|
|
29
|
+
executionModelScreen,
|
|
30
|
+
executionProfileScreen,
|
|
31
|
+
executionThinkingScreen,
|
|
32
|
+
executionTimeoutInputScreen,
|
|
33
|
+
resetAgentExecution,
|
|
34
|
+
} from "./execution-ui.js";
|
|
35
|
+
import {
|
|
36
|
+
applyBlockingParallelLimitSetting,
|
|
37
|
+
blockingParallelLimitScreen,
|
|
38
|
+
} from "./parallel-limit-ui.js";
|
|
9
39
|
import type { ManagedAgent } from "./registry.js";
|
|
40
|
+
import { safeTerminalLine as safeTerminalText } from "./safe-text.js";
|
|
10
41
|
import {
|
|
11
42
|
type DelegationWorkflow,
|
|
12
43
|
hasOwn,
|
|
44
|
+
inspectBlockingParallelLimitSettings,
|
|
13
45
|
inspectCompletionDeliverySettings,
|
|
14
46
|
inspectConsultResourceSettings,
|
|
15
47
|
inspectCwdPolicySettings,
|
|
@@ -24,6 +56,20 @@ import {
|
|
|
24
56
|
updateDelegationWorkflowSetting,
|
|
25
57
|
} from "./settings.js";
|
|
26
58
|
import { formatStatefulAgentLine, type StatefulSubagentRuntimeStatus } from "./stateful.js";
|
|
59
|
+
import {
|
|
60
|
+
applyStatefulLimitSetting,
|
|
61
|
+
formatDetachedLimitSummary,
|
|
62
|
+
formatEmptyStatefulRuntime,
|
|
63
|
+
statefulLimitInputScreen,
|
|
64
|
+
statefulLimitListScreen,
|
|
65
|
+
} from "./stateful-limit-ui.js";
|
|
66
|
+
import { isStatefulLimitField, type StatefulLimitField } from "./stateful-limits.js";
|
|
67
|
+
import {
|
|
68
|
+
applyTransportSetting,
|
|
69
|
+
responsivenessSetupScreen,
|
|
70
|
+
transportSettingsScreen,
|
|
71
|
+
} from "./transport-ui.js";
|
|
72
|
+
import { showWorkflowPreview, workflowLabel } from "./workflow-ui.js";
|
|
27
73
|
|
|
28
74
|
const SUBCOMMANDS = [
|
|
29
75
|
{ value: "settings", label: "settings", description: "Configure subagent user settings" },
|
|
@@ -34,10 +80,12 @@ const TOOL_VIEWPORT_SIZE = 10;
|
|
|
34
80
|
|
|
35
81
|
export interface SubagentSettingsRuntime {
|
|
36
82
|
getBlockingEnabled(): boolean;
|
|
83
|
+
getMaxParallelTasks(): number;
|
|
37
84
|
getCompletionDelivery(): CompletionDelivery;
|
|
38
85
|
getConsultResourcePolicy(): ConsultResourcePolicy;
|
|
39
86
|
getConsultationCwdPolicy(): ConsultationCwdPolicy;
|
|
40
87
|
getDelegationCwdPolicy(): DelegationCwdPolicy;
|
|
88
|
+
setMaxParallelTasks(value: number): void;
|
|
41
89
|
setCompletionDelivery(value: CompletionDelivery): void;
|
|
42
90
|
setConsultResourcePolicy(value: ConsultResourcePolicy): void;
|
|
43
91
|
setConsultationCwdPolicy(value: ConsultationCwdPolicy): void;
|
|
@@ -47,7 +95,7 @@ export interface SubagentSettingsRuntime {
|
|
|
47
95
|
clearAgents(): Promise<number>;
|
|
48
96
|
}
|
|
49
97
|
|
|
50
|
-
interface
|
|
98
|
+
export interface SubagentMenuOwner {
|
|
51
99
|
generation: number;
|
|
52
100
|
controller: AbortController;
|
|
53
101
|
}
|
|
@@ -61,8 +109,8 @@ interface ToolDraft {
|
|
|
61
109
|
selected: Set<string>;
|
|
62
110
|
}
|
|
63
111
|
|
|
64
|
-
export function
|
|
65
|
-
const owner:
|
|
112
|
+
export function registerSubagentConfigLifecycle(pi: ExtensionAPI): SubagentMenuOwner {
|
|
113
|
+
const owner: SubagentMenuOwner = { generation: 0, controller: new AbortController() };
|
|
66
114
|
pi.on("session_start", () => {
|
|
67
115
|
owner.generation += 1;
|
|
68
116
|
owner.controller.abort(new DOMException("Subagent session replaced", "AbortError"));
|
|
@@ -72,13 +120,21 @@ export function registerSubagentConfigCommand(pi: ExtensionAPI, runtime: Subagen
|
|
|
72
120
|
owner.generation += 1;
|
|
73
121
|
owner.controller.abort(new DOMException("Subagent session shut down", "AbortError"));
|
|
74
122
|
});
|
|
123
|
+
return owner;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function registerSubagentConfigCommand(
|
|
127
|
+
pi: ExtensionAPI,
|
|
128
|
+
runtime: SubagentSettingsRuntime,
|
|
129
|
+
owner = registerSubagentConfigLifecycle(pi),
|
|
130
|
+
) {
|
|
75
131
|
registerSubagentPrimaryCommand(pi, runtime, owner);
|
|
76
132
|
}
|
|
77
133
|
|
|
78
134
|
function registerSubagentPrimaryCommand(
|
|
79
135
|
pi: ExtensionAPI,
|
|
80
136
|
runtime: SubagentSettingsRuntime,
|
|
81
|
-
owner:
|
|
137
|
+
owner: SubagentMenuOwner,
|
|
82
138
|
) {
|
|
83
139
|
pi.registerCommand("subagents", {
|
|
84
140
|
description: "Manage current-session subagents and user settings",
|
|
@@ -116,7 +172,7 @@ async function showSubagentManager(
|
|
|
116
172
|
pi: ExtensionAPI,
|
|
117
173
|
ctx: ExtensionCommandContext,
|
|
118
174
|
runtime: SubagentSettingsRuntime,
|
|
119
|
-
owner:
|
|
175
|
+
owner: SubagentMenuOwner,
|
|
120
176
|
) {
|
|
121
177
|
if (ctx.mode !== "tui") {
|
|
122
178
|
showSubagentStatus(ctx, runtime);
|
|
@@ -128,12 +184,27 @@ async function showSubagentManager(
|
|
|
128
184
|
if (!isCurrent()) return;
|
|
129
185
|
let availableAgents = discoverAgents(ctx.cwd, "user", readSubagentSettings() ?? {}).agents;
|
|
130
186
|
let toolDraft: ToolDraft | undefined;
|
|
187
|
+
let selectedExecutionAgent: (typeof availableAgents)[number] | undefined;
|
|
188
|
+
let selectedStatefulLimit: StatefulLimitField = "maxAgents";
|
|
131
189
|
type Screen =
|
|
132
190
|
| "main"
|
|
133
191
|
| "workflow"
|
|
134
192
|
| "agents"
|
|
135
193
|
| "settings"
|
|
136
194
|
| "advanced"
|
|
195
|
+
| "performance"
|
|
196
|
+
| "responsiveness"
|
|
197
|
+
| "transport"
|
|
198
|
+
| "execution-profiles"
|
|
199
|
+
| "execution-agent-picker"
|
|
200
|
+
| "execution-agent"
|
|
201
|
+
| "execution-thinking"
|
|
202
|
+
| "execution-model"
|
|
203
|
+
| "execution-model-input"
|
|
204
|
+
| "execution-timeout"
|
|
205
|
+
| "parallel-limit"
|
|
206
|
+
| "stateful-limits"
|
|
207
|
+
| "stateful-limit-input"
|
|
137
208
|
| "status"
|
|
138
209
|
| "help"
|
|
139
210
|
| "agent-picker"
|
|
@@ -141,6 +212,16 @@ async function showSubagentManager(
|
|
|
141
212
|
type Action =
|
|
142
213
|
| "set-workflow"
|
|
143
214
|
| "clear-agents"
|
|
215
|
+
| "set-transport"
|
|
216
|
+
| "apply-execution-profile"
|
|
217
|
+
| "pick-execution-agent"
|
|
218
|
+
| "set-agent-thinking"
|
|
219
|
+
| "set-agent-model"
|
|
220
|
+
| "set-agent-timeout"
|
|
221
|
+
| "reset-agent-execution"
|
|
222
|
+
| "set-parallel-limit"
|
|
223
|
+
| "pick-stateful-limit"
|
|
224
|
+
| "set-stateful-limit"
|
|
144
225
|
| "set-completion"
|
|
145
226
|
| "set-consult-resources"
|
|
146
227
|
| "set-consultation-cwd"
|
|
@@ -183,7 +264,7 @@ async function showSubagentManager(
|
|
|
183
264
|
{
|
|
184
265
|
id: "advanced",
|
|
185
266
|
label: "Advanced settings",
|
|
186
|
-
description: "Agent permissions, runtime details, and settings path",
|
|
267
|
+
description: "Agent permissions, parallel limit, runtime details, and settings path",
|
|
187
268
|
to: "advanced",
|
|
188
269
|
},
|
|
189
270
|
{ id: "help", label: "Help", to: "help" },
|
|
@@ -240,7 +321,9 @@ async function showSubagentManager(
|
|
|
240
321
|
return {
|
|
241
322
|
kind: "actions",
|
|
242
323
|
title: "Current-session Subagents",
|
|
243
|
-
lines: agents.length
|
|
324
|
+
lines: agents.length
|
|
325
|
+
? agents.map(formatStatefulAgentLine)
|
|
326
|
+
: [formatEmptyStatefulRuntime(status)],
|
|
244
327
|
items: [
|
|
245
328
|
...(agents.length > 0
|
|
246
329
|
? [
|
|
@@ -258,26 +341,85 @@ async function showSubagentManager(
|
|
|
258
341
|
};
|
|
259
342
|
},
|
|
260
343
|
settings: () => subagentSettingsScreen(runtime),
|
|
261
|
-
advanced: () =>
|
|
344
|
+
advanced: () => {
|
|
345
|
+
const limit = inspectBlockingParallelLimitSettings();
|
|
346
|
+
return {
|
|
347
|
+
kind: "actions",
|
|
348
|
+
title: "Advanced Subagent Settings",
|
|
349
|
+
items: [
|
|
350
|
+
{
|
|
351
|
+
id: "agent-tools",
|
|
352
|
+
label: "Agent tool permissions",
|
|
353
|
+
description: "Customize persistent per-agent tool allow-lists",
|
|
354
|
+
action: "load-agent-picker",
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
id: "status",
|
|
358
|
+
label: "Runtime details",
|
|
359
|
+
description: "Show transport, configured source, and settings path",
|
|
360
|
+
to: "status",
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
id: "parallel-limit",
|
|
364
|
+
label: "Maximum parallel workers",
|
|
365
|
+
description: `Current: ${runtime.getMaxParallelTasks()} per blocking call`,
|
|
366
|
+
to: "parallel-limit",
|
|
367
|
+
disabled: limit.error !== undefined,
|
|
368
|
+
disabledReason: limit.error
|
|
369
|
+
? `Repair ${safeTerminalText(limit.path)} before editing this setting`
|
|
370
|
+
: undefined,
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
id: "stateful-limits",
|
|
374
|
+
label: "Detached agent limits",
|
|
375
|
+
description: formatDetachedLimitSummary(runtime.getRuntimeStatus()),
|
|
376
|
+
to: "stateful-limits",
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
id: "performance",
|
|
380
|
+
label: "Performance and execution",
|
|
381
|
+
description: "Transport, responsiveness, profiles, and agent defaults",
|
|
382
|
+
to: "performance",
|
|
383
|
+
},
|
|
384
|
+
{ id: "back", label: "Back", action: "back" },
|
|
385
|
+
],
|
|
386
|
+
hint: "back",
|
|
387
|
+
};
|
|
388
|
+
},
|
|
389
|
+
performance: () => ({
|
|
262
390
|
kind: "actions",
|
|
263
|
-
title: "
|
|
391
|
+
title: "Performance and Execution",
|
|
264
392
|
items: [
|
|
265
393
|
{
|
|
266
|
-
id: "
|
|
267
|
-
label: "
|
|
268
|
-
description: "
|
|
269
|
-
|
|
394
|
+
id: "responsiveness",
|
|
395
|
+
label: "Responsiveness setup",
|
|
396
|
+
description: "Preview automatic retained transport and completion guidance",
|
|
397
|
+
to: "responsiveness",
|
|
270
398
|
},
|
|
399
|
+
{ id: "transport", label: "Detached transport", to: "transport" },
|
|
400
|
+
{ id: "profiles", label: "Execution profiles", to: "execution-profiles" },
|
|
271
401
|
{
|
|
272
|
-
id: "
|
|
273
|
-
label: "
|
|
274
|
-
description: "
|
|
275
|
-
to: "
|
|
402
|
+
id: "agents",
|
|
403
|
+
label: "Agent execution defaults",
|
|
404
|
+
description: "Model, thinking level, and timeout",
|
|
405
|
+
to: "execution-agent-picker",
|
|
276
406
|
},
|
|
277
407
|
{ id: "back", label: "Back", action: "back" },
|
|
278
408
|
],
|
|
279
409
|
hint: "back",
|
|
280
410
|
}),
|
|
411
|
+
responsiveness: () => responsivenessSetupScreen(runtime),
|
|
412
|
+
transport: () => transportSettingsScreen(runtime),
|
|
413
|
+
"execution-profiles": () => executionProfileScreen(),
|
|
414
|
+
"execution-agent-picker": () => executionAgentPickerScreen(availableAgents),
|
|
415
|
+
"execution-agent": () => executionAgentScreen(selectedExecutionAgent),
|
|
416
|
+
"execution-thinking": () => executionThinkingScreen(selectedExecutionAgent),
|
|
417
|
+
"execution-model": () => executionModelScreen(selectedExecutionAgent, ctx),
|
|
418
|
+
"execution-model-input": () => executionModelInputScreen(selectedExecutionAgent),
|
|
419
|
+
"execution-timeout": () => executionTimeoutInputScreen(selectedExecutionAgent),
|
|
420
|
+
"parallel-limit": () => blockingParallelLimitScreen(runtime),
|
|
421
|
+
"stateful-limits": () => statefulLimitListScreen(runtime),
|
|
422
|
+
"stateful-limit-input": () => statefulLimitInputScreen(selectedStatefulLimit, runtime),
|
|
281
423
|
status: () => ({
|
|
282
424
|
kind: "detail",
|
|
283
425
|
title: "Subagent runtime details",
|
|
@@ -351,7 +493,7 @@ async function showSubagentManager(
|
|
|
351
493
|
}),
|
|
352
494
|
},
|
|
353
495
|
actions: {
|
|
354
|
-
"set-workflow": async ({ itemId }) => {
|
|
496
|
+
"set-workflow": async ({ itemId, signal }) => {
|
|
355
497
|
if (!isWorkflow(itemId)) return { kind: "rejected" };
|
|
356
498
|
const snapshot = inspectDelegationWorkflowSettings();
|
|
357
499
|
if (snapshot.error) return { kind: "rejected" };
|
|
@@ -364,9 +506,10 @@ async function showSubagentManager(
|
|
|
364
506
|
if (requiresReload && blockReloadWithRetainedAgents(ctx, runtime)) {
|
|
365
507
|
return { kind: "rejected" };
|
|
366
508
|
}
|
|
367
|
-
if (!(await showWorkflowPreview(ctx, active, itemId, requiresReload))) {
|
|
368
|
-
return { kind: "rejected" };
|
|
509
|
+
if (!(await showWorkflowPreview(ctx, active, itemId, requiresReload, signal))) {
|
|
510
|
+
return signal.aborted || !isCurrent() ? { kind: "close" } : { kind: "rejected" };
|
|
369
511
|
}
|
|
512
|
+
if (signal.aborted || !isCurrent()) return { kind: "close" };
|
|
370
513
|
if (requiresReload && blockReloadWithRetainedAgents(ctx, runtime)) {
|
|
371
514
|
return { kind: "rejected" };
|
|
372
515
|
}
|
|
@@ -393,21 +536,71 @@ async function showSubagentManager(
|
|
|
393
536
|
await ctx.reload();
|
|
394
537
|
return { kind: "close" };
|
|
395
538
|
},
|
|
396
|
-
"clear-agents": async () => {
|
|
539
|
+
"clear-agents": async ({ signal }) => {
|
|
397
540
|
const agents = runtime.listAgents();
|
|
398
541
|
if (agents.length === 0) return { kind: "stay" };
|
|
399
542
|
const confirmed = await ctx.ui.confirm(
|
|
400
543
|
"Clear current-session subagents?",
|
|
401
544
|
`Close and delete ${agents.length} retained agent${agents.length === 1 ? "" : "s"}?`,
|
|
545
|
+
{ signal },
|
|
402
546
|
);
|
|
547
|
+
if (signal.aborted || !isCurrent()) return { kind: "close" };
|
|
403
548
|
if (!confirmed) return { kind: "rejected" };
|
|
549
|
+
if (
|
|
550
|
+
runtime
|
|
551
|
+
.listAgents()
|
|
552
|
+
.map((agent) => agent.id)
|
|
553
|
+
.join("\0") !== agents.map((agent) => agent.id).join("\0")
|
|
554
|
+
) {
|
|
555
|
+
ctx.ui.notify(
|
|
556
|
+
"Detached agents changed while confirming; review the list again.",
|
|
557
|
+
"warning",
|
|
558
|
+
);
|
|
559
|
+
return { kind: "rejected" };
|
|
560
|
+
}
|
|
404
561
|
const cleared = await runtime.clearAgents();
|
|
562
|
+
if (signal.aborted || !isCurrent()) return { kind: "close" };
|
|
405
563
|
ctx.ui.notify(
|
|
406
564
|
`Cleared ${cleared} current-session subagent${cleared === 1 ? "" : "s"}.`,
|
|
407
565
|
"info",
|
|
408
566
|
);
|
|
409
567
|
return { kind: "stay" };
|
|
410
568
|
},
|
|
569
|
+
"set-transport": async ({ itemId, signal }) =>
|
|
570
|
+
applyTransportSetting(itemId, ctx, runtime, signal, isCurrent),
|
|
571
|
+
"apply-execution-profile": async ({ itemId, signal }) =>
|
|
572
|
+
applyExecutionProfileFromUi(itemId, ctx, signal, isCurrent),
|
|
573
|
+
"pick-execution-agent": async ({ itemId }) => {
|
|
574
|
+
selectedExecutionAgent = availableAgents.find((agent) => agent.name === itemId);
|
|
575
|
+
return selectedExecutionAgent
|
|
576
|
+
? { kind: "to", screen: "execution-agent" as const }
|
|
577
|
+
: { kind: "rejected" as const };
|
|
578
|
+
},
|
|
579
|
+
"set-agent-thinking": async ({ value }) =>
|
|
580
|
+
applyAgentThinking(selectedExecutionAgent, value, ctx),
|
|
581
|
+
"set-agent-model": async ({ itemId, value }) => {
|
|
582
|
+
const selected = value ?? (itemId.startsWith("model:") ? itemId.slice(6) : undefined);
|
|
583
|
+
return applyAgentModel(
|
|
584
|
+
selectedExecutionAgent,
|
|
585
|
+
selected === "__inherited__" ? undefined : selected,
|
|
586
|
+
ctx,
|
|
587
|
+
);
|
|
588
|
+
},
|
|
589
|
+
"set-agent-timeout": async ({ value }) =>
|
|
590
|
+
applyAgentTimeout(selectedExecutionAgent, value, ctx),
|
|
591
|
+
"reset-agent-execution": async () => resetAgentExecution(selectedExecutionAgent, ctx),
|
|
592
|
+
"set-parallel-limit": async ({ value }) =>
|
|
593
|
+
applyBlockingParallelLimitSetting(value, ctx, runtime),
|
|
594
|
+
"pick-stateful-limit": async ({ itemId }) => {
|
|
595
|
+
if (!isStatefulLimitField(itemId)) return { kind: "rejected" };
|
|
596
|
+
selectedStatefulLimit = itemId;
|
|
597
|
+
return { kind: "to", screen: "stateful-limit-input" };
|
|
598
|
+
},
|
|
599
|
+
"set-stateful-limit": async ({ value, signal }) =>
|
|
600
|
+
applyStatefulLimitSetting(selectedStatefulLimit, value, ctx, runtime, {
|
|
601
|
+
signal,
|
|
602
|
+
isCurrent,
|
|
603
|
+
}),
|
|
411
604
|
"set-completion": async ({ value }) => applyCompletionSetting(value, ctx, runtime),
|
|
412
605
|
"set-consult-resources": async ({ value }) =>
|
|
413
606
|
applyConsultResourceSetting(value, ctx, runtime),
|
|
@@ -491,7 +684,7 @@ async function showSubagentManager(
|
|
|
491
684
|
async function showSubagentSettings(
|
|
492
685
|
ctx: ExtensionCommandContext,
|
|
493
686
|
runtime: SubagentSettingsRuntime,
|
|
494
|
-
owner:
|
|
687
|
+
owner: SubagentMenuOwner,
|
|
495
688
|
) {
|
|
496
689
|
const snapshot = inspectConsultResourceSettings();
|
|
497
690
|
if (ctx.mode !== "tui") {
|
|
@@ -693,224 +886,10 @@ function blockReloadWithRetainedAgents(
|
|
|
693
886
|
return true;
|
|
694
887
|
}
|
|
695
888
|
|
|
696
|
-
async function showWorkflowPreview(
|
|
697
|
-
ctx: ExtensionCommandContext,
|
|
698
|
-
current: DelegationWorkflow,
|
|
699
|
-
next: DelegationWorkflow,
|
|
700
|
-
requiresReload: boolean,
|
|
701
|
-
): Promise<boolean> {
|
|
702
|
-
const changes = workflowEffects(current, next);
|
|
703
|
-
return ctx.ui.confirm(
|
|
704
|
-
requiresReload ? "Save delegation change and reload?" : "Save delegation change?",
|
|
705
|
-
[
|
|
706
|
-
`Current: ${workflowLabel(current)}`,
|
|
707
|
-
`New: ${workflowLabel(next)}`,
|
|
708
|
-
"",
|
|
709
|
-
"Effect:",
|
|
710
|
-
...(changes.length > 0 ? changes : ["Keep the current registered tools"]).map(
|
|
711
|
-
(effect) => `- ${effect}`,
|
|
712
|
-
),
|
|
713
|
-
`- ${requiresReload ? "Reload the extension to apply this tool surface" : "No reload is needed because the active tools already match"}`,
|
|
714
|
-
].join("\n"),
|
|
715
|
-
);
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
function showSubagentStatus(ctx: ExtensionCommandContext, runtime: SubagentSettingsRuntime) {
|
|
719
|
-
if (ctx.mode !== "tui" && !ctx.hasUI) return;
|
|
720
|
-
const snapshot = inspectCompletionDeliverySettings();
|
|
721
|
-
ctx.ui.notify(
|
|
722
|
-
formatStatus(runtime.getRuntimeStatus(), snapshot, runtime),
|
|
723
|
-
snapshot.error ? "warning" : "info",
|
|
724
|
-
);
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
function showSubagentHelp(ctx: ExtensionCommandContext, runtime: SubagentSettingsRuntime) {
|
|
728
|
-
if (ctx.mode !== "tui" && !ctx.hasUI) return;
|
|
729
|
-
ctx.ui.notify(helpLines(runtime).join("\n"), "info");
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
function statusLines(runtime: SubagentSettingsRuntime): string[] {
|
|
733
|
-
const snapshot = inspectCompletionDeliverySettings();
|
|
734
|
-
return formatStatus(runtime.getRuntimeStatus(), snapshot, runtime).split("\n");
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
function helpLines(runtime: SubagentSettingsRuntime): string[] {
|
|
738
|
-
const snapshot = inspectCompletionDeliverySettings();
|
|
739
|
-
const cwdPolicy = inspectCwdPolicySettings();
|
|
740
|
-
return [
|
|
741
|
-
"/subagents — choose delegation workflow, manage current agents, and configure agent tools",
|
|
742
|
-
"/subagents settings — configure target locations, trusted resources, and async completion",
|
|
743
|
-
"/subagents status — show current-session and user-setting values",
|
|
744
|
-
"/subagents help — show this help",
|
|
745
|
-
"Target policies control startup directories and resources, not filesystem access or sandboxing.",
|
|
746
|
-
"Manage saved folder trust with Pi /trust and restart Pi after changing it.",
|
|
747
|
-
`Runtime consultation target: ${consultationCwdLabel(runtime.getConsultationCwdPolicy())}`,
|
|
748
|
-
`Configured consultation target: ${consultationCwdLabel(cwdPolicy.consultation.value)} (${cwdPolicy.consultation.source})`,
|
|
749
|
-
`Runtime delegation target: ${delegationCwdLabel(runtime.getDelegationCwdPolicy())}`,
|
|
750
|
-
`Configured delegation target: ${delegationCwdLabel(cwdPolicy.delegation.value)} (${cwdPolicy.delegation.source})`,
|
|
751
|
-
`User settings: ${safeTerminalText(snapshot.path)}`,
|
|
752
|
-
];
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
function formatManagerSummary(
|
|
756
|
-
runtime: SubagentSettingsRuntime,
|
|
757
|
-
status: StatefulSubagentRuntimeStatus,
|
|
758
|
-
configured: ReturnType<typeof inspectDelegationWorkflowSettings>,
|
|
759
|
-
): string {
|
|
760
|
-
const current = currentWorkflow(runtime, status);
|
|
761
|
-
const cwdPolicy = inspectCwdPolicySettings();
|
|
762
|
-
const consult = inspectConsultResourceSettings();
|
|
763
|
-
return [
|
|
764
|
-
`Delegation: ${workflowLabel(current)}`,
|
|
765
|
-
`Completion: ${completionLabel(status.completionDelivery)}`,
|
|
766
|
-
`Consult target: ${consultationCwdLabel(runtime.getConsultationCwdPolicy())}`,
|
|
767
|
-
`Delegation target: ${delegationCwdLabel(runtime.getDelegationCwdPolicy())}`,
|
|
768
|
-
`Consult resources: ${consultResourceLabel(runtime.getConsultResourcePolicy())}`,
|
|
769
|
-
`Configured consult target: ${consultationCwdLabel(cwdPolicy.consultation.value)} · ${cwdPolicy.consultation.source}`,
|
|
770
|
-
`Configured delegation target: ${delegationCwdLabel(cwdPolicy.delegation.value)} · ${cwdPolicy.delegation.source}`,
|
|
771
|
-
`Configured consult resources: ${consultResourceLabel(consult.value)} · ${consult.source}`,
|
|
772
|
-
`Settings: ${safeTerminalText(cwdPolicy.path)}`,
|
|
773
|
-
`Agents: ${status.activeAgents} active · ${status.retainedAgents} retained`,
|
|
774
|
-
...(configured.value !== current
|
|
775
|
-
? [`Configured after reload: ${workflowLabel(configured.value)}`]
|
|
776
|
-
: []),
|
|
777
|
-
...(configured.error ? ["Settings need repair; open Advanced settings for details."] : []),
|
|
778
|
-
].join("\n");
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
function formatStatus(
|
|
782
|
-
status: StatefulSubagentRuntimeStatus,
|
|
783
|
-
snapshot: ReturnType<typeof inspectCompletionDeliverySettings>,
|
|
784
|
-
runtime?: SubagentSettingsRuntime,
|
|
785
|
-
): string {
|
|
786
|
-
const configuredWorkflow = inspectDelegationWorkflowSettings();
|
|
787
|
-
const consult = inspectConsultResourceSettings();
|
|
788
|
-
const cwdPolicy = inspectCwdPolicySettings();
|
|
789
|
-
const current = runtime ? currentWorkflow(runtime, status) : configuredWorkflow.value;
|
|
790
|
-
return [
|
|
791
|
-
"Current session",
|
|
792
|
-
` Delegation: ${workflowLabel(current)}`,
|
|
793
|
-
` Async runtime: ${status.initialized ? "initialized" : status.enabled ? "not initialized" : "disabled"}`,
|
|
794
|
-
` Transport: ${status.transport}`,
|
|
795
|
-
` Completion: ${completionLabel(status.completionDelivery)}`,
|
|
796
|
-
` Consultation target: ${consultationCwdLabel(runtime?.getConsultationCwdPolicy() ?? cwdPolicy.consultation.value)}`,
|
|
797
|
-
` Delegation target: ${delegationCwdLabel(runtime?.getDelegationCwdPolicy() ?? cwdPolicy.delegation.value)}`,
|
|
798
|
-
` Consultation resources: ${consultResourceLabel(runtime?.getConsultResourcePolicy() ?? consult.value)}`,
|
|
799
|
-
` Agents: ${status.activeAgents} active, ${status.retainedAgents} retained`,
|
|
800
|
-
"User settings",
|
|
801
|
-
` Delegation source: ${configuredWorkflow.source}`,
|
|
802
|
-
` Configured delegation: ${workflowLabel(configuredWorkflow.value)}`,
|
|
803
|
-
` Completion source: ${snapshot.source}`,
|
|
804
|
-
` Configured completion: ${completionLabel(snapshot.value)}`,
|
|
805
|
-
` Configured consultation target: ${consultationCwdLabel(cwdPolicy.consultation.value)}`,
|
|
806
|
-
` Consultation target source: ${cwdPolicy.consultation.source}`,
|
|
807
|
-
` Configured delegation target: ${delegationCwdLabel(cwdPolicy.delegation.value)}`,
|
|
808
|
-
` Delegation target source: ${cwdPolicy.delegation.source}`,
|
|
809
|
-
` Configured consultation resources: ${consultResourceLabel(consult.value)}`,
|
|
810
|
-
` Consultation resource source: ${consult.source}`,
|
|
811
|
-
` Path: ${safeTerminalText(snapshot.path)}`,
|
|
812
|
-
configuredWorkflow.error || snapshot.error || cwdPolicy.error
|
|
813
|
-
? ` Warning: ${safeTerminalText(configuredWorkflow.error ?? snapshot.error ?? cwdPolicy.error ?? "invalid settings")}`
|
|
814
|
-
: " Warning: none",
|
|
815
|
-
configuredWorkflow.value !== current
|
|
816
|
-
? "Configured delegation differs from this session. Run /reload to apply it."
|
|
817
|
-
: "Manual file changes require /reload.",
|
|
818
|
-
].join("\n");
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
function formatEmptyRuntime(status: StatefulSubagentRuntimeStatus): string {
|
|
822
|
-
if (!status.enabled) return "Stateful subagents are disabled in user settings.";
|
|
823
|
-
if (!status.initialized) return "Stateful subagents are not initialized for this session.";
|
|
824
|
-
return "No current-session subagents.";
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
function currentWorkflow(
|
|
828
|
-
runtime: SubagentSettingsRuntime,
|
|
829
|
-
status: StatefulSubagentRuntimeStatus,
|
|
830
|
-
): DelegationWorkflow {
|
|
831
|
-
const blocking = runtime.getBlockingEnabled();
|
|
832
|
-
if (blocking && status.enabled) return "all";
|
|
833
|
-
if (status.enabled) return "async-only";
|
|
834
|
-
if (blocking) return "blocking-only";
|
|
835
|
-
return "disabled";
|
|
836
|
-
}
|
|
837
|
-
|
|
838
889
|
function isWorkflow(value: string): value is Exclude<DelegationWorkflow, "disabled"> {
|
|
839
890
|
return value === "all" || value === "async-only" || value === "blocking-only";
|
|
840
891
|
}
|
|
841
892
|
|
|
842
|
-
function workflowLabel(value: DelegationWorkflow): string {
|
|
843
|
-
switch (value) {
|
|
844
|
-
case "all":
|
|
845
|
-
return "All delegation methods";
|
|
846
|
-
case "async-only":
|
|
847
|
-
return "Async only";
|
|
848
|
-
case "blocking-only":
|
|
849
|
-
return "Blocking only";
|
|
850
|
-
case "disabled":
|
|
851
|
-
return "Delegation disabled";
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
function completionLabel(value: CompletionDelivery): string {
|
|
856
|
-
return value === "auto-resume" ? "Resume automatically when finished" : "Wait until my next turn";
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
function consultationCwdLabel(value: ConsultationCwdPolicy): string {
|
|
860
|
-
return value === "current-workspace"
|
|
861
|
-
? "Current workspace only"
|
|
862
|
-
: "Anywhere · untrusted targets inherit nothing";
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
function delegationCwdLabel(value: DelegationCwdPolicy): string {
|
|
866
|
-
switch (value) {
|
|
867
|
-
case "trusted-targets":
|
|
868
|
-
return "Current or saved-trusted folders";
|
|
869
|
-
case "current-workspace":
|
|
870
|
-
return "Current workspace only";
|
|
871
|
-
case "anywhere":
|
|
872
|
-
return "Anywhere · normal Pi permissions";
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
function consultResourceLabel(value: ConsultResourcePolicy): string {
|
|
877
|
-
switch (value) {
|
|
878
|
-
case "project-context":
|
|
879
|
-
return "Project context only";
|
|
880
|
-
case "none":
|
|
881
|
-
return "No inherited resources";
|
|
882
|
-
case "all":
|
|
883
|
-
return "All trusted resources";
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
function workflowEffects(current: DelegationWorkflow, next: DelegationWorkflow): string[] {
|
|
888
|
-
const blockingEnabled = (value: DelegationWorkflow) =>
|
|
889
|
-
value === "all" || value === "blocking-only";
|
|
890
|
-
const asyncEnabled = (value: DelegationWorkflow) => value === "all" || value === "async-only";
|
|
891
|
-
const effects: string[] = [];
|
|
892
|
-
if (blockingEnabled(current) !== blockingEnabled(next)) {
|
|
893
|
-
effects.push(
|
|
894
|
-
blockingEnabled(next)
|
|
895
|
-
? "Add blocking `subagent` and read-only `subagent_consult`"
|
|
896
|
-
: "Remove blocking `subagent` and read-only `subagent_consult`",
|
|
897
|
-
);
|
|
898
|
-
}
|
|
899
|
-
if (asyncEnabled(current) !== asyncEnabled(next)) {
|
|
900
|
-
effects.push(
|
|
901
|
-
asyncEnabled(next)
|
|
902
|
-
? "Add reusable async lifecycle tools"
|
|
903
|
-
: "Remove reusable async lifecycle tools",
|
|
904
|
-
);
|
|
905
|
-
}
|
|
906
|
-
return effects;
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
function safeTerminalText(value: string): string {
|
|
910
|
-
// biome-ignore lint/suspicious/noControlCharactersInRegex: Escape untrusted terminal controls.
|
|
911
|
-
return value.replace(/[\u0000-\u001f\u007f-\u009f]/gu, "?");
|
|
912
|
-
}
|
|
913
|
-
|
|
914
893
|
function formatError(error: unknown): string {
|
|
915
894
|
return safeTerminalText(error instanceof Error ? error.message : String(error));
|
|
916
895
|
}
|
package/src/consult-resources.ts
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DefaultResourceLoader,
|
|
3
|
-
getAgentDir,
|
|
4
|
-
SettingsManager,
|
|
5
|
-
} from "@earendil-works/pi-coding-agent";
|
|
6
1
|
import type { ConsultResourcePolicy } from "./agents.js";
|
|
7
2
|
import { DEFAULT_MAX_CONTEXT_BYTES, truncateUtf8 } from "./limits.js";
|
|
8
|
-
import {
|
|
3
|
+
import { resolvePiPromptResources } from "./prompt-resources.js";
|
|
9
4
|
import type { ChildLaunchPolicy } from "./runner.js";
|
|
10
5
|
|
|
11
6
|
const MINIMAL_CONSULT_SYSTEM_PROMPT =
|
|
@@ -31,30 +26,12 @@ export async function resolveConsultResourceLaunchPolicy(
|
|
|
31
26
|
};
|
|
32
27
|
}
|
|
33
28
|
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
"SYSTEM.md",
|
|
37
|
-
"APPEND_SYSTEM.md",
|
|
38
|
-
]);
|
|
39
|
-
const loader = new DefaultResourceLoader({
|
|
40
|
-
cwd,
|
|
41
|
-
agentDir,
|
|
42
|
-
settingsManager: SettingsManager.inMemory({}, { projectTrusted }),
|
|
43
|
-
noExtensions: true,
|
|
44
|
-
noSkills: true,
|
|
45
|
-
noPromptTemplates: true,
|
|
46
|
-
noThemes: true,
|
|
47
|
-
noContextFiles: true,
|
|
48
|
-
});
|
|
49
|
-
await loader.reload();
|
|
50
|
-
|
|
51
|
-
const discoveredSystemPrompt = loader.getSystemPrompt();
|
|
29
|
+
const resources = await resolvePiPromptResources(cwd, projectTrusted);
|
|
30
|
+
const discoveredSystemPrompt = resources.systemPrompt;
|
|
52
31
|
const baseSystemPrompt = discoveredSystemPrompt
|
|
53
32
|
? truncateUtf8(discoveredSystemPrompt, DEFAULT_MAX_CONTEXT_BYTES).text
|
|
54
33
|
: undefined;
|
|
55
|
-
const appendSystemPromptPaths =
|
|
56
|
-
.getAppendSystemPromptSources()
|
|
57
|
-
.map((source) => source.path);
|
|
34
|
+
const appendSystemPromptPaths = resources.appendSystemPromptPaths;
|
|
58
35
|
const shared = {
|
|
59
36
|
disableExtensions: true,
|
|
60
37
|
disableContextFiles: !projectTrusted,
|
package/src/consult.ts
CHANGED
|
@@ -61,7 +61,14 @@ export const SubagentConsultParams = Type.Object(
|
|
|
61
61
|
agentScope: Type.Optional(ConsultScopeSchema),
|
|
62
62
|
confirmProjectAgents: Type.Optional(Type.Boolean({ default: true })),
|
|
63
63
|
cwd: Type.Optional(Type.String({ minLength: 1 })),
|
|
64
|
-
timeoutMs: Type.Optional(
|
|
64
|
+
timeoutMs: Type.Optional(
|
|
65
|
+
Type.Number({
|
|
66
|
+
minimum: 1,
|
|
67
|
+
maximum: MAX_SUBAGENT_TIMEOUT_MS,
|
|
68
|
+
description:
|
|
69
|
+
"Work deadline selected for the consultation difficulty. On expiry, Pi aborts the work and makes one separately bounded summary attempt.",
|
|
70
|
+
}),
|
|
71
|
+
),
|
|
65
72
|
thinkingLevel: Type.Optional(ConsultThinkingSchema),
|
|
66
73
|
},
|
|
67
74
|
{ additionalProperties: false },
|
|
@@ -191,6 +198,7 @@ export function registerSubagentConsult(
|
|
|
191
198
|
promptSnippet: "Consult one constrained read-only subagent and wait for its answer",
|
|
192
199
|
promptGuidelines: [
|
|
193
200
|
"Use subagent_consult for bounded reconnaissance, planning, or review whose result is required in the current turn.",
|
|
201
|
+
"Set subagent_consult timeoutMs to the shortest realistic work deadline for the task difficulty; split oversized consultations instead of extending the deadline merely to compensate for broad scope.",
|
|
194
202
|
"Implementation-shaped tasks remain read-only and can return only analysis or instructions.",
|
|
195
203
|
],
|
|
196
204
|
parameters: SubagentConsultParams,
|