pi-subagents 0.57.0 → 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +104 -0
- package/docs/agents.md +18 -9
- package/docs/configuration.md +4 -4
- package/docs/extension-api.md +40 -1
- package/docs/models.md +27 -4
- package/docs/observability.md +1 -1
- package/docs/tool-reference.md +92 -6
- package/docs/workflows.md +115 -0
- package/package.json +3 -1
- package/prompts/review-loop.md +2 -2
- package/skills/council-mode/SKILL.md +1 -1
- package/skills/pi-subagents/SKILL.md +3 -1
- package/skills/pi-subagents/references/execution-controls.md +6 -2
- package/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
- package/skills/pi-subagents/references/prompting-and-roles.md +26 -5
- package/src/agents/agent-management.ts +28 -17
- package/src/agents/agent-serializer.ts +9 -2
- package/src/agents/agents.ts +103 -27
- package/src/agents/runtime-agent-events.ts +70 -0
- package/src/agents/runtime-agent-registry.ts +19 -18
- package/src/api/agents.ts +10 -5
- package/src/api/background-work.ts +5 -1
- package/src/api/delegation.ts +0 -7
- package/src/api/preflight.ts +32 -10
- package/src/extension/fanout-child.ts +5 -3
- package/src/extension/index.ts +66 -27
- package/src/extension/public-execution.ts +15 -2
- package/src/extension/rpc.ts +35 -14
- package/src/extension/schemas.ts +37 -12
- package/src/extension/tool-description.ts +25 -6
- package/src/integrations/herdr-status.ts +5 -0
- package/src/intercom/result-intercom.ts +2 -0
- package/src/profiles/profiles.ts +5 -6
- package/src/runs/background/active-async-capacity.ts +2 -2
- package/src/runs/background/async-execution.ts +78 -46
- package/src/runs/background/async-job-tracker.ts +14 -12
- package/src/runs/background/async-resume.ts +29 -27
- package/src/runs/background/async-status-snapshot.ts +23 -261
- package/src/runs/background/async-status.ts +68 -7
- package/src/runs/background/chain-append.ts +8 -3
- package/src/runs/background/chain-root-attachment.ts +60 -8
- package/src/runs/background/fleet-view.ts +21 -11
- package/src/runs/background/notify.ts +184 -9
- package/src/runs/background/result-delivery-ownership.ts +45 -0
- package/src/runs/background/result-files.ts +2 -1
- package/src/runs/background/result-watcher.ts +29 -10
- package/src/runs/background/resume-guidance.ts +1 -1
- package/src/runs/background/retained-children.ts +1 -1
- package/src/runs/background/run-status.ts +18 -8
- package/src/runs/background/scheduled-runs.ts +86 -7
- package/src/runs/background/stale-run-reconciler.ts +10 -4
- package/src/runs/background/steering.ts +4 -14
- package/src/runs/background/subagent-runner.ts +389 -350
- package/src/runs/background/subagent-wait.ts +58 -10
- package/src/runs/background/terminal-run-index.ts +1 -1
- package/src/runs/background/wait-completions.ts +22 -1
- package/src/runs/background/wait-config.ts +23 -9
- package/src/runs/background/wait-tool.ts +9 -2
- package/src/runs/foreground/async-steering-action.ts +2 -2
- package/src/runs/foreground/execution.ts +134 -121
- package/src/runs/foreground/foreground-control.ts +3 -0
- package/src/runs/foreground/foreground-history.ts +1 -0
- package/src/runs/foreground/subagent-executor.ts +527 -257
- package/src/runs/foreground/workflow-detach-reconcile.ts +130 -120
- package/src/runs/shared/abort-recovery.ts +119 -0
- package/src/runs/shared/async-status-projection.ts +463 -0
- package/src/runs/shared/child-identity.ts +19 -4
- package/src/runs/shared/child-launch-plan.ts +151 -0
- package/src/runs/shared/completion-evidence.ts +89 -0
- package/src/runs/shared/completion-guard.ts +5 -4
- package/src/runs/shared/dynamic-fanout.ts +3 -3
- package/src/runs/shared/fast-mode-extension.ts +5 -5
- package/src/runs/shared/host-step-status.ts +230 -0
- package/src/runs/shared/lane-metadata.ts +105 -0
- package/src/runs/shared/launch-cwd.ts +16 -0
- package/src/runs/shared/long-running-guard.ts +2 -1
- package/src/runs/shared/mcp-config-sources.ts +422 -0
- package/src/runs/shared/mcp-direct-tool-allowlist.ts +221 -158
- package/src/runs/shared/mcp-direct-tool-grant.ts +197 -0
- package/src/runs/shared/model-exclusions.ts +12 -0
- package/src/runs/shared/model-fallback.ts +25 -6
- package/src/runs/shared/nested-events.ts +6 -2
- package/src/runs/shared/nested-render.ts +7 -3
- package/src/runs/shared/parallel-handoff.ts +419 -7
- package/src/runs/shared/parallel-utils.ts +15 -1
- package/src/runs/shared/pi-args.ts +81 -8
- package/src/runs/shared/single-output.ts +44 -4
- package/src/runs/shared/subagent-prompt-runtime.ts +98 -13
- package/src/runs/shared/worktree-cleanup-plan.ts +847 -0
- package/src/runs/shared/worktree.ts +18 -0
- package/src/shared/child-session-name.ts +46 -0
- package/src/shared/extension-context.ts +24 -0
- package/src/shared/formatters.ts +11 -2
- package/src/shared/launch-contract.ts +5 -1
- package/src/shared/settings.ts +9 -103
- package/src/shared/types.ts +240 -30
- package/src/shared/utils.ts +41 -84
- package/src/slash/delegation-adapters.ts +1 -8
- package/src/slash/delegation-request.ts +0 -4
- package/src/slash/slash-bridge.ts +1 -2
- package/src/slash/slash-commands.ts +369 -90
- package/src/slash/slash-live-state.ts +22 -11
- package/src/slash/subagents-admin.ts +3 -0
- package/src/tui/fleet-status.ts +125 -74
- package/src/tui/fleet.ts +11 -5
- package/src/tui/render.ts +330 -33
- package/src/watchdog/turn-delta.ts +1 -1
- package/src/workflows/chat-progress.ts +6 -3
- package/src/workflows/host-command.ts +230 -0
- package/src/workflows/scripted-workflow.ts +496 -35
- package/src/workflows/workflow-child-summary.ts +9 -5
- package/src/workflows/workflow-preflight.ts +270 -0
- package/src/workflows/workflow-receipt.ts +79 -5
- package/src/workflows/workflow-settlement.ts +246 -0
- package/src/runs/shared/turn-budget.ts +0 -98
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import type { AcceptanceInput, AcceptanceRole, AgentRunnerConfig, OutputMode, ToolBudgetConfig
|
|
2
|
+
import type { AcceptanceInput, AcceptanceRole, AgentRunnerConfig, OutputMode, ToolBudgetConfig } from "../shared/types.ts";
|
|
3
3
|
import { CODE_OWNED_EXTERNAL_CLI_ADAPTER_LABEL, isCodeOwnedExternalCliAdapterId, parseExternalCliCapabilityNarrowing, validateCodeOwnedProfileRunner } from "../runs/shared/external-cli-contract.ts";
|
|
4
4
|
import { validateAcceptanceInput } from "../runs/shared/acceptance.ts";
|
|
5
5
|
import { validatePermissionRules, type PermissionRules } from "../runs/shared/permissions.ts";
|
|
6
6
|
import { validateToolBudgetConfig } from "../runs/shared/tool-budget.ts";
|
|
7
|
-
import { resolveTurnBudgetConfig } from "../runs/shared/turn-budget.ts";
|
|
8
7
|
import { BUILTIN_AGENT_NAMES } from "./builtin-names.ts";
|
|
9
8
|
import type { AgentConfig, AgentDefaultContext, AgentDiscoveryDiagnostic } from "./agents.ts";
|
|
10
9
|
|
|
@@ -21,18 +20,19 @@ export interface RuntimeAgentDefinition {
|
|
|
21
20
|
systemPrompt: string;
|
|
22
21
|
aliases?: readonly string[];
|
|
23
22
|
tools?: readonly string[];
|
|
23
|
+
allowNestedSubagents?: boolean;
|
|
24
24
|
mcpDirectTools?: readonly string[];
|
|
25
25
|
model?: string;
|
|
26
26
|
fallbackModels?: readonly string[];
|
|
27
27
|
thinking?: string | false;
|
|
28
28
|
systemPromptMode?: "append" | "replace";
|
|
29
29
|
inheritProjectContext?: boolean;
|
|
30
|
+
inheritGlobalContext?: boolean;
|
|
30
31
|
inheritSkills?: boolean;
|
|
31
32
|
defaultContext?: AgentDefaultContext;
|
|
32
33
|
defaultAsync?: boolean;
|
|
33
34
|
defaultTimeoutMs?: number;
|
|
34
35
|
defaultToolTimeoutMs?: number;
|
|
35
|
-
defaultTurnBudget?: TurnBudgetConfig;
|
|
36
36
|
defaultAcceptance?: AcceptanceInput;
|
|
37
37
|
acceptanceRole?: AcceptanceRole;
|
|
38
38
|
runner?: AgentRunnerConfig;
|
|
@@ -40,6 +40,7 @@ export interface RuntimeAgentDefinition {
|
|
|
40
40
|
skillPath?: readonly string[];
|
|
41
41
|
extensions?: readonly string[];
|
|
42
42
|
subagentOnlyExtensions?: readonly string[];
|
|
43
|
+
mutationTools?: readonly string[];
|
|
43
44
|
output?: string;
|
|
44
45
|
outputMode?: OutputMode;
|
|
45
46
|
defaultReads?: readonly string[];
|
|
@@ -133,8 +134,8 @@ function validateStringList(value: unknown, field: string): string[] | undefined
|
|
|
133
134
|
|
|
134
135
|
function validatePositiveInteger(value: unknown, field: string): number | undefined {
|
|
135
136
|
if (value === undefined) return undefined;
|
|
136
|
-
if (!Number.isInteger(value) ||
|
|
137
|
-
return value
|
|
137
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) throw new Error(`${field} must be a positive integer when provided.`);
|
|
138
|
+
return value;
|
|
138
139
|
}
|
|
139
140
|
|
|
140
141
|
function validateBoolean(value: unknown, field: string): boolean | undefined {
|
|
@@ -181,12 +182,6 @@ function validateRunner(value: unknown): AgentRunnerConfig | undefined {
|
|
|
181
182
|
return { type: "external-cli", ...(isCodeOwnedExternalCliAdapterId(runner.adapter) ? { adapter: runner.adapter } : {}), command: runner.command.trim(), ...(args?.length ? { args } : {}), ...(runner.promptDelivery ? { promptDelivery: "stdin" as const } : {}), ...(capabilities ? { capabilities } : {}) };
|
|
182
183
|
}
|
|
183
184
|
|
|
184
|
-
function validateTurnBudget(value: unknown): TurnBudgetConfig | undefined {
|
|
185
|
-
const result = resolveTurnBudgetConfig(value, "Runtime agent definition defaultTurnBudget");
|
|
186
|
-
if (result.error) throw new Error(result.error);
|
|
187
|
-
return result.turnBudget;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
185
|
function validateAcceptance(value: unknown): AcceptanceInput | undefined {
|
|
191
186
|
const errors = validateAcceptanceInput(value, "Runtime agent definition defaultAcceptance");
|
|
192
187
|
if (errors.length > 0) throw new Error(errors.join(" "));
|
|
@@ -203,10 +198,10 @@ function validateDefinition(value: unknown): RuntimeAgentDefinition {
|
|
|
203
198
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Runtime agent definition must be an object.");
|
|
204
199
|
const definition = value as Record<string, unknown>;
|
|
205
200
|
const supported = new Set([
|
|
206
|
-
"description", "systemPrompt", "aliases", "tools", "mcpDirectTools", "model", "fallbackModels", "thinking",
|
|
207
|
-
"systemPromptMode", "inheritProjectContext", "inheritSkills", "defaultContext", "defaultAsync", "defaultTimeoutMs",
|
|
208
|
-
"defaultToolTimeoutMs", "
|
|
209
|
-
"extensions", "subagentOnlyExtensions", "output", "outputMode", "defaultReads", "defaultProgress", "interactive",
|
|
201
|
+
"description", "systemPrompt", "aliases", "tools", "allowNestedSubagents", "mcpDirectTools", "model", "fallbackModels", "thinking",
|
|
202
|
+
"systemPromptMode", "inheritProjectContext", "inheritGlobalContext", "inheritSkills", "defaultContext", "defaultAsync", "defaultTimeoutMs",
|
|
203
|
+
"defaultToolTimeoutMs", "defaultAcceptance", "acceptanceRole", "runner", "skills", "skillPath",
|
|
204
|
+
"extensions", "subagentOnlyExtensions", "mutationTools", "output", "outputMode", "defaultReads", "defaultProgress", "interactive",
|
|
210
205
|
"maxSubagentDepth", "completionGuard", "toolBudget", "permissions",
|
|
211
206
|
]);
|
|
212
207
|
const unknown = Object.keys(definition).filter((key) => !supported.has(key));
|
|
@@ -223,21 +218,23 @@ function validateDefinition(value: unknown): RuntimeAgentDefinition {
|
|
|
223
218
|
if (outputMode !== undefined && outputMode !== "inline" && outputMode !== "file-only") throw new Error("Runtime agent definition outputMode must be 'inline' or 'file-only'.");
|
|
224
219
|
const aliases = validateStringList(definition.aliases, "Runtime agent definition aliases");
|
|
225
220
|
const tools = validateStringList(definition.tools, "Runtime agent definition tools");
|
|
221
|
+
const allowNestedSubagents = validateBoolean(definition.allowNestedSubagents, "Runtime agent definition allowNestedSubagents");
|
|
226
222
|
const mcpDirectTools = validateStringList(definition.mcpDirectTools, "Runtime agent definition mcpDirectTools");
|
|
227
223
|
const model = validateOptionalString(definition.model, "Runtime agent definition model");
|
|
228
224
|
const fallbackModels = validateStringList(definition.fallbackModels, "Runtime agent definition fallbackModels");
|
|
229
225
|
const inheritProjectContext = validateBoolean(definition.inheritProjectContext, "Runtime agent definition inheritProjectContext");
|
|
226
|
+
const inheritGlobalContext = validateBoolean(definition.inheritGlobalContext, "Runtime agent definition inheritGlobalContext");
|
|
230
227
|
const inheritSkills = validateBoolean(definition.inheritSkills, "Runtime agent definition inheritSkills");
|
|
231
228
|
const defaultAsync = validateBoolean(definition.defaultAsync, "Runtime agent definition defaultAsync");
|
|
232
229
|
const defaultTimeoutMs = validatePositiveInteger(definition.defaultTimeoutMs, "Runtime agent definition defaultTimeoutMs");
|
|
233
230
|
const defaultToolTimeoutMs = validatePositiveInteger(definition.defaultToolTimeoutMs, "Runtime agent definition defaultToolTimeoutMs");
|
|
234
|
-
const defaultTurnBudget = validateTurnBudget(definition.defaultTurnBudget);
|
|
235
231
|
const defaultAcceptance = validateAcceptance(definition.defaultAcceptance);
|
|
236
232
|
const runner = validateRunner(definition.runner);
|
|
237
233
|
const skills = validateStringList(definition.skills, "Runtime agent definition skills");
|
|
238
234
|
const skillPath = validateStringList(definition.skillPath, "Runtime agent definition skillPath");
|
|
239
235
|
const extensions = validateStringList(definition.extensions, "Runtime agent definition extensions");
|
|
240
236
|
const subagentOnlyExtensions = validateStringList(definition.subagentOnlyExtensions, "Runtime agent definition subagentOnlyExtensions");
|
|
237
|
+
const mutationTools = validateStringList(definition.mutationTools, "Runtime agent definition mutationTools");
|
|
241
238
|
const output = validateOptionalString(definition.output, "Runtime agent definition output");
|
|
242
239
|
const defaultReads = validateStringList(definition.defaultReads, "Runtime agent definition defaultReads");
|
|
243
240
|
const defaultProgress = validateBoolean(definition.defaultProgress, "Runtime agent definition defaultProgress");
|
|
@@ -251,18 +248,19 @@ function validateDefinition(value: unknown): RuntimeAgentDefinition {
|
|
|
251
248
|
systemPrompt: validateString(definition.systemPrompt, "Runtime agent definition systemPrompt", MAX_SYSTEM_PROMPT_LENGTH),
|
|
252
249
|
...(aliases ? { aliases } : {}),
|
|
253
250
|
...(tools ? { tools } : {}),
|
|
251
|
+
...(allowNestedSubagents !== undefined ? { allowNestedSubagents } : {}),
|
|
254
252
|
...(mcpDirectTools ? { mcpDirectTools } : {}),
|
|
255
253
|
...(model ? { model } : {}),
|
|
256
254
|
...(fallbackModels ? { fallbackModels } : {}),
|
|
257
255
|
...(thinking !== undefined ? { thinking: thinking as string | false } : {}),
|
|
258
256
|
...(systemPromptMode !== undefined ? { systemPromptMode: systemPromptMode as "append" | "replace" } : {}),
|
|
259
257
|
...(inheritProjectContext !== undefined ? { inheritProjectContext } : {}),
|
|
258
|
+
...(inheritGlobalContext !== undefined ? { inheritGlobalContext } : {}),
|
|
260
259
|
...(inheritSkills !== undefined ? { inheritSkills } : {}),
|
|
261
260
|
...(defaultContext !== undefined ? { defaultContext: defaultContext as AgentDefaultContext } : {}),
|
|
262
261
|
...(defaultAsync !== undefined ? { defaultAsync } : {}),
|
|
263
262
|
...(defaultTimeoutMs !== undefined ? { defaultTimeoutMs } : {}),
|
|
264
263
|
...(defaultToolTimeoutMs !== undefined ? { defaultToolTimeoutMs } : {}),
|
|
265
|
-
...(defaultTurnBudget !== undefined ? { defaultTurnBudget } : {}),
|
|
266
264
|
...(defaultAcceptance !== undefined ? { defaultAcceptance } : {}),
|
|
267
265
|
...(acceptanceRole !== undefined ? { acceptanceRole: acceptanceRole as AcceptanceRole } : {}),
|
|
268
266
|
...(runner !== undefined ? { runner } : {}),
|
|
@@ -270,6 +268,7 @@ function validateDefinition(value: unknown): RuntimeAgentDefinition {
|
|
|
270
268
|
...(skillPath ? { skillPath } : {}),
|
|
271
269
|
...(extensions ? { extensions } : {}),
|
|
272
270
|
...(subagentOnlyExtensions ? { subagentOnlyExtensions } : {}),
|
|
271
|
+
...(mutationTools ? { mutationTools } : {}),
|
|
273
272
|
...(output ? { output } : {}),
|
|
274
273
|
...(outputMode !== undefined ? { outputMode: outputMode as OutputMode } : {}),
|
|
275
274
|
...(defaultReads ? { defaultReads } : {}),
|
|
@@ -328,18 +327,19 @@ function toAgentConfig(name: string, definition: RuntimeAgentDefinition): AgentC
|
|
|
328
327
|
...(aliases ? { aliases } : {}),
|
|
329
328
|
...(definition.runner !== undefined ? { runner: definition.runner } : {}),
|
|
330
329
|
...(definition.tools !== undefined ? { tools: [...definition.tools] } : {}),
|
|
330
|
+
...(definition.allowNestedSubagents !== undefined ? { allowNestedSubagents: definition.allowNestedSubagents } : {}),
|
|
331
331
|
...(definition.mcpDirectTools !== undefined ? { mcpDirectTools: [...definition.mcpDirectTools] } : {}),
|
|
332
332
|
...(definition.model !== undefined ? { model: definition.model } : {}),
|
|
333
333
|
...(definition.fallbackModels !== undefined ? { fallbackModels: [...definition.fallbackModels] } : {}),
|
|
334
334
|
...(definition.thinking !== undefined ? { thinking: definition.thinking } : {}),
|
|
335
335
|
systemPromptMode: definition.systemPromptMode ?? defaultSystemPromptMode(name),
|
|
336
336
|
inheritProjectContext: definition.inheritProjectContext ?? defaultInheritProjectContext(name),
|
|
337
|
+
inheritGlobalContext: definition.inheritGlobalContext ?? false,
|
|
337
338
|
inheritSkills: definition.inheritSkills ?? defaultInheritSkills(),
|
|
338
339
|
...(definition.defaultContext !== undefined ? { defaultContext: definition.defaultContext } : {}),
|
|
339
340
|
...(definition.defaultAsync !== undefined ? { defaultAsync: definition.defaultAsync } : {}),
|
|
340
341
|
...(definition.defaultTimeoutMs !== undefined ? { defaultTimeoutMs: definition.defaultTimeoutMs } : {}),
|
|
341
342
|
...(definition.defaultToolTimeoutMs !== undefined ? { defaultToolTimeoutMs: definition.defaultToolTimeoutMs } : {}),
|
|
342
|
-
...(definition.defaultTurnBudget !== undefined ? { defaultTurnBudget: definition.defaultTurnBudget } : {}),
|
|
343
343
|
...(definition.defaultAcceptance !== undefined ? { defaultAcceptance: definition.defaultAcceptance } : {}),
|
|
344
344
|
...(definition.acceptanceRole !== undefined ? { acceptanceRole: definition.acceptanceRole } : {}),
|
|
345
345
|
systemPrompt: definition.systemPrompt,
|
|
@@ -349,6 +349,7 @@ function toAgentConfig(name: string, definition: RuntimeAgentDefinition): AgentC
|
|
|
349
349
|
...(definition.skillPath !== undefined ? { skillPath: [...definition.skillPath] } : {}),
|
|
350
350
|
...(definition.extensions !== undefined ? { extensions: [...definition.extensions] } : {}),
|
|
351
351
|
...(definition.subagentOnlyExtensions !== undefined ? { subagentOnlyExtensions: [...definition.subagentOnlyExtensions] } : {}),
|
|
352
|
+
...(definition.mutationTools !== undefined ? { mutationTools: [...definition.mutationTools] } : {}),
|
|
352
353
|
...(definition.output !== undefined ? { output: definition.output } : {}),
|
|
353
354
|
...(definition.outputMode !== undefined ? { outputMode: definition.outputMode } : {}),
|
|
354
355
|
...(definition.defaultReads !== undefined ? { defaultReads: [...definition.defaultReads] } : {}),
|
package/src/api/agents.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { RegisterRuntimeAgentInput, RuntimeAgentDefinition, RuntimeAgentRegistration } from "../agents/runtime-agent-registry.ts";
|
|
2
|
+
export { registerRuntimeAgent as registerAgent } from "../agents/runtime-agent-registry.ts";
|
|
3
|
+
export {
|
|
4
|
+
RUNTIME_AGENT_REGISTER_EVENT,
|
|
5
|
+
RUNTIME_AGENT_REGISTER_VERSION,
|
|
6
|
+
registerAgentViaEvents,
|
|
7
|
+
type RegisterRuntimeAgentViaEventsInput,
|
|
8
|
+
type RuntimeAgentRegistrationRequest,
|
|
9
|
+
type RuntimeAgentRegistrationResult,
|
|
10
|
+
} from "../agents/runtime-agent-events.ts";
|
|
2
11
|
|
|
3
12
|
export type { RegisterRuntimeAgentInput, RuntimeAgentDefinition, RuntimeAgentRegistration };
|
|
4
|
-
|
|
5
|
-
export function registerAgent(input: RegisterRuntimeAgentInput): RuntimeAgentRegistration {
|
|
6
|
-
return registerRuntimeAgent(input);
|
|
7
|
-
}
|
|
@@ -4,7 +4,11 @@ export const BACKGROUND_WORK_REGISTRY_KEY = "pi-subagents.background-work.v1";
|
|
|
4
4
|
const MAX_PROVIDER_NAME_LENGTH = 128;
|
|
5
5
|
const MAX_PROVIDERS = 100;
|
|
6
6
|
const MAX_ITEM_ID_LENGTH = 256;
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* A Pi session id is the session file path, which routinely exceeds a short
|
|
9
|
+
* identity budget in nested worktrees, so it is bounded like the other paths.
|
|
10
|
+
*/
|
|
11
|
+
const MAX_SESSION_ID_LENGTH = 4_096;
|
|
8
12
|
const MAX_WAKE_CHANNEL_LENGTH = 256;
|
|
9
13
|
const MAX_ITEMS_PER_PROVIDER = 10_000;
|
|
10
14
|
|
package/src/api/delegation.ts
CHANGED
|
@@ -7,11 +7,6 @@ export const SUBAGENT_DELEGATION_UPDATE_EVENT = "prompt-template:subagent:update
|
|
|
7
7
|
export const SUBAGENT_DELEGATION_RESPONSE_EVENT = "prompt-template:subagent:response";
|
|
8
8
|
export const SUBAGENT_DELEGATION_CANCEL_EVENT = "prompt-template:subagent:cancel";
|
|
9
9
|
|
|
10
|
-
export interface SubagentDelegationTurnBudget {
|
|
11
|
-
maxTurns: number;
|
|
12
|
-
graceTurns?: number;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
10
|
export interface SubagentDelegationToolBudget {
|
|
16
11
|
soft?: number;
|
|
17
12
|
hard: number;
|
|
@@ -37,7 +32,6 @@ export interface SubagentDelegationRequest {
|
|
|
37
32
|
model?: string;
|
|
38
33
|
thinking?: SubagentDelegationThinking;
|
|
39
34
|
timeoutMs?: number;
|
|
40
|
-
turnBudget?: SubagentDelegationTurnBudget;
|
|
41
35
|
toolBudget?: SubagentDelegationToolBudget;
|
|
42
36
|
skill?: string | string[] | boolean;
|
|
43
37
|
artifacts?: boolean;
|
|
@@ -69,7 +63,6 @@ export type SubagentDelegationStatus =
|
|
|
69
63
|
| "timed_out"
|
|
70
64
|
| "cancelled"
|
|
71
65
|
| "interrupted"
|
|
72
|
-
| "turn_budget_exhausted"
|
|
73
66
|
| "tool_budget_exhausted"
|
|
74
67
|
| "structured_output_failed"
|
|
75
68
|
| "acceptance_failed"
|
package/src/api/preflight.ts
CHANGED
|
@@ -14,9 +14,7 @@ import { resolveEffectiveThinking } from "../shared/model-info.ts";
|
|
|
14
14
|
import { assertThinkingWithinCeiling, decodeThinkingCeiling, intersectThinkingCeilings, SUBAGENT_THINKING_CEILING_ENV, type ThinkingLevel } from "../shared/thinking-ceiling.ts";
|
|
15
15
|
import { SUBAGENT_LIFECYCLE_ARTIFACT_VERSION, type ArtifactDirPreference, type ArtifactPaths, type JsonSchemaObject, type OutputMode } from "../shared/types.ts";
|
|
16
16
|
import { capabilityCeilingAgentRestrictionMessage, intersectSubagentCapabilityCeilings, type ResolvedSubagentCapabilityCeiling, type SubagentCapabilityAudit } from "../runs/shared/capability-ceiling.ts";
|
|
17
|
-
import { appendTurnBudgetSystemPrompt } from "../runs/shared/turn-budget.ts";
|
|
18
17
|
import { resolvePermissionRules } from "../runs/shared/permissions.ts";
|
|
19
|
-
import type { ResolvedTurnBudget } from "../shared/types.ts";
|
|
20
18
|
import type { ResolvedMcpDirectToolSelection } from "../runs/shared/mcp-direct-tool-allowlist.ts";
|
|
21
19
|
import { resolveStepBehavior } from "../shared/settings.ts";
|
|
22
20
|
import { canPreferForkFromSnapshot, resolveSubagentLaunchContext } from "../shared/fork-context.ts";
|
|
@@ -42,8 +40,10 @@ export type SubagentLaunchContractReasonCode =
|
|
|
42
40
|
| "thinking_ceiling"
|
|
43
41
|
| "invalid_extension_bindings";
|
|
44
42
|
|
|
43
|
+
export type SubagentLaunchContractDiagnosticCode = SubagentLaunchContractReasonCode | "host_required" | "snapshot_warning" | "workspace_scope_authority";
|
|
44
|
+
|
|
45
45
|
export interface SubagentLaunchContractDiagnostic {
|
|
46
|
-
code:
|
|
46
|
+
code: SubagentLaunchContractDiagnosticCode;
|
|
47
47
|
severity: "error" | "warning" | "host-required";
|
|
48
48
|
message: string;
|
|
49
49
|
}
|
|
@@ -67,7 +67,6 @@ export interface SubagentLaunchContractInput {
|
|
|
67
67
|
outputMode?: OutputMode;
|
|
68
68
|
outputSchema?: JsonSchemaObject;
|
|
69
69
|
extensionBindings?: ExtensionBindings;
|
|
70
|
-
turnBudget?: ResolvedTurnBudget;
|
|
71
70
|
artifacts?: boolean;
|
|
72
71
|
artifactDir?: ArtifactDirPreference;
|
|
73
72
|
parentSessionFile?: string | null;
|
|
@@ -157,6 +156,7 @@ export interface SubagentLaunchContract {
|
|
|
157
156
|
thinkingCeiling?: ThinkingLevel;
|
|
158
157
|
systemPromptMode: AgentConfig["systemPromptMode"];
|
|
159
158
|
inheritProjectContext: boolean;
|
|
159
|
+
inheritGlobalContext: boolean;
|
|
160
160
|
inheritSkills: boolean;
|
|
161
161
|
skills: SubagentLaunchContractSkills;
|
|
162
162
|
tools: SubagentLaunchContractTools;
|
|
@@ -204,8 +204,26 @@ function resolveLaunchContractContext(input: SubagentLaunchContractInput, agent:
|
|
|
204
204
|
});
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
function
|
|
208
|
-
|
|
207
|
+
function taskWorkspaceScopeAuthorityDiagnostic(task: string | undefined): SubagentLaunchContractDiagnostic | undefined {
|
|
208
|
+
if (!task) return undefined;
|
|
209
|
+
const text = task.replace(/\s+/g, " ").trim();
|
|
210
|
+
if (!text) return undefined;
|
|
211
|
+
const createsWorkspacePackage = /\b(?:add|create|introduce|make|set up)\b.{0,80}\b(?:new\s+)?(?:workspace\s+)?package\b/i.test(text)
|
|
212
|
+
|| /\b(?:new\s+)?package\b.{0,80}\b(?:workspace|monorepo)\b/i.test(text);
|
|
213
|
+
if (!createsWorkspacePackage) return undefined;
|
|
214
|
+
const packageOnlyAuthority = /\b(?:only|solely)\b.{0,40}\b(?:edit|change|modify|touch|write(?:\s+to)?)\b.{0,80}\b(?:package(?:\s+directory)?|packages\/[\w.-]+)\b/i.test(text)
|
|
215
|
+
|| /\b(?:do not|don't|must not)\b.{0,40}\b(?:edit|change|modify|touch|write(?:\s+to)?)\b.{0,80}\b(?:root|workspace|lockfile|metadata)\b/i.test(text)
|
|
216
|
+
|| /\bwithout\b.{0,40}\b(?:root|workspace|lockfile|metadata)\b.{0,40}\b(?:edit|change|modification|write)s?\b/i.test(text);
|
|
217
|
+
if (!packageOnlyAuthority) return undefined;
|
|
218
|
+
return {
|
|
219
|
+
code: "workspace_scope_authority",
|
|
220
|
+
severity: "warning",
|
|
221
|
+
message: "Task asks for a workspace package change while limiting authority to package-scope edits. New workspace packages often need root workspace metadata or lockfile changes, so confirm that authority before launch.",
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function candidateList(inputAgent: string, selected: AgentConfig | undefined, cwd: string, provider?: string): SubagentLaunchContractAgentCandidate[] {
|
|
226
|
+
const all = discoverAgentsAll(cwd, provider);
|
|
209
227
|
return [...all.builtin, ...all.package, ...all.user, ...all.project]
|
|
210
228
|
.filter((agent) => Boolean(resolveAgentName(inputAgent, [agent]).agent))
|
|
211
229
|
.map((agent) => ({
|
|
@@ -221,6 +239,8 @@ function candidateList(inputAgent: string, selected: AgentConfig | undefined, cw
|
|
|
221
239
|
|
|
222
240
|
export async function resolveSubagentLaunchContract(input: SubagentLaunchContractInput): Promise<SubagentLaunchContractResult> {
|
|
223
241
|
const diagnostics: SubagentLaunchContractDiagnostic[] = [];
|
|
242
|
+
const authorityDiagnostic = taskWorkspaceScopeAuthorityDiagnostic(input.task);
|
|
243
|
+
if (authorityDiagnostic) diagnostics.push(authorityDiagnostic);
|
|
224
244
|
const effectiveCwd = path.resolve(input.cwd);
|
|
225
245
|
try {
|
|
226
246
|
if (!fs.statSync(effectiveCwd).isDirectory()) {
|
|
@@ -237,7 +257,8 @@ export async function resolveSubagentLaunchContract(input: SubagentLaunchContrac
|
|
|
237
257
|
return { ok: false, code: "invalid_artifact_dir", message: `Unsupported artifactDir '${String(input.artifactDir)}'; expected 'project', 'session', or 'temp'.`, diagnostics };
|
|
238
258
|
}
|
|
239
259
|
const scope = resolveExecutionAgentScope(input.agentScope);
|
|
240
|
-
const
|
|
260
|
+
const parentProvider = input.preferredProvider ?? input.parentModel?.provider;
|
|
261
|
+
const discovered = discoverAgents(effectiveCwd, scope, parentProvider);
|
|
241
262
|
const resolvedAgent = resolveAgentName(input.agent, discovered.agents);
|
|
242
263
|
const ambiguousCandidates = resolvedAgent.error
|
|
243
264
|
? discovered.agents.filter((agent) => resolveAgentName(input.agent, [agent]).agent)
|
|
@@ -330,6 +351,7 @@ export async function resolveSubagentLaunchContract(input: SubagentLaunchContrac
|
|
|
330
351
|
try {
|
|
331
352
|
toolPlan = resolvePiLaunchToolPlan({
|
|
332
353
|
tools: agent.tools,
|
|
354
|
+
allowNestedSubagents: agent.allowNestedSubagents,
|
|
333
355
|
extensions: agent.extensions,
|
|
334
356
|
subagentOnlyExtensions: agent.subagentOnlyExtensions,
|
|
335
357
|
mcpDirectTools: agent.mcpDirectTools,
|
|
@@ -375,9 +397,7 @@ export async function resolveSubagentLaunchContract(input: SubagentLaunchContrac
|
|
|
375
397
|
const memoryInjection = buildAgentMemoryInjection(agent, effectiveCwd);
|
|
376
398
|
if (memoryInjection) effectiveSystemPrompt = effectiveSystemPrompt ? `${effectiveSystemPrompt}\n\n${memoryInjection}` : memoryInjection;
|
|
377
399
|
effectiveSystemPrompt = injectOutputPathSystemPrompt(effectiveSystemPrompt, outputPath, agent);
|
|
378
|
-
const
|
|
379
|
-
effectiveSystemPrompt = appendTurnBudgetSystemPrompt(effectiveSystemPrompt, turnBudget);
|
|
380
|
-
const candidates = candidateList(input.agent, agent, effectiveCwd);
|
|
400
|
+
const candidates = candidateList(input.agent, agent, effectiveCwd, parentProvider);
|
|
381
401
|
const shadowedCandidates = candidates.filter((candidate) => !candidate.selected);
|
|
382
402
|
const definitionDigest = agentDefinitionDigest(agent);
|
|
383
403
|
const contractBase: Omit<SubagentLaunchContract, "digest"> = {
|
|
@@ -400,6 +420,7 @@ export async function resolveSubagentLaunchContract(input: SubagentLaunchContrac
|
|
|
400
420
|
...(thinkingCeiling ? { thinkingCeiling } : {}),
|
|
401
421
|
systemPromptMode: agent.systemPromptMode,
|
|
402
422
|
inheritProjectContext: agent.inheritProjectContext,
|
|
423
|
+
inheritGlobalContext: agent.inheritGlobalContext,
|
|
403
424
|
inheritSkills: agent.inheritSkills,
|
|
404
425
|
skills: {
|
|
405
426
|
requested: requestedSkills,
|
|
@@ -455,6 +476,7 @@ export async function resolveSubagentLaunchContract(input: SubagentLaunchContrac
|
|
|
455
476
|
systemPrompt: effectiveSystemPrompt,
|
|
456
477
|
systemPromptMode: agent.systemPromptMode,
|
|
457
478
|
inheritProjectContext: agent.inheritProjectContext,
|
|
479
|
+
inheritGlobalContext: agent.inheritGlobalContext,
|
|
458
480
|
inheritSkills: agent.inheritSkills,
|
|
459
481
|
skills: requestedSkills,
|
|
460
482
|
tools: toolPlan.effectiveToolAllowlist,
|
|
@@ -158,13 +158,15 @@ export default function registerFanoutChildSubagentExtension(pi: ExtensionAPI):
|
|
|
158
158
|
registeredApis.add(pi);
|
|
159
159
|
|
|
160
160
|
const config = loadConfig();
|
|
161
|
+
const waitToolConfig = resolveWaitToolConfig(config.waitTool);
|
|
161
162
|
const state = createChildSafeState();
|
|
162
163
|
const executor = createSubagentExecutor({
|
|
163
164
|
pi,
|
|
164
165
|
state,
|
|
165
166
|
config,
|
|
166
167
|
asyncByDefault: resolveAsyncByDefault(config),
|
|
167
|
-
waitToolEnabled:
|
|
168
|
+
waitToolEnabled: waitToolConfig.enabled,
|
|
169
|
+
waitToolDefaultTimeoutMs: waitToolConfig.defaultTimeoutMs,
|
|
168
170
|
tempArtifactsDir: getArtifactsDir(null),
|
|
169
171
|
getSubagentSessionRoot,
|
|
170
172
|
expandTilde,
|
|
@@ -178,8 +180,8 @@ export default function registerFanoutChildSubagentExtension(pi: ExtensionAPI):
|
|
|
178
180
|
label: "Subagent",
|
|
179
181
|
description: [
|
|
180
182
|
"Delegate to subagents from child-safe fanout mode.",
|
|
181
|
-
"Allowed management/control actions: list, get, status, interrupt, resume, steer, doctor.",
|
|
182
|
-
"Mutating management actions (create, update, delete, eject, disable, enable, reset, grant-spawn-budget) are blocked in this mode.",
|
|
183
|
+
"Allowed management/control actions: list, get, status, lane.status, interrupt, resume, steer, doctor.",
|
|
184
|
+
"Mutating management actions (create, update, delete, eject, disable, enable, reset, grant-spawn-budget, lane.recordMerge, lane.recordSupersession) are blocked in this mode.",
|
|
183
185
|
].join("\n"),
|
|
184
186
|
parameters: params,
|
|
185
187
|
async execute(id, params, signal, onUpdate, ctx) {
|