pi-subagents 0.54.0 → 0.55.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 +35 -1
- package/agents/reviewer.md +12 -2
- package/docs/agents.md +4 -4
- package/docs/configuration.md +4 -4
- package/docs/extension-api.md +14 -4
- package/docs/models.md +24 -3
- package/docs/observability.md +14 -3
- package/docs/tool-reference.md +21 -6
- package/docs/workflows.md +7 -1
- package/package.json +1 -1
- package/prompts/council.md +9 -0
- package/prompts/parallel-review.md +5 -1
- package/prompts/review-loop.md +9 -5
- package/skills/council-mode/SKILL.md +33 -10
- package/skills/pi-subagents/references/constraints-and-recipes.md +16 -1
- package/skills/pi-subagents/references/execution-controls.md +11 -4
- package/skills/pi-subagents/references/multi-lane-orchestration.md +3 -3
- package/skills/pi-subagents/references/prompting-and-roles.md +8 -8
- package/src/agents/agent-management.ts +30 -9
- package/src/agents/agent-serializer.ts +2 -2
- package/src/agents/agents.ts +146 -41
- package/src/api/external-job-provider.ts +10 -1
- package/src/api/preflight.ts +26 -17
- package/src/api/project-panes.ts +2 -0
- package/src/extension/index.ts +20 -1
- package/src/extension/public-execution.ts +12 -9
- package/src/extension/rpc.ts +77 -3
- package/src/extension/schemas.ts +2 -1
- package/src/extension/tool-description.ts +9 -6
- package/src/inspectors/herdr/focus.ts +55 -0
- package/src/inspectors/herdr/project-panes.ts +228 -44
- package/src/integrations/herdr-status.ts +26 -4
- package/src/runs/background/async-execution.ts +103 -9
- package/src/runs/background/async-job-tracker.ts +33 -14
- package/src/runs/background/async-resume.ts +20 -2
- package/src/runs/background/async-status.ts +10 -0
- package/src/runs/background/control-channel.ts +98 -10
- package/src/runs/background/notify.ts +62 -1
- package/src/runs/background/run-status.ts +15 -1
- package/src/runs/background/subagent-runner.ts +226 -37
- package/src/runs/foreground/async-stop-action.ts +23 -2
- package/src/runs/foreground/execution.ts +81 -7
- package/src/runs/foreground/subagent-executor.ts +348 -40
- package/src/runs/foreground/workflow-detach-reconcile.ts +3 -0
- package/src/runs/shared/acceptance.ts +1 -0
- package/src/runs/shared/child-identity.ts +36 -0
- package/src/runs/shared/completion-guard.ts +50 -1
- package/src/runs/shared/external-job-bridge.ts +53 -37
- package/src/runs/shared/external-job-runner.ts +126 -23
- package/src/runs/shared/model-fallback.ts +10 -0
- package/src/runs/shared/orca-progress-tabs.ts +71 -9
- package/src/runs/shared/parallel-utils.ts +12 -0
- package/src/runs/shared/pi-args.ts +9 -12
- package/src/runs/shared/subagent-prompt-runtime.ts +3 -1
- package/src/runs/shared/tool-availability.ts +1 -3
- package/src/shared/launch-contract.ts +6 -5
- package/src/shared/thinking-ceiling.ts +52 -0
- package/src/shared/types.ts +59 -2
- package/src/tui/fleet-status.ts +66 -13
- package/src/tui/render.ts +5 -4
- package/src/workflows/scripted-workflow.ts +107 -10
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
import { buildSkillInjection, resolveSkillsWithFallback } from "../../agents/skills.ts";
|
|
56
56
|
import { buildAgentMemoryInjection } from "../../agents/agent-memory.ts";
|
|
57
57
|
import { effectiveToolTimeoutMs, formatToolTimeoutMessage, resolveToolTimeoutMs, toolTimeoutCallKey, toolTimeoutFromEnv } from "../shared/tool-timeout.ts";
|
|
58
|
-
import { evaluateCompletionMutationGuard } from "../shared/completion-guard.ts";
|
|
58
|
+
import { evaluateCompletionMutationGuard, validateImplementationToolContract } from "../shared/completion-guard.ts";
|
|
59
59
|
import { arbitrateCompletionGuardRescue } from "../shared/llm-intent-arbiter.ts";
|
|
60
60
|
import { getPiSpawnCommand } from "../shared/pi-spawn.ts";
|
|
61
61
|
import { createJsonlWriter } from "../../shared/jsonl-writer.ts";
|
|
@@ -66,12 +66,14 @@ import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, projectLaunchResolved
|
|
|
66
66
|
import { readRuntimeAcknowledgedExtensions } from "../shared/runtime-acknowledged-extensions.ts";
|
|
67
67
|
import { assertAgentAllowedByCapabilityCeiling, decodeSubagentCapabilityCeiling, intersectSubagentCapabilityCeilings, resolveCurrentSubagentCapabilityCeiling, SUBAGENT_CAPABILITY_CEILING_ENV } from "../shared/capability-ceiling.ts";
|
|
68
68
|
import { resolveEffectiveThinking } from "../../shared/model-info.ts";
|
|
69
|
+
import { assertThinkingWithinCeiling, decodeThinkingCeiling, intersectThinkingCeilings, SUBAGENT_THINKING_CEILING_ENV } from "../../shared/thinking-ceiling.ts";
|
|
69
70
|
import { MISSING_STRUCTURED_OUTPUT_CALL_ERROR, readStructuredOutput } from "../shared/structured-output.ts";
|
|
70
71
|
import { formatProcessSignalError, isUnexplainedProcessSignal } from "../shared/process-signal.ts";
|
|
71
72
|
import { readChildToolDiagnosticError } from "../shared/tool-availability.ts";
|
|
72
73
|
import { captureSingleOutputSnapshot, extractChildWrittenOutput, finalizeSingleOutput, formatSavedOutputReference, injectOutputPathSystemPrompt, resolveSingleOutput, validateFileOnlyOutputMode, type SingleOutputSnapshot } from "../shared/single-output.ts";
|
|
73
74
|
import {
|
|
74
75
|
buildModelCandidates,
|
|
76
|
+
formatSubagentModelVerificationError,
|
|
75
77
|
formatModelAttemptNote,
|
|
76
78
|
isContextOverflow,
|
|
77
79
|
isRetryableModelFailure,
|
|
@@ -310,10 +312,13 @@ async function runSingleAttempt(
|
|
|
310
312
|
taskDelivery?: SubagentTaskDelivery;
|
|
311
313
|
orcaProgressTab?: OrcaProgressTab;
|
|
312
314
|
launchWarnings: { emitted: boolean };
|
|
315
|
+
verifyModel: boolean;
|
|
313
316
|
},
|
|
314
317
|
): Promise<SingleResult> {
|
|
315
318
|
const effectiveThinking = options.thinkingOverride ?? agent.thinking;
|
|
316
319
|
const modelArg = applyThinkingSuffix(model, effectiveThinking, options.thinkingOverride !== undefined);
|
|
320
|
+
assertThinkingWithinCeiling({ model: modelArg, configThinking: effectiveThinking, ceiling: options.thinkingCeiling, agent: agent.name, runId: options.runId });
|
|
321
|
+
const expectedModelForVerification = shared.verifyModel ? modelArg : undefined;
|
|
317
322
|
const resolvedThinking = resolveEffectiveThinking(modelArg, effectiveThinking);
|
|
318
323
|
const watchdogConfig = resolveWatchdogConfig(options.cwd ?? runtimeCwd);
|
|
319
324
|
const childWatchdog = watchdogConfig.ok
|
|
@@ -370,6 +375,7 @@ async function runSingleAttempt(
|
|
|
370
375
|
childWatchdog,
|
|
371
376
|
waitToolEnabled: options.waitToolEnabled,
|
|
372
377
|
capabilityCeiling: options.capabilityCeiling,
|
|
378
|
+
thinkingCeiling: options.thinkingCeiling,
|
|
373
379
|
});
|
|
374
380
|
if (!shared.launchWarnings.emitted && warnings.length > 0) {
|
|
375
381
|
for (const warning of warnings) console.warn(`[pi-subagents] ${warning}`);
|
|
@@ -390,6 +396,36 @@ async function runSingleAttempt(
|
|
|
390
396
|
agentName: agent.name,
|
|
391
397
|
permissionRules,
|
|
392
398
|
});
|
|
399
|
+
const contractTools = toolPlan.explicitToolAllowlist ? toolPlan.effectiveToolAllowlist : undefined;
|
|
400
|
+
const contractError = validateImplementationToolContract({
|
|
401
|
+
agent: agent.name,
|
|
402
|
+
task: shared.originalTask ?? task,
|
|
403
|
+
tools: contractTools,
|
|
404
|
+
mcpDirectTools: toolPlan.effectiveMcpTools,
|
|
405
|
+
configuredExtensions: toolPlan.configuredExtensions,
|
|
406
|
+
requestedTools: toolPlan.requestedBuiltinTools,
|
|
407
|
+
acceptanceRole: agent.acceptanceRole,
|
|
408
|
+
completionGuard: agent.completionGuard,
|
|
409
|
+
});
|
|
410
|
+
if (contractError) {
|
|
411
|
+
cleanupTempDir(tempDir);
|
|
412
|
+
return {
|
|
413
|
+
index: options.index ?? 0,
|
|
414
|
+
agent: agent.name,
|
|
415
|
+
task,
|
|
416
|
+
messages: [],
|
|
417
|
+
finalOutput: "",
|
|
418
|
+
exitCode: 1,
|
|
419
|
+
error: contractError,
|
|
420
|
+
usage: emptyUsage(),
|
|
421
|
+
model: modelArg,
|
|
422
|
+
modelAttempts: [],
|
|
423
|
+
attemptedModels: [],
|
|
424
|
+
progressSummary: { status: "failed", toolCount: 0, tokens: 0, durationMs: 0 },
|
|
425
|
+
...(toolPlan.capabilityCeiling ? { capabilityCeiling: toolPlan.capabilityCeiling } : {}),
|
|
426
|
+
...(toolPlan.capabilityAudit ? { capabilityAudit: toolPlan.capabilityAudit } : {}),
|
|
427
|
+
};
|
|
428
|
+
}
|
|
393
429
|
const launchResolvedExtensions = projectLaunchResolvedChildExtensions(toolPlan);
|
|
394
430
|
const launchContractDigest = launchBindingDigest({
|
|
395
431
|
definitionDigest: agentDefinitionDigest(agent),
|
|
@@ -397,6 +433,7 @@ async function runSingleAttempt(
|
|
|
397
433
|
...(modelArg ? { model: modelArg } : {}),
|
|
398
434
|
modelCandidates: shared.modelCandidates,
|
|
399
435
|
...(resolvedThinking ? { thinking: resolvedThinking } : {}),
|
|
436
|
+
...(options.thinkingCeiling ? { thinkingCeiling: options.thinkingCeiling } : {}),
|
|
400
437
|
systemPrompt: effectiveSystemPrompt,
|
|
401
438
|
systemPromptMode: agent.systemPromptMode,
|
|
402
439
|
inheritProjectContext: agent.inheritProjectContext,
|
|
@@ -490,6 +527,7 @@ async function runSingleAttempt(
|
|
|
490
527
|
let observedMutationAttempt = false;
|
|
491
528
|
let structuredOutputToolInvoked = false;
|
|
492
529
|
let structuredOutputMessageStartIndex: number | undefined;
|
|
530
|
+
let toolAvailabilityError: string | undefined;
|
|
493
531
|
|
|
494
532
|
const exitCode = await new Promise<number>((resolve) => {
|
|
495
533
|
const spawnSpec = getPiSpawnCommand(args);
|
|
@@ -1042,6 +1080,10 @@ async function runSingleAttempt(
|
|
|
1042
1080
|
if (evt.message.model) {
|
|
1043
1081
|
progress.model = evt.message.model;
|
|
1044
1082
|
if (!result.model) result.model = evt.message.model;
|
|
1083
|
+
if (expectedModelForVerification && !hasToolCall) {
|
|
1084
|
+
const modelVerificationError = formatSubagentModelVerificationError(expectedModelForVerification, evt.message.model, options.availableModels);
|
|
1085
|
+
if (modelVerificationError && !result.error) result.error = modelVerificationError;
|
|
1086
|
+
}
|
|
1045
1087
|
}
|
|
1046
1088
|
if (evt.message.errorMessage) assistantError = evt.message.errorMessage;
|
|
1047
1089
|
const assistantText = extractTextFromContent(evt.message.content);
|
|
@@ -1267,6 +1309,7 @@ async function runSingleAttempt(
|
|
|
1267
1309
|
// JSONL artifact flush is best effort.
|
|
1268
1310
|
});
|
|
1269
1311
|
const toolDiagnosticError = readChildToolDiagnosticError(toolDiagnosticPath);
|
|
1312
|
+
toolAvailabilityError = toolDiagnosticError;
|
|
1270
1313
|
result.runtimeAcknowledgedExtensions = readRuntimeAcknowledgedExtensions(runtimeAcknowledgedExtensionsPath);
|
|
1271
1314
|
cleanupTempDir(tempDir);
|
|
1272
1315
|
stdoutReader.end();
|
|
@@ -1462,16 +1505,18 @@ async function runSingleAttempt(
|
|
|
1462
1505
|
fullOutput = fullOutput.trim() ? `${note}\n\n${fullOutput}` : note;
|
|
1463
1506
|
}
|
|
1464
1507
|
const completionGuardEnabled = isAgentContractV1(options.agentContract) ? agent.completionGuard === true : agent.completionGuard !== false;
|
|
1465
|
-
const completionGuard = result.exitCode === 0 && !result.error && completionGuardEnabled
|
|
1508
|
+
const completionGuard = ((result.exitCode === 0 && !result.error) || toolAvailabilityError) && completionGuardEnabled
|
|
1466
1509
|
? evaluateCompletionMutationGuard({
|
|
1467
1510
|
agent: agent.name,
|
|
1468
1511
|
task: shared.originalTask ?? task,
|
|
1469
1512
|
messages: result.messages ?? [],
|
|
1470
|
-
tools:
|
|
1471
|
-
mcpDirectTools:
|
|
1513
|
+
tools: contractTools,
|
|
1514
|
+
mcpDirectTools: toolPlan.effectiveMcpTools,
|
|
1515
|
+
toolAvailabilityError,
|
|
1472
1516
|
})
|
|
1473
1517
|
: undefined;
|
|
1474
1518
|
let completionGuardTriggered = completionGuard?.triggered === true && !observedMutationAttempt;
|
|
1519
|
+
const completionGuardBlocked = completionGuard?.blocked === true;
|
|
1475
1520
|
// The classifier is deliberately narrow, so a read-only review task can
|
|
1476
1521
|
// still be misread as implementation. Arbitrate BEFORE any failure side
|
|
1477
1522
|
// effect is published (effects, exit code, progress, notifications,
|
|
@@ -1492,7 +1537,9 @@ async function runSingleAttempt(
|
|
|
1492
1537
|
result.effects = {
|
|
1493
1538
|
...(result.effects ?? {}),
|
|
1494
1539
|
fileMutation: {
|
|
1495
|
-
status:
|
|
1540
|
+
status: completionGuardBlocked
|
|
1541
|
+
? "blocked"
|
|
1542
|
+
: completionGuard.expectedMutation
|
|
1496
1543
|
? completionGuardTriggered
|
|
1497
1544
|
? "missing"
|
|
1498
1545
|
: arbiterRescued
|
|
@@ -1500,7 +1547,8 @@ async function runSingleAttempt(
|
|
|
1500
1547
|
: "observed"
|
|
1501
1548
|
: "not-applicable",
|
|
1502
1549
|
expected: completionGuard.expectedMutation,
|
|
1503
|
-
attempted: completionGuard.attemptedMutation || observedMutationAttempt,
|
|
1550
|
+
attempted: completionGuardBlocked ? false : completionGuard.attemptedMutation || observedMutationAttempt,
|
|
1551
|
+
...(completionGuardBlocked && completionGuard.message ? { message: completionGuard.message } : {}),
|
|
1504
1552
|
...(completionGuardTriggered ? { message: "Subagent completed without making edits for an implementation task." } : {}),
|
|
1505
1553
|
...(arbiterRescued ? { resolvedBy: "llm-intent-arbiter" } : {}),
|
|
1506
1554
|
},
|
|
@@ -1582,6 +1630,14 @@ async function runSyncCompletionInner(
|
|
|
1582
1630
|
error: `Unknown agent: ${agentName}`,
|
|
1583
1631
|
}, options.context));
|
|
1584
1632
|
}
|
|
1633
|
+
options = {
|
|
1634
|
+
...options,
|
|
1635
|
+
thinkingCeiling: intersectThinkingCeilings(
|
|
1636
|
+
options.thinkingCeiling,
|
|
1637
|
+
agent.maxThinking,
|
|
1638
|
+
decodeThinkingCeiling(process.env[SUBAGENT_THINKING_CEILING_ENV]),
|
|
1639
|
+
),
|
|
1640
|
+
};
|
|
1585
1641
|
try {
|
|
1586
1642
|
assertAgentAllowedByCapabilityCeiling(agent.name, options.capabilityCeiling);
|
|
1587
1643
|
} catch (error) {
|
|
@@ -1695,9 +1751,25 @@ async function runSyncCompletionInner(
|
|
|
1695
1751
|
options.modelOverride ?? agent.model,
|
|
1696
1752
|
agent.fallbackModels,
|
|
1697
1753
|
options.availableModels,
|
|
1698
|
-
options.preferredModelProvider,
|
|
1754
|
+
agent.modelProvider ?? options.preferredModelProvider,
|
|
1699
1755
|
{ scope: options.modelScope, primaryModelFromParent: options.modelOverrideFromParent },
|
|
1700
1756
|
);
|
|
1757
|
+
try {
|
|
1758
|
+
for (const candidate of candidates) {
|
|
1759
|
+
const model = applyThinkingSuffix(candidate, options.thinkingOverride ?? agent.thinking, options.thinkingOverride !== undefined);
|
|
1760
|
+
assertThinkingWithinCeiling({ model, configThinking: options.thinkingOverride ?? agent.thinking, ceiling: options.thinkingCeiling, agent: agent.name, runId: options.runId });
|
|
1761
|
+
}
|
|
1762
|
+
} catch (error) {
|
|
1763
|
+
return redactResultPrompt(withRunContext({
|
|
1764
|
+
index: options.index ?? 0,
|
|
1765
|
+
agent: agent.name,
|
|
1766
|
+
task,
|
|
1767
|
+
exitCode: 1,
|
|
1768
|
+
messages: [],
|
|
1769
|
+
usage: emptyUsage(),
|
|
1770
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1771
|
+
}, options.context));
|
|
1772
|
+
}
|
|
1701
1773
|
const attemptedModels: string[] = [];
|
|
1702
1774
|
const modelAttempts: ModelAttempt[] = [];
|
|
1703
1775
|
const aggregateUsage = emptyUsage();
|
|
@@ -1777,6 +1849,7 @@ async function runSyncCompletionInner(
|
|
|
1777
1849
|
modelAttemptsLoop: for (let modelIndex = 0; modelIndex < modelsToTry.length; modelIndex++) {
|
|
1778
1850
|
const candidate = modelsToTry[modelIndex];
|
|
1779
1851
|
for (let startupAttemptIndex = 0; ; startupAttemptIndex++) {
|
|
1852
|
+
const verifyModel = Boolean(candidate) && !(options.modelOverrideFromParent && modelIndex === 0);
|
|
1780
1853
|
const outputSnapshot = captureSingleOutputSnapshot(options.outputPath);
|
|
1781
1854
|
const result = await runSingleAttempt(runtimeCwd, agent, taskWithAcceptance, candidate, attemptOptions, {
|
|
1782
1855
|
sessionEnabled,
|
|
@@ -1795,6 +1868,7 @@ async function runSyncCompletionInner(
|
|
|
1795
1868
|
taskDelivery: taskDeliveryOverride,
|
|
1796
1869
|
orcaProgressTab,
|
|
1797
1870
|
launchWarnings,
|
|
1871
|
+
verifyModel,
|
|
1798
1872
|
});
|
|
1799
1873
|
lastResult = result;
|
|
1800
1874
|
if (startupAttemptIndex === 0) {
|