pi-subagents 0.36.0 → 0.37.1
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 +38 -0
- package/README.md +111 -16
- package/agents/delegate.md +2 -0
- package/agents/planner.md +2 -1
- package/agents/worker.md +2 -0
- package/package.json +6 -4
- package/skills/pi-subagents/SKILL.md +18 -973
- package/skills/pi-subagents/references/constraints-and-recipes.md +256 -0
- package/skills/pi-subagents/references/execution-controls.md +411 -0
- package/skills/pi-subagents/references/management-authoring-rpc.md +140 -0
- package/skills/pi-subagents/references/prompting-and-roles.md +268 -0
- package/src/agents/agent-management.ts +7 -1
- package/src/agents/agents.ts +99 -12
- package/src/api/capability-ceiling.ts +17 -0
- package/src/api/delegation.ts +6 -1
- package/src/api/preflight.ts +399 -0
- package/src/extension/index.ts +16 -7
- package/src/extension/rpc.ts +29 -2
- package/src/extension/schemas.ts +10 -4
- package/src/extension/tool-description.ts +4 -2
- package/src/intercom/intercom-bridge.ts +5 -2
- package/src/runs/background/async-execution.ts +125 -14
- package/src/runs/background/async-job-tracker.ts +19 -12
- package/src/runs/background/async-resume.ts +27 -9
- package/src/runs/background/async-status.ts +18 -0
- package/src/runs/background/notify.ts +3 -0
- package/src/runs/background/process-terminal.ts +280 -0
- package/src/runs/background/result-watcher.ts +9 -3
- package/src/runs/background/run-status.ts +7 -1
- package/src/runs/background/scheduled-runs.ts +6 -1
- package/src/runs/background/stale-run-reconciler.ts +6 -0
- package/src/runs/background/subagent-runner.ts +182 -12
- package/src/runs/foreground/chain-execution.ts +5 -0
- package/src/runs/foreground/execution.ts +59 -13
- package/src/runs/foreground/subagent-executor.ts +142 -47
- package/src/runs/shared/acceptance.ts +41 -30
- package/src/runs/shared/capability-ceiling.ts +177 -0
- package/src/runs/shared/dynamic-fanout.ts +1 -1
- package/src/runs/shared/mcp-direct-tool-allowlist.ts +56 -17
- package/src/runs/shared/model-fallback.ts +8 -0
- package/src/runs/shared/nested-events.ts +8 -1
- package/src/runs/shared/parallel-utils.ts +5 -0
- package/src/runs/shared/pi-args.ts +141 -58
- package/src/runs/shared/session-lease.ts +25 -5
- package/src/runs/shared/subagent-prompt-runtime.ts +14 -1
- package/src/runs/shared/task-intent.ts +1 -1
- package/src/runs/shared/tool-availability.ts +18 -2
- package/src/shared/launch-contract.ts +123 -0
- package/src/shared/types.ts +118 -8
- package/src/shared/utils.ts +17 -42
- package/src/slash/delegation-adapters.ts +6 -1
- package/src/slash/slash-commands.ts +1 -1
- package/src/tui/fleet-status.ts +62 -16
- package/src/tui/fleet.ts +1 -1
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
getFinalOutput,
|
|
43
43
|
findLatestSessionFile,
|
|
44
44
|
detectSubagentError,
|
|
45
|
+
hasEmptyTerminalAssistantResponse,
|
|
45
46
|
extractToolArgsPreview,
|
|
46
47
|
extractTextFromContent,
|
|
47
48
|
} from "../../shared/utils.ts";
|
|
@@ -51,7 +52,8 @@ import { evaluateCompletionMutationGuard } from "../shared/completion-guard.ts";
|
|
|
51
52
|
import { getPiSpawnCommand } from "../shared/pi-spawn.ts";
|
|
52
53
|
import { createJsonlWriter } from "../../shared/jsonl-writer.ts";
|
|
53
54
|
import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.ts";
|
|
54
|
-
import { applyThinkingSuffix, buildPiArgs, cleanupTempDir } from "../shared/pi-args.ts";
|
|
55
|
+
import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, resolvePiLaunchToolPlan } from "../shared/pi-args.ts";
|
|
56
|
+
import { decodeSubagentCapabilityCeiling, resolveCurrentSubagentCapabilityCeiling, SUBAGENT_CAPABILITY_CEILING_ENV } from "../shared/capability-ceiling.ts";
|
|
55
57
|
import { resolveEffectiveThinking } from "../../shared/model-info.ts";
|
|
56
58
|
import { MISSING_STRUCTURED_OUTPUT_CALL_ERROR, readStructuredOutput } from "../shared/structured-output.ts";
|
|
57
59
|
import { readChildToolDiagnosticError } from "../shared/tool-availability.ts";
|
|
@@ -77,6 +79,7 @@ import { attachContractProjections, isAgentContractV1 } from "../shared/agent-co
|
|
|
77
79
|
import { appendTurnBudgetSystemPrompt, formatTurnBudgetOutput, initialTurnBudgetState, turnBudgetDecision, turnBudgetDeferredNote, turnBudgetDeferredState, turnBudgetExceededMessage, turnBudgetSoftNote, turnBudgetState } from "../shared/turn-budget.ts";
|
|
78
80
|
import { initialToolBudgetState, toolBudgetState } from "../shared/tool-budget.ts";
|
|
79
81
|
import { resolveWatchdogConfig } from "../../watchdog/settings.ts";
|
|
82
|
+
import { agentDefinitionDigest, launchBindingDigest } from "../../shared/launch-contract.ts";
|
|
80
83
|
import { createBoundedByteTail, createBoundedLineReader, formatProtocolOutputLimit, MAX_CHILD_STDERR_BYTES, projectChildLifecycle, type ChildLifecycleAction, type ProtocolOutputLimit } from "../shared/child-protocol.ts";
|
|
81
84
|
import {
|
|
82
85
|
acceptChildWatchdogEvent,
|
|
@@ -125,6 +128,7 @@ function resolveAttemptTimeout(options: RunSyncOptions): { timeoutMs: number; re
|
|
|
125
128
|
function buildPendingAcceptanceLedger(acceptance: ResolvedAcceptanceConfig): AcceptanceLedger {
|
|
126
129
|
return {
|
|
127
130
|
status: "pending",
|
|
131
|
+
evidenceStatus: "pending",
|
|
128
132
|
explicit: acceptance.explicit,
|
|
129
133
|
effectiveAcceptance: acceptance,
|
|
130
134
|
inferredReason: acceptance.inferredReason,
|
|
@@ -194,6 +198,7 @@ async function runSingleAttempt(
|
|
|
194
198
|
sessionEnabled: boolean;
|
|
195
199
|
systemPrompt: string;
|
|
196
200
|
resolvedSkillNames?: string[];
|
|
201
|
+
modelCandidates?: string[];
|
|
197
202
|
skillsWarning?: string;
|
|
198
203
|
jsonlPath?: string;
|
|
199
204
|
artifactPaths?: ArtifactPaths;
|
|
@@ -215,7 +220,7 @@ async function runSingleAttempt(
|
|
|
215
220
|
childIndex: options.index ?? 0,
|
|
216
221
|
})
|
|
217
222
|
: undefined;
|
|
218
|
-
const { args, env: sharedEnv, tempDir, toolDiagnosticPath } = buildPiArgs({
|
|
223
|
+
const { args, env: sharedEnv, tempDir, toolDiagnosticPath, capabilityAudit } = buildPiArgs({
|
|
219
224
|
baseArgs: ["--mode", "json", "-p"],
|
|
220
225
|
task,
|
|
221
226
|
sessionEnabled: shared.sessionEnabled,
|
|
@@ -249,12 +254,44 @@ async function runSingleAttempt(
|
|
|
249
254
|
allowZeroToolBudget: options.allowZeroToolBudget,
|
|
250
255
|
childWatchdog,
|
|
251
256
|
waitToolEnabled: options.waitToolEnabled,
|
|
257
|
+
capabilityCeiling: options.capabilityCeiling,
|
|
252
258
|
});
|
|
253
259
|
|
|
260
|
+
const effectiveSystemPrompt = appendTurnBudgetSystemPrompt(shared.systemPrompt, options.turnBudget);
|
|
261
|
+
const toolPlan = resolvePiLaunchToolPlan({
|
|
262
|
+
tools: agent.tools,
|
|
263
|
+
extensions: agent.extensions,
|
|
264
|
+
subagentOnlyExtensions: agent.subagentOnlyExtensions,
|
|
265
|
+
mcpDirectTools: agent.mcpDirectTools,
|
|
266
|
+
cwd: options.cwd ?? runtimeCwd,
|
|
267
|
+
requireReadTool: Boolean(shared.resolvedSkillNames?.length),
|
|
268
|
+
structuredOutput: Boolean(options.structuredOutput),
|
|
269
|
+
capabilityCeiling: options.capabilityCeiling,
|
|
270
|
+
inheritedCapabilityCeiling: decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]),
|
|
271
|
+
});
|
|
272
|
+
const launchContractDigest = launchBindingDigest({
|
|
273
|
+
definitionDigest: agentDefinitionDigest(agent),
|
|
274
|
+
task: shared.originalTask ?? task,
|
|
275
|
+
...(modelArg ? { model: modelArg } : {}),
|
|
276
|
+
modelCandidates: shared.modelCandidates,
|
|
277
|
+
...(resolvedThinking ? { thinking: resolvedThinking } : {}),
|
|
278
|
+
systemPrompt: effectiveSystemPrompt,
|
|
279
|
+
systemPromptMode: agent.systemPromptMode,
|
|
280
|
+
inheritProjectContext: agent.inheritProjectContext,
|
|
281
|
+
inheritSkills: agent.inheritSkills,
|
|
282
|
+
skills: shared.resolvedSkillNames ?? [],
|
|
283
|
+
tools: toolPlan.effectiveToolAllowlist,
|
|
284
|
+
extensions: toolPlan.extensionArgs,
|
|
285
|
+
mcpDirectTools: toolPlan.effectiveMcpTools,
|
|
286
|
+
...(options.outputPath ? { outputPath: options.outputPath } : {}),
|
|
287
|
+
outputMode: options.outputMode ?? "inline",
|
|
288
|
+
...(options.structuredOutput ? { structuredOutputSchema: options.structuredOutput.schema } : {}),
|
|
289
|
+
});
|
|
254
290
|
const result: SingleResult = withRunContext({
|
|
255
291
|
agent: agent.name,
|
|
256
292
|
task: shared.originalTask ?? task,
|
|
257
293
|
...(options.agentContract ? { agentContract: options.agentContract } : {}),
|
|
294
|
+
launchContractDigest,
|
|
258
295
|
exitCode: 0,
|
|
259
296
|
messages: [],
|
|
260
297
|
usage: emptyUsage(),
|
|
@@ -266,6 +303,8 @@ async function runSingleAttempt(
|
|
|
266
303
|
skillsWarning: shared.skillsWarning,
|
|
267
304
|
...(options.turnBudget ? { turnBudget: initialTurnBudgetState(options.turnBudget) } : {}),
|
|
268
305
|
...(options.toolBudget ? { toolBudget: initialToolBudgetState(options.toolBudget) } : {}),
|
|
306
|
+
...(options.capabilityCeiling ? { capabilityCeiling: options.capabilityCeiling } : {}),
|
|
307
|
+
...(capabilityAudit ? { capabilityAudit } : {}),
|
|
269
308
|
}, options.context);
|
|
270
309
|
const startTime = Date.now();
|
|
271
310
|
if (options.structuredOutput) {
|
|
@@ -1041,22 +1080,21 @@ async function runSingleAttempt(
|
|
|
1041
1080
|
result.exitCode = 1;
|
|
1042
1081
|
}
|
|
1043
1082
|
if (result.exitCode === 0 && !result.error) {
|
|
1044
|
-
const
|
|
1045
|
-
|
|
1046
|
-
result.exitCode = errInfo.exitCode ?? 1;
|
|
1047
|
-
result.error = errInfo.details
|
|
1048
|
-
? `${errInfo.errorType} failed (exit ${errInfo.exitCode}): ${errInfo.details}`
|
|
1049
|
-
: `${errInfo.errorType} failed with exit code ${errInfo.exitCode}`;
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
if (result.exitCode === 0 && !result.error) {
|
|
1053
|
-
const finalText = getFinalOutput(result.messages ?? []);
|
|
1083
|
+
const messages = result.messages ?? [];
|
|
1084
|
+
const finalText = getFinalOutput(messages);
|
|
1054
1085
|
const missingStructuredOutput = options.structuredOutput
|
|
1055
1086
|
? !existsSync(options.structuredOutput.outputPath)
|
|
1056
1087
|
: false;
|
|
1057
|
-
|
|
1088
|
+
const errInfo = detectSubagentError(messages);
|
|
1089
|
+
const missingOutput = !finalText?.trim() && (!options.structuredOutput || missingStructuredOutput);
|
|
1090
|
+
if (missingOutput && (!errInfo.hasError || hasEmptyTerminalAssistantResponse(messages))) {
|
|
1058
1091
|
result.exitCode = 1;
|
|
1059
1092
|
result.error = "Subagent produced no output (possible model cold-start or empty response).";
|
|
1093
|
+
} else if (errInfo.hasError) {
|
|
1094
|
+
result.exitCode = errInfo.exitCode ?? 1;
|
|
1095
|
+
result.error = errInfo.details
|
|
1096
|
+
? `${errInfo.errorType} failed (exit ${errInfo.exitCode}): ${errInfo.details}`
|
|
1097
|
+
: `${errInfo.errorType} failed with exit code ${errInfo.exitCode}`;
|
|
1060
1098
|
}
|
|
1061
1099
|
}
|
|
1062
1100
|
if (options.structuredOutput && result.exitCode === 0 && !result.error) {
|
|
@@ -1194,6 +1232,10 @@ export async function runSync(
|
|
|
1194
1232
|
task: string,
|
|
1195
1233
|
options: RunSyncOptions,
|
|
1196
1234
|
): Promise<SingleResult> {
|
|
1235
|
+
options = {
|
|
1236
|
+
...options,
|
|
1237
|
+
capabilityCeiling: options.capabilityCeiling ?? resolveCurrentSubagentCapabilityCeiling(options.parentSessionId),
|
|
1238
|
+
};
|
|
1197
1239
|
const agent = agents.find((a) => a.name === agentName);
|
|
1198
1240
|
if (!agent) {
|
|
1199
1241
|
return withRunContext({
|
|
@@ -1317,8 +1359,11 @@ export async function runSync(
|
|
|
1317
1359
|
toolCount: target.progressSummary?.toolCount,
|
|
1318
1360
|
error: target.error,
|
|
1319
1361
|
agentContract: target.agentContract,
|
|
1362
|
+
launchContractDigest: target.launchContractDigest,
|
|
1320
1363
|
execution: target.execution,
|
|
1321
1364
|
acceptance: target.acceptance,
|
|
1365
|
+
capabilityCeiling: target.capabilityCeiling,
|
|
1366
|
+
capabilityAudit: target.capabilityAudit,
|
|
1322
1367
|
review: target.review,
|
|
1323
1368
|
effects: target.effects,
|
|
1324
1369
|
...(transcriptWriter ? { transcriptPath: artifactPathsResult.transcriptPath } : {}),
|
|
@@ -1383,6 +1428,7 @@ export async function runSync(
|
|
|
1383
1428
|
artifactPaths: artifactPathsResult,
|
|
1384
1429
|
transcriptWriter,
|
|
1385
1430
|
attemptNotes,
|
|
1431
|
+
modelCandidates: candidates.map((candidate) => applyThinkingSuffix(candidate, options.thinkingOverride ?? agent.thinking, options.thinkingOverride !== undefined)),
|
|
1386
1432
|
outputSnapshot,
|
|
1387
1433
|
originalTask: task,
|
|
1388
1434
|
});
|