pi-subagents 0.56.0 → 0.58.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 +92 -0
- package/agents/claude-code-writer.md +15 -0
- package/agents/claude-code.md +15 -0
- package/agents/codex-exec-writer.md +15 -0
- package/agents/codex-exec.md +15 -0
- package/agents/cursor-agent-writer.md +14 -0
- package/agents/cursor-agent.md +14 -0
- package/docs/agents.md +124 -21
- package/docs/configuration.md +37 -0
- package/docs/extension-api.md +41 -2
- package/docs/models.md +3 -3
- package/docs/observability.md +8 -7
- package/docs/tool-reference.md +14 -3
- package/docs/workflows.md +44 -0
- package/package.json +1 -1
- package/skills/pi-subagents/SKILL.md +2 -0
- package/skills/pi-subagents/references/execution-controls.md +2 -2
- package/skills/pi-subagents/references/management-authoring-rpc.md +1 -0
- package/skills/pi-subagents/references/prompting-and-roles.md +2 -2
- package/src/agents/agent-management.ts +36 -5
- package/src/agents/agent-refinements.ts +4 -4
- package/src/agents/agent-serializer.ts +5 -0
- package/src/agents/agents.ts +257 -51
- package/src/agents/builtin-names.ts +6 -0
- package/src/agents/runtime-agent-events.ts +70 -0
- package/src/agents/runtime-agent-registry.ts +18 -4
- package/src/api/agents.ts +10 -5
- package/src/api/preflight.ts +28 -3
- package/src/extension/config.ts +70 -0
- package/src/extension/doctor.ts +3 -3
- package/src/extension/index.ts +33 -8
- package/src/extension/public-execution.ts +29 -13
- package/src/extension/rpc.ts +55 -19
- package/src/extension/schemas.ts +6 -5
- package/src/extension/tool-description.ts +18 -12
- package/src/inspectors/herdr/actions.ts +2 -1
- package/src/inspectors/herdr/inspector-runner.ts +2 -10
- package/src/inspectors/herdr/session-roots-codec.ts +42 -0
- package/src/integrations/herdr-status.ts +51 -3
- package/src/runs/background/active-async-capacity.ts +77 -10
- package/src/runs/background/async-execution.ts +127 -19
- package/src/runs/background/async-job-tracker.ts +5 -0
- package/src/runs/background/async-resume.ts +6 -2
- package/src/runs/background/async-retention.ts +20 -3
- package/src/runs/background/async-status.ts +7 -0
- package/src/runs/background/chain-append.ts +2 -0
- package/src/runs/background/chain-root-attachment.ts +15 -1
- package/src/runs/background/fleet-view.ts +16 -10
- package/src/runs/background/inspect-rpc.ts +8 -8
- package/src/runs/background/notify.ts +26 -3
- package/src/runs/background/result-delivery-ownership.ts +45 -0
- package/src/runs/background/result-files.ts +27 -14
- package/src/runs/background/result-watcher.ts +36 -15
- package/src/runs/background/run-status.ts +33 -6
- package/src/runs/background/scheduled-runs.ts +7 -1
- package/src/runs/background/subagent-runner.ts +239 -56
- package/src/runs/background/wait-completions.ts +4 -0
- package/src/runs/foreground/execution.ts +92 -11
- package/src/runs/foreground/foreground-control.ts +6 -0
- package/src/runs/foreground/foreground-history.ts +22 -1
- package/src/runs/foreground/subagent-executor.ts +322 -102
- package/src/runs/foreground/workflow-detach-reconcile.ts +144 -18
- package/src/runs/shared/child-protocol.ts +21 -7
- package/src/runs/shared/claude-code-adapter.ts +129 -0
- package/src/runs/shared/codex-exec-adapter.ts +129 -0
- package/src/runs/shared/completion-guard.ts +4 -3
- package/src/runs/shared/cursor-agent-adapter.ts +114 -0
- package/src/runs/shared/dynamic-fanout.ts +3 -3
- package/src/runs/shared/external-cli-contract.ts +167 -0
- package/src/runs/shared/external-cli-preflight.ts +122 -0
- package/src/runs/shared/external-cli-runner.ts +348 -55
- package/src/runs/shared/fast-mode-extension.ts +5 -5
- 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 +386 -0
- package/src/runs/shared/mcp-direct-tool-allowlist.ts +155 -42
- package/src/runs/shared/model-exclusions.ts +69 -7
- package/src/runs/shared/model-fallback.ts +39 -5
- package/src/runs/shared/mutation-evidence.ts +7 -2
- package/src/runs/shared/nested-events.ts +3 -1
- package/src/runs/shared/nested-render.ts +2 -2
- package/src/runs/shared/parallel-utils.ts +8 -1
- package/src/runs/shared/pi-args.ts +61 -6
- package/src/runs/shared/process-signal.ts +13 -0
- package/src/runs/shared/run-history.ts +21 -1
- package/src/runs/shared/single-output.ts +17 -0
- package/src/runs/shared/subagent-prompt-runtime.ts +85 -9
- package/src/shared/fork-context.ts +21 -0
- package/src/shared/formatters.ts +13 -1
- package/src/shared/launch-contract.ts +4 -0
- package/src/shared/pruned-fork.ts +450 -0
- package/src/shared/session-file-trust.ts +19 -0
- package/src/shared/session-tokens.ts +14 -3
- package/src/shared/settings.ts +10 -2
- package/src/shared/shortcuts.ts +17 -0
- package/src/shared/types.ts +160 -10
- package/src/shared/utils.ts +6 -29
- package/src/shared/workflow-child-permit.ts +116 -0
- package/src/slash/delegation-adapters.ts +0 -1
- package/src/slash/slash-commands.ts +8 -6
- package/src/slash/subagents-admin.ts +3 -0
- package/src/tui/fleet-status.ts +27 -10
- package/src/tui/fleet-transcript.ts +11 -5
- package/src/tui/fleet.ts +28 -13
- package/src/tui/render.ts +55 -21
- package/src/workflows/scripted-workflow.ts +299 -31
- package/src/workflows/workflow-child-summary.ts +117 -0
- package/src/workflows/workflow-receipt.ts +155 -5
package/src/shared/types.ts
CHANGED
|
@@ -14,6 +14,7 @@ import type { AuthorityPolicyConfig } from "../policy/authority.ts";
|
|
|
14
14
|
import type { ThinkingLevel } from "./model-info.ts";
|
|
15
15
|
import type { GlobalMissionIndexRecord, MissionRecord, MissionStoreConfig } from "../missions/types.ts";
|
|
16
16
|
import type { ExtensionBindings } from "../runs/shared/extension-bindings.ts";
|
|
17
|
+
import type { WorkflowChildPermitContext } from "./workflow-child-permit.ts";
|
|
17
18
|
|
|
18
19
|
// ============================================================================
|
|
19
20
|
// Basic Types
|
|
@@ -75,16 +76,48 @@ export interface WorkflowGraphSnapshot {
|
|
|
75
76
|
|
|
76
77
|
export type WorkflowReceiptState = "complete" | "failed" | "paused" | "stopped";
|
|
77
78
|
|
|
79
|
+
export type WorkflowTerminalResolution = "settled-awaiting-resume" | "failed-child" | "interrupted-child";
|
|
80
|
+
|
|
81
|
+
export interface WorkflowTerminalOutcome {
|
|
82
|
+
state: "partial";
|
|
83
|
+
reason: "budget_exhausted" | "timeout";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface WorkflowRecoveryAction {
|
|
87
|
+
key: string;
|
|
88
|
+
call: "runs.run";
|
|
89
|
+
resume: { workflowRunId: string; key: string; latest: true };
|
|
90
|
+
taskRequired: true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface WorkflowChildSummaryV1 {
|
|
94
|
+
version: 1;
|
|
95
|
+
parentToolCallId: string;
|
|
96
|
+
workflowRunId: string;
|
|
97
|
+
inventoryComplete: boolean;
|
|
98
|
+
workflowState: "queued" | "running" | "completed" | "failed" | "paused" | "stopped";
|
|
99
|
+
children: Array<{
|
|
100
|
+
childId: string;
|
|
101
|
+
runId?: string;
|
|
102
|
+
agent?: string;
|
|
103
|
+
model?: string;
|
|
104
|
+
thinking?: string;
|
|
105
|
+
state: "pending" | "running" | "completed" | "failed" | "paused" | "stopped" | "rejected" | "detached";
|
|
106
|
+
}>;
|
|
107
|
+
}
|
|
108
|
+
|
|
78
109
|
type WorkflowReceiptEntryResumability =
|
|
79
110
|
| { latestRunId: string; resumability: { state: "resumable" } }
|
|
80
111
|
| { latestRunId?: string; resumability: { state: "not-resumable"; reason: string } };
|
|
81
112
|
|
|
82
113
|
export type WorkflowReceiptEntry = WorkflowReceiptEntryResumability & {
|
|
83
114
|
key: string;
|
|
115
|
+
terminalOutcome?: WorkflowTerminalOutcome;
|
|
84
116
|
agent?: string;
|
|
85
117
|
requestedContext?: "fresh" | "fork";
|
|
86
118
|
resolvedContext?: "fresh" | "fork" | "mixed";
|
|
87
119
|
outputReference?: string;
|
|
120
|
+
externalAdapter?: ExternalCliReceiptMetadata;
|
|
88
121
|
continuation: { runIds: string[] };
|
|
89
122
|
};
|
|
90
123
|
|
|
@@ -94,6 +127,10 @@ export interface WorkflowReceipt {
|
|
|
94
127
|
state: WorkflowReceiptState;
|
|
95
128
|
createdAt: number;
|
|
96
129
|
entries: Record<string, WorkflowReceiptEntry>;
|
|
130
|
+
workflowChildren?: WorkflowChildSummaryV1;
|
|
131
|
+
workflowResolution?: WorkflowTerminalResolution;
|
|
132
|
+
terminalOutcome?: WorkflowTerminalOutcome;
|
|
133
|
+
recovery?: WorkflowRecoveryAction[];
|
|
97
134
|
}
|
|
98
135
|
|
|
99
136
|
export interface SavedOutputReference {
|
|
@@ -166,6 +203,10 @@ export interface TokenUsage {
|
|
|
166
203
|
input: number;
|
|
167
204
|
output: number;
|
|
168
205
|
total: number;
|
|
206
|
+
/** Input plus cache-read tokens for the latest assistant turn. */
|
|
207
|
+
window?: number;
|
|
208
|
+
/** Largest window observed in this usage scope. */
|
|
209
|
+
windowPeak?: number;
|
|
169
210
|
}
|
|
170
211
|
|
|
171
212
|
export type ActivityState = "active_long_running" | "needs_attention";
|
|
@@ -352,8 +393,24 @@ export interface FileMutationEffect {
|
|
|
352
393
|
evidence?: TrackedMutationEvidence;
|
|
353
394
|
}
|
|
354
395
|
|
|
396
|
+
export interface SettlementDiagnostic {
|
|
397
|
+
finalTextPresent: boolean;
|
|
398
|
+
mutation: {
|
|
399
|
+
expected: boolean;
|
|
400
|
+
attempted: boolean;
|
|
401
|
+
observed: boolean;
|
|
402
|
+
};
|
|
403
|
+
requiredOutput?: {
|
|
404
|
+
kind: "file-only" | "structured";
|
|
405
|
+
path: string;
|
|
406
|
+
missing: boolean;
|
|
407
|
+
};
|
|
408
|
+
afterCompactionSettlement?: boolean;
|
|
409
|
+
}
|
|
410
|
+
|
|
355
411
|
export interface EffectsProjection {
|
|
356
412
|
fileMutation?: FileMutationEffect;
|
|
413
|
+
settlementDiagnostic?: SettlementDiagnostic;
|
|
357
414
|
}
|
|
358
415
|
|
|
359
416
|
export interface TrackedMutationSnapshot {
|
|
@@ -582,9 +639,11 @@ export interface SteeringRecoveryDescriptor {
|
|
|
582
639
|
extensions?: string[];
|
|
583
640
|
subagentOnlyExtensions?: string[];
|
|
584
641
|
mcpDirectTools?: string[];
|
|
642
|
+
mutationTools?: string[];
|
|
585
643
|
systemPrompt?: string;
|
|
586
644
|
systemPromptMode: "append" | "replace";
|
|
587
645
|
inheritProjectContext: boolean;
|
|
646
|
+
inheritGlobalContext: boolean;
|
|
588
647
|
inheritSkills: boolean;
|
|
589
648
|
skills?: string[];
|
|
590
649
|
skillPath?: string[];
|
|
@@ -703,6 +762,8 @@ export interface AgentProgress {
|
|
|
703
762
|
thinking?: string;
|
|
704
763
|
inputTokens?: number;
|
|
705
764
|
outputTokens?: number;
|
|
765
|
+
window?: number;
|
|
766
|
+
windowPeak?: number;
|
|
706
767
|
durationMs: number;
|
|
707
768
|
error?: string;
|
|
708
769
|
failedTool?: string;
|
|
@@ -1044,6 +1105,8 @@ export interface SingleResult {
|
|
|
1044
1105
|
watchdog?: ChildWatchdogProgress;
|
|
1045
1106
|
capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
|
|
1046
1107
|
capabilityAudit?: SubagentCapabilityAudit;
|
|
1108
|
+
runner?: ExternalCliRunnerStatus | ExternalJobRunnerStatus;
|
|
1109
|
+
externalProcess?: ExternalProcessStatus;
|
|
1047
1110
|
}
|
|
1048
1111
|
|
|
1049
1112
|
export interface SpawnBudgetGrant {
|
|
@@ -1090,6 +1153,7 @@ export interface WaitCompletion {
|
|
|
1090
1153
|
/** Versioned bounded output archive retained with the durable completion replay. */
|
|
1091
1154
|
archivePath?: string;
|
|
1092
1155
|
results?: WaitCompletionChild[];
|
|
1156
|
+
workflowChildren?: WorkflowChildSummaryV1;
|
|
1093
1157
|
}
|
|
1094
1158
|
|
|
1095
1159
|
export interface Details {
|
|
@@ -1100,6 +1164,7 @@ export interface Details {
|
|
|
1100
1164
|
/** Run-level context summary. "mixed" when children resolved to different modes. */
|
|
1101
1165
|
context?: "fresh" | "fork" | "mixed";
|
|
1102
1166
|
results: SingleResult[];
|
|
1167
|
+
workflowChildren?: WorkflowChildSummaryV1;
|
|
1103
1168
|
/**
|
|
1104
1169
|
* Terminal completion payloads for runs this subagent_wait call observed
|
|
1105
1170
|
* finishing. Async completions travel as result files that are consumed and
|
|
@@ -1375,9 +1440,11 @@ export type AgentRunnerConfig =
|
|
|
1375
1440
|
| { type: "pi" }
|
|
1376
1441
|
| {
|
|
1377
1442
|
type: "external-cli";
|
|
1443
|
+
adapter?: "codex-exec" | "codex-exec-writer" | "claude-code" | "claude-code-writer" | "cursor-agent" | "cursor-agent-writer";
|
|
1378
1444
|
command: string;
|
|
1379
1445
|
args?: string[];
|
|
1380
1446
|
promptDelivery?: "stdin";
|
|
1447
|
+
capabilities?: ExternalCliCapabilityNarrowing;
|
|
1381
1448
|
}
|
|
1382
1449
|
| {
|
|
1383
1450
|
type: "external-job";
|
|
@@ -1385,18 +1452,46 @@ export type AgentRunnerConfig =
|
|
|
1385
1452
|
options?: Record<string, unknown>;
|
|
1386
1453
|
};
|
|
1387
1454
|
|
|
1455
|
+
export type ExternalCliCapabilityNarrowing = Partial<Record<"steer" | "resume" | "structuredOutput" | "toolEvents" | "supervisor" | "forkContext" | "extensionBindings", false>>;
|
|
1456
|
+
|
|
1457
|
+
export interface ExternalCliCapabilities {
|
|
1458
|
+
stop: true;
|
|
1459
|
+
steer: false;
|
|
1460
|
+
resume: false;
|
|
1461
|
+
structuredOutput: false;
|
|
1462
|
+
toolEvents: false;
|
|
1463
|
+
supervisor: "unsupported";
|
|
1464
|
+
forkContext: false;
|
|
1465
|
+
extensionBindings: false;
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
export interface ExternalCliReceiptMetadata {
|
|
1469
|
+
adapter: { id: "external-cli" | "codex-exec" | "codex-exec-writer" | "claude-code" | "claude-code-writer" | "cursor-agent" | "cursor-agent-writer" | "grok-build"; version: 1; executionMode: "one-shot-stdin" | "one-shot-prompt-file" };
|
|
1470
|
+
capabilities: ExternalCliCapabilities;
|
|
1471
|
+
safety?:
|
|
1472
|
+
| { sandbox: "read-only"; approvalPolicy: "never"; ephemeral: true }
|
|
1473
|
+
| { access: "workspace-write"; sandbox: "workspace-write"; approvalPolicy: "never"; ephemeral: true }
|
|
1474
|
+
| { permissionMode: "plan"; tools: "none"; mcp: "empty-strict"; settingSources: "none"; sessionPersistence: false }
|
|
1475
|
+
| { access: "read-only"; authentication: "existing-cli-required"; permissionMode: "plan"; tools: "none"; mcp: "empty-strict"; settingSources: "user"; userSettingsTrust: "required"; sessionPersistence: false }
|
|
1476
|
+
| { access: "workspace-write"; authentication: "existing-cli-required"; permissionMode: "acceptEdits"; tools: "Read,Write,Edit,Glob,Grep"; mcp: "empty-strict"; settingSources: "user"; userSettingsTrust: "required"; sessionPersistence: false }
|
|
1477
|
+
| { access: "read-only"; authentication: "cursor-api-key-or-existing-login"; mode: "ask"; sandbox: "enabled"; workspaceTrust: "existing-required"; sessionReuse: false }
|
|
1478
|
+
| { access: "workspace-write"; authentication: "cursor-api-key-or-existing-login"; mode: "print"; sandbox: "enabled"; workspaceTrust: "existing-required"; sessionReuse: false };
|
|
1479
|
+
outputArtifacts?: { stdoutPath?: string; stderrPath?: string; finalOutputPath?: string };
|
|
1480
|
+
handoff: { mode: "fresh" };
|
|
1481
|
+
supervisor: { mode: "unsupported"; reason: string };
|
|
1482
|
+
nonResumableReason: string;
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1388
1485
|
export interface ExternalCliRunnerStatus {
|
|
1389
1486
|
type: "external-cli";
|
|
1390
1487
|
command: string;
|
|
1391
1488
|
args: string[];
|
|
1392
|
-
promptDelivery: "stdin";
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
toolEvents: false;
|
|
1399
|
-
};
|
|
1489
|
+
promptDelivery: "stdin" | "prompt-file";
|
|
1490
|
+
adapter: ExternalCliReceiptMetadata["adapter"];
|
|
1491
|
+
safety?: ExternalCliReceiptMetadata["safety"];
|
|
1492
|
+
capabilities: ExternalCliCapabilities;
|
|
1493
|
+
unsupportedReasons: Record<Exclude<keyof ExternalCliCapabilities, "stop">, string>;
|
|
1494
|
+
nonResumableReason: string;
|
|
1400
1495
|
}
|
|
1401
1496
|
|
|
1402
1497
|
export interface ExternalJobRunnerStatus {
|
|
@@ -1443,6 +1538,11 @@ export interface ExternalProcessStatus {
|
|
|
1443
1538
|
processSignal?: string | null;
|
|
1444
1539
|
stdoutPath: string;
|
|
1445
1540
|
stderrPath: string;
|
|
1541
|
+
finalOutputPath?: string;
|
|
1542
|
+
stdoutBytes?: number;
|
|
1543
|
+
stderrBytes?: number;
|
|
1544
|
+
stdoutTruncated?: boolean;
|
|
1545
|
+
stderrTruncated?: boolean;
|
|
1446
1546
|
}
|
|
1447
1547
|
|
|
1448
1548
|
export interface AsyncStatus {
|
|
@@ -1499,6 +1599,7 @@ export interface AsyncStatus {
|
|
|
1499
1599
|
capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
|
|
1500
1600
|
capabilityAudit?: SubagentCapabilityAudit;
|
|
1501
1601
|
workflow?: Details["workflow"];
|
|
1602
|
+
workflowChildren?: WorkflowChildSummaryV1;
|
|
1502
1603
|
parentWorkflowRunId?: string;
|
|
1503
1604
|
workflowKey?: string;
|
|
1504
1605
|
/** Set when a durable schedule launched this run, so completions can name their origin. */
|
|
@@ -1557,6 +1658,7 @@ export interface AsyncStatus {
|
|
|
1557
1658
|
skills?: string[];
|
|
1558
1659
|
model?: string;
|
|
1559
1660
|
thinking?: string;
|
|
1661
|
+
contextLimit?: number;
|
|
1560
1662
|
thinkingCeiling?: ThinkingLevel;
|
|
1561
1663
|
attemptedModels?: string[];
|
|
1562
1664
|
modelAttempts?: ModelAttempt[];
|
|
@@ -1654,6 +1756,7 @@ export interface AsyncJobState {
|
|
|
1654
1756
|
parentWorkflowRunId?: string;
|
|
1655
1757
|
workflowKey?: string;
|
|
1656
1758
|
workflow?: Details["workflow"];
|
|
1759
|
+
workflowChildren?: WorkflowChildSummaryV1;
|
|
1657
1760
|
}
|
|
1658
1761
|
|
|
1659
1762
|
export interface ForegroundResumeChild {
|
|
@@ -1671,6 +1774,8 @@ export interface ForegroundResumeChild {
|
|
|
1671
1774
|
currentPath?: string;
|
|
1672
1775
|
turnCount?: number;
|
|
1673
1776
|
tokens?: number;
|
|
1777
|
+
window?: number;
|
|
1778
|
+
windowPeak?: number;
|
|
1674
1779
|
toolCount?: number;
|
|
1675
1780
|
exitCode?: number;
|
|
1676
1781
|
error?: string;
|
|
@@ -1685,6 +1790,14 @@ export interface ForegroundResumeChild {
|
|
|
1685
1790
|
detachedReason?: string;
|
|
1686
1791
|
acceptance?: AcceptanceLedger;
|
|
1687
1792
|
agentContract?: AgentContract;
|
|
1793
|
+
/** Private bounded launch fields needed to preserve the child contract on resume. */
|
|
1794
|
+
resumeContract?: {
|
|
1795
|
+
outputSchema?: JsonSchemaObject;
|
|
1796
|
+
agentContract?: AgentContract;
|
|
1797
|
+
acceptance?: AcceptanceInput;
|
|
1798
|
+
output?: string | boolean;
|
|
1799
|
+
outputMode?: OutputMode;
|
|
1800
|
+
};
|
|
1688
1801
|
launchContractDigest?: string;
|
|
1689
1802
|
/** Private retained launch authority. Never project into status or result output. */
|
|
1690
1803
|
extensionBindings?: ExtensionBindings;
|
|
@@ -1723,6 +1836,8 @@ export interface ForegroundChildControl {
|
|
|
1723
1836
|
tokens?: number;
|
|
1724
1837
|
inputTokens?: number;
|
|
1725
1838
|
outputTokens?: number;
|
|
1839
|
+
window?: number;
|
|
1840
|
+
windowPeak?: number;
|
|
1726
1841
|
model?: string;
|
|
1727
1842
|
thinking?: string;
|
|
1728
1843
|
toolCount?: number;
|
|
@@ -1758,6 +1873,8 @@ export interface ForegroundRunControl {
|
|
|
1758
1873
|
tokens?: number;
|
|
1759
1874
|
inputTokens?: number;
|
|
1760
1875
|
outputTokens?: number;
|
|
1876
|
+
window?: number;
|
|
1877
|
+
windowPeak?: number;
|
|
1761
1878
|
model?: string;
|
|
1762
1879
|
thinking?: string;
|
|
1763
1880
|
toolCount?: number;
|
|
@@ -1808,6 +1925,8 @@ export interface SubagentState {
|
|
|
1808
1925
|
parentSessionFile?: string | null;
|
|
1809
1926
|
/** Extension-owned roots trusted for child session transcript reads. */
|
|
1810
1927
|
trustedSessionRoots?: string[];
|
|
1928
|
+
/** Pi sessions base that caps exact runtime-recorded session file trust. */
|
|
1929
|
+
trustedSessionFileRoot?: string;
|
|
1811
1930
|
/** Live async session roots created by this parent executor, keyed by run id. */
|
|
1812
1931
|
liveAsyncSessionRoots?: Map<string, string>;
|
|
1813
1932
|
/** Last valid parent session model observed for this session; used when continuation contexts omit ctx.model. */
|
|
@@ -1932,6 +2051,8 @@ export interface SubagentChildStatusEvent {
|
|
|
1932
2051
|
// ============================================================================
|
|
1933
2052
|
|
|
1934
2053
|
export interface RunSyncOptions {
|
|
2054
|
+
/** Exact discovery provenance for an unknown-agent error; omission uses defensive fallback discovery. */
|
|
2055
|
+
unknownAgentDiagnosticContext?: import("../agents/agents.ts").UnknownAgentDiagnosticContext;
|
|
1935
2056
|
/** Opt-in global permission rules; missing tools remain allowed. */
|
|
1936
2057
|
permissions?: import("../runs/shared/permissions.ts").PermissionConfig;
|
|
1937
2058
|
/** Session id of the direct parent session for permission-system ask forwarding. */
|
|
@@ -1943,6 +2064,8 @@ export interface RunSyncOptions {
|
|
|
1943
2064
|
/** Resolved launch context for this child. */
|
|
1944
2065
|
context?: "fresh" | "fork";
|
|
1945
2066
|
cwd?: string;
|
|
2067
|
+
/** Original cwd input retained for launch diagnostics. */
|
|
2068
|
+
requestedCwd?: string;
|
|
1946
2069
|
signal?: AbortSignal;
|
|
1947
2070
|
interruptSignal?: AbortSignal;
|
|
1948
2071
|
timeoutMs?: number;
|
|
@@ -1998,10 +2121,14 @@ export interface RunSyncOptions {
|
|
|
1998
2121
|
thinkingOverride?: AgentConfig["thinking"];
|
|
1999
2122
|
thinkingCeiling?: ThinkingLevel;
|
|
2000
2123
|
extensionBindings?: ExtensionBindings;
|
|
2124
|
+
/** Package-internal one-use authorization for one foreground workflow child. */
|
|
2125
|
+
workflowChildPermitLaunch?: WorkflowChildPermitContext;
|
|
2001
2126
|
/** Registry models available for heuristic bare-model resolution */
|
|
2002
|
-
availableModels?: Array<{ provider: string; id: string; fullId: string }>;
|
|
2127
|
+
availableModels?: Array<{ provider: string; id: string; fullId: string; contextWindow?: number }>;
|
|
2003
2128
|
/** Current parent-session provider to prefer for ambiguous bare model ids */
|
|
2004
2129
|
preferredModelProvider?: string;
|
|
2130
|
+
/** Parent Pi event host used to snapshot runtime-registered MCP servers before child launch. */
|
|
2131
|
+
runtimeSnapshotHost?: import("../runs/shared/mcp-direct-tool-allowlist.ts").McpRuntimeSnapshotHost;
|
|
2005
2132
|
/** Optional subagent model-scope enforcement for fallback candidates */
|
|
2006
2133
|
modelScope?: ModelScopeRule | ModelScopeRule[];
|
|
2007
2134
|
/** Skills to make available (overrides agent default if provided) */
|
|
@@ -2063,6 +2190,11 @@ export interface ScheduledRunsConfig {
|
|
|
2063
2190
|
storeRoot?: string;
|
|
2064
2191
|
}
|
|
2065
2192
|
|
|
2193
|
+
export interface ModelExclusionsConfig {
|
|
2194
|
+
/** Default duration in milliseconds. A lower configured value also shortens active cached exclusions. */
|
|
2195
|
+
defaultTtlMs?: number;
|
|
2196
|
+
}
|
|
2197
|
+
|
|
2066
2198
|
export type FleetViewPlacement = "aboveEditor" | "belowEditor";
|
|
2067
2199
|
|
|
2068
2200
|
export const FLEET_KEYBINDING_ACTIONS = [
|
|
@@ -2097,10 +2229,24 @@ export interface MainWindowRendererConfig {
|
|
|
2097
2229
|
compactResultMaxLines?: number;
|
|
2098
2230
|
}
|
|
2099
2231
|
|
|
2232
|
+
export interface ForkContextConfig {
|
|
2233
|
+
/** Keep the complete fork by default, or summarize large text-only tool results before launch. */
|
|
2234
|
+
mode?: "full" | "pruned";
|
|
2235
|
+
/** Required pruning model when mode is "pruned". */
|
|
2236
|
+
model?: string;
|
|
2237
|
+
}
|
|
2238
|
+
|
|
2239
|
+
export interface ActiveAsyncCapacityConfig {
|
|
2240
|
+
/** Reclaim failed runner slots after this age when process proof is unknown; false keeps strict retention. */
|
|
2241
|
+
abandonedSlotReleaseAfterMs?: number | false;
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2100
2244
|
export interface ExtensionConfig {
|
|
2101
2245
|
asyncByDefault?: boolean;
|
|
2102
2246
|
/** Set the context for launches that omit an explicit context. */
|
|
2103
2247
|
defaultSubagentContext?: "fresh" | "fork";
|
|
2248
|
+
/** Configure how every resolved fork session is prepared before child spawn. */
|
|
2249
|
+
forkContext?: ForkContextConfig;
|
|
2104
2250
|
/** Optional shortcut that detaches the active foreground single-subagent run. */
|
|
2105
2251
|
foregroundDetachShortcut?: string;
|
|
2106
2252
|
/** Show the Claude Code-style navigable fleet. Defaults to true. */
|
|
@@ -2111,6 +2257,8 @@ export interface ExtensionConfig {
|
|
|
2111
2257
|
fleetKeybindings?: FleetKeybindingsConfig;
|
|
2112
2258
|
/** Show the under-editor async runs widget. Defaults to true, including when FleetView is enabled. */
|
|
2113
2259
|
asyncWidget?: boolean;
|
|
2260
|
+
/** Configure the process-wide TTL policy for persisted model exclusions. */
|
|
2261
|
+
modelExclusions?: ModelExclusionsConfig;
|
|
2114
2262
|
/** Tool description variant registered for the parent-facing subagent tool. Defaults to split metadata. */
|
|
2115
2263
|
toolDescriptionMode?: ToolDescriptionMode;
|
|
2116
2264
|
/** Inline chat rendering for the subagent tool. Defaults to rich. */
|
|
@@ -2130,6 +2278,8 @@ export interface ExtensionConfig {
|
|
|
2130
2278
|
maxSubagentSpawnsPerRun?: number;
|
|
2131
2279
|
/** Optional active top-level async run cap per parent session. Unset or 0 means unlimited. */
|
|
2132
2280
|
maxActiveAsyncRunsPerSession?: number;
|
|
2281
|
+
/** Active-capacity cleanup policy. */
|
|
2282
|
+
capacity?: ActiveAsyncCapacityConfig;
|
|
2133
2283
|
/** Global cap on simultaneously-running subagent tasks within a single run. Defaults to 20. */
|
|
2134
2284
|
globalConcurrencyLimit?: number;
|
|
2135
2285
|
/**
|
|
@@ -2285,7 +2435,7 @@ export const POLL_INTERVAL_MS = 250;
|
|
|
2285
2435
|
export const WIDGET_ANIMATION_INTERVAL_MS = 1000;
|
|
2286
2436
|
export const MAX_WIDGET_JOBS = 4;
|
|
2287
2437
|
export const DEFAULT_SUBAGENT_MAX_DEPTH = 2;
|
|
2288
|
-
export const SUBAGENT_ACTIONS = ["list", "get", "models", "children.list", "guide", "create", "update", "delete", "eject", "disable", "enable", "reset", "mission.create", "mission.list", "mission.show", "mission.update", "mission.resolve-decision", "mission.attach-run", "mission.close", "worktree.discard", "refine", "refine.show", "refine.rollback", "inspector.open", "inspector.status", "inspector.close", "project.open", "project.status", "project.close", "status", "debug.run", "grant-spawn-budget", "interrupt", "resume", "steer", "stop", "dismiss", "doctor", "watchdog.status", "watchdog.check", "watchdog.configure", "watchdog.recommend-model", "schedule.create", "schedule.list", "schedule.show", "schedule.history", "schedule.pause", "schedule.resume", "schedule.run", "schedule.run-due", "schedule.delete"] as const;
|
|
2438
|
+
export const SUBAGENT_ACTIONS = ["list", "get", "models", "children.list", "guide", "validate", "create", "update", "delete", "eject", "disable", "enable", "reset", "mission.create", "mission.list", "mission.show", "mission.update", "mission.resolve-decision", "mission.attach-run", "mission.close", "worktree.discard", "refine", "refine.show", "refine.rollback", "inspector.open", "inspector.status", "inspector.close", "project.open", "project.status", "project.close", "status", "debug.run", "grant-spawn-budget", "interrupt", "resume", "steer", "stop", "dismiss", "doctor", "watchdog.status", "watchdog.check", "watchdog.configure", "watchdog.recommend-model", "schedule.create", "schedule.list", "schedule.show", "schedule.history", "schedule.pause", "schedule.resume", "schedule.run", "schedule.run-due", "schedule.delete"] as const;
|
|
2289
2439
|
|
|
2290
2440
|
export const DEFAULT_FORK_PREAMBLE =
|
|
2291
2441
|
"You are a delegated subagent running from a fork of the parent session. " +
|
package/src/shared/utils.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* General utility functions for the subagent extension
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
1
|
import * as fs from "node:fs";
|
|
6
2
|
import * as os from "node:os";
|
|
7
3
|
import * as path from "node:path";
|
|
@@ -10,10 +6,6 @@ import { previewDisplayText, sanitizeDisplayText, truncateDisplayText } from "./
|
|
|
10
6
|
import { formatToolCall } from "./formatters.ts";
|
|
11
7
|
import type { AgentProgress, AsyncStatus, Details, DisplayItem, ErrorInfo, NestedRunSummary, SingleResult, ToolCallSummary, Usage } from "./types.ts";
|
|
12
8
|
|
|
13
|
-
// ============================================================================
|
|
14
|
-
// File System Utilities
|
|
15
|
-
// ============================================================================
|
|
16
|
-
|
|
17
9
|
const DEFAULT_CONFIG_DIR_NAME = ".pi";
|
|
18
10
|
const PI_CODING_AGENT_PACKAGE_NAME = "@earendil-works/pi-coding-agent";
|
|
19
11
|
export const PI_CODING_AGENT_PACKAGE_ROOT_ENV = "PI_SUBAGENTS_PI_CODING_AGENT_PACKAGE_ROOT";
|
|
@@ -96,9 +88,10 @@ export function getProjectConfigDir(projectRoot: string): string {
|
|
|
96
88
|
|
|
97
89
|
export function getAgentDir(): string {
|
|
98
90
|
const configured = process.env.PI_CODING_AGENT_DIR;
|
|
99
|
-
|
|
100
|
-
if (configured
|
|
101
|
-
|
|
91
|
+
const home = process.env.HOME || process.env.USERPROFILE || os.homedir();
|
|
92
|
+
if (configured === "~") return home;
|
|
93
|
+
if (configured?.startsWith("~/") || configured?.startsWith("~\\")) return path.join(home, configured.slice(2));
|
|
94
|
+
return configured || path.join(home, getConfigDirName(), "agent");
|
|
102
95
|
}
|
|
103
96
|
|
|
104
97
|
const statusCache = new Map<string, { mtime: number; ctime: number; size: number; ino: number; status: AsyncStatus }>();
|
|
@@ -253,10 +246,7 @@ function getOutputTail(outputFile: string | undefined, maxLines: number = 3): st
|
|
|
253
246
|
}
|
|
254
247
|
}
|
|
255
248
|
|
|
256
|
-
|
|
257
|
-
* Get human-readable last activity time for a file
|
|
258
|
-
*/
|
|
259
|
-
export function getLastActivity(outputFile: string | undefined): string {
|
|
249
|
+
export function getLastActivity(outputFile: string | undefined): string {
|
|
260
250
|
if (!outputFile) return "";
|
|
261
251
|
try {
|
|
262
252
|
const stat = fs.statSync(outputFile);
|
|
@@ -265,14 +255,11 @@ function getOutputTail(outputFile: string | undefined, maxLines: number = 3): st
|
|
|
265
255
|
if (ago < 60000) return `active ${Math.floor(ago / 1000)}s ago`;
|
|
266
256
|
return `active ${Math.floor(ago / 60000)}m ago`;
|
|
267
257
|
} catch {
|
|
268
|
-
// Last-activity text is best effort; missing files should
|
|
258
|
+
// Last-activity text is best effort; missing files should omit the hint.
|
|
269
259
|
return "";
|
|
270
260
|
}
|
|
271
261
|
}
|
|
272
262
|
|
|
273
|
-
/**
|
|
274
|
-
* Find the latest session file in a directory
|
|
275
|
-
*/
|
|
276
263
|
export function findLatestSessionFile(sessionDir: string): string | null {
|
|
277
264
|
if (!fs.existsSync(sessionDir)) return null;
|
|
278
265
|
const files = fs.readdirSync(sessionDir)
|
|
@@ -289,9 +276,6 @@ export function findLatestSessionFile(sessionDir: string): string | null {
|
|
|
289
276
|
return latest ? latest.path : null;
|
|
290
277
|
}
|
|
291
278
|
|
|
292
|
-
/**
|
|
293
|
-
* Write a prompt to a temporary file
|
|
294
|
-
*/
|
|
295
279
|
function writePrompt(agent: string, prompt: string): { dir: string; path: string } {
|
|
296
280
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagent-"));
|
|
297
281
|
const p = path.join(dir, `${agent.replace(/[^\w.-]/g, "_")}.md`);
|
|
@@ -299,13 +283,6 @@ function writePrompt(agent: string, prompt: string): { dir: string; path: string
|
|
|
299
283
|
return { dir, path: p };
|
|
300
284
|
}
|
|
301
285
|
|
|
302
|
-
// ============================================================================
|
|
303
|
-
// Message Parsing Utilities
|
|
304
|
-
// ============================================================================
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* Get the final text output from a list of messages
|
|
308
|
-
*/
|
|
309
286
|
export function getFinalOutput(messages: Message[]): string {
|
|
310
287
|
const validTextParts: string[] = [];
|
|
311
288
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { stableJsonDigest } from "./launch-contract.ts";
|
|
2
|
+
|
|
3
|
+
export interface WorkflowChildPermitInput {
|
|
4
|
+
issuerPackage: string;
|
|
5
|
+
workflowRunId: string;
|
|
6
|
+
childKey: string;
|
|
7
|
+
agent: string;
|
|
8
|
+
launchContractDigest: string;
|
|
9
|
+
context: "fresh" | "fork";
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface WorkflowChildPermitLaunch {
|
|
13
|
+
workflowRunId: string;
|
|
14
|
+
childKey: string;
|
|
15
|
+
agent: string;
|
|
16
|
+
launchContractDigest: string;
|
|
17
|
+
context: "fresh" | "fork";
|
|
18
|
+
runner: "pi";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface WorkflowChildPermitContext {
|
|
22
|
+
permit: WorkflowChildPermit;
|
|
23
|
+
workflowRunId: string;
|
|
24
|
+
childKey: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface WorkflowChildPermit {
|
|
28
|
+
readonly __workflowChildPermit: unique symbol;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface WorkflowChildPermitRecord {
|
|
32
|
+
issuerPackage: string;
|
|
33
|
+
workflowRunId: string;
|
|
34
|
+
childKey: string;
|
|
35
|
+
agent: string;
|
|
36
|
+
expectedProjectionDigest: string;
|
|
37
|
+
state: "available" | "claimed" | "consumed";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const records = new WeakMap<object, WorkflowChildPermitRecord>();
|
|
41
|
+
|
|
42
|
+
function projectionDigest(input: Omit<WorkflowChildPermitLaunch, "workflowRunId">): string {
|
|
43
|
+
return stableJsonDigest({
|
|
44
|
+
version: 1,
|
|
45
|
+
childKey: input.childKey,
|
|
46
|
+
agent: input.agent,
|
|
47
|
+
launchContractDigest: input.launchContractDigest,
|
|
48
|
+
context: input.context,
|
|
49
|
+
runner: input.runner,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function required(value: string, label: string): string {
|
|
54
|
+
if (!value.trim() || value !== value.trim()) throw new Error(`${label} must be a non-empty trimmed string.`);
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Package-internal first-slice permit. It is opaque, in-memory, and not serializable. */
|
|
59
|
+
export function createWorkflowChildPermit(input: WorkflowChildPermitInput): WorkflowChildPermit {
|
|
60
|
+
const permit = Object.freeze(Object.create(null)) as WorkflowChildPermit;
|
|
61
|
+
const record: WorkflowChildPermitRecord = {
|
|
62
|
+
issuerPackage: required(input.issuerPackage, "issuerPackage"),
|
|
63
|
+
workflowRunId: required(input.workflowRunId, "workflowRunId"),
|
|
64
|
+
childKey: required(input.childKey, "childKey"),
|
|
65
|
+
agent: required(input.agent, "agent"),
|
|
66
|
+
expectedProjectionDigest: projectionDigest({
|
|
67
|
+
childKey: input.childKey,
|
|
68
|
+
agent: input.agent,
|
|
69
|
+
launchContractDigest: required(input.launchContractDigest, "launchContractDigest"),
|
|
70
|
+
context: input.context,
|
|
71
|
+
runner: "pi",
|
|
72
|
+
}),
|
|
73
|
+
state: "available",
|
|
74
|
+
};
|
|
75
|
+
records.set(permit as object, record);
|
|
76
|
+
return permit;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function validateWorkflowChildPermitRoot(permit: WorkflowChildPermit, workflowRunId: string): string | undefined {
|
|
80
|
+
const record = records.get(permit as object);
|
|
81
|
+
if (!record) return "Workflow child permit is invalid.";
|
|
82
|
+
if (record.state !== "available") return "Workflow child permit is already consumed.";
|
|
83
|
+
if (record.workflowRunId !== workflowRunId) return "Workflow child permit does not match this workflow root.";
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Claim the first distinct launch attempt before validating its model-authored shape. */
|
|
88
|
+
export function claimWorkflowChildPermit(permit: WorkflowChildPermit, workflowRunId: string, childKey: string): string | undefined {
|
|
89
|
+
const record = records.get(permit as object);
|
|
90
|
+
if (!record) return "Workflow child permit is invalid.";
|
|
91
|
+
if (record.state !== "available") return "Workflow child permit is already consumed.";
|
|
92
|
+
if (record.workflowRunId !== workflowRunId) return "Workflow child permit does not match this workflow root.";
|
|
93
|
+
record.state = record.childKey === childKey ? "claimed" : "consumed";
|
|
94
|
+
if (record.childKey !== childKey) return "Workflow child permit child key mismatch.";
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Verify and permanently consume the permit before the one native process spawn. */
|
|
99
|
+
export function consumeWorkflowChildPermit(permit: WorkflowChildPermit, launch: WorkflowChildPermitLaunch): string | undefined {
|
|
100
|
+
const record = records.get(permit as object);
|
|
101
|
+
if (!record) return "Workflow child permit is invalid.";
|
|
102
|
+
if (record.state === "available") return "Workflow child permit launch was not claimed.";
|
|
103
|
+
if (record.state === "consumed") return "Workflow child permit is already consumed.";
|
|
104
|
+
if (record.workflowRunId !== launch.workflowRunId) return "Workflow child permit does not match this workflow root.";
|
|
105
|
+
record.state = "consumed";
|
|
106
|
+
if (record.childKey !== launch.childKey) return "Workflow child permit child key mismatch.";
|
|
107
|
+
if (record.agent !== launch.agent) return "Workflow child permit agent mismatch.";
|
|
108
|
+
if (launch.runner !== "pi") return "Workflow child permit supports native Pi children only.";
|
|
109
|
+
if (record.expectedProjectionDigest !== projectionDigest(launch)) return "Workflow child permit does not match the final launch projection.";
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function workflowChildPermitConsumed(permit: WorkflowChildPermit): boolean {
|
|
114
|
+
const state = records.get(permit as object)?.state;
|
|
115
|
+
return state === "claimed" || state === "consumed";
|
|
116
|
+
}
|
|
@@ -298,7 +298,6 @@ export function toSubagentDelegationExecutionParams(request: SubagentDelegationR
|
|
|
298
298
|
enforceHardTurnLimit: true,
|
|
299
299
|
toolBudget: request.toolBudget,
|
|
300
300
|
skill: request.skill,
|
|
301
|
-
output: false,
|
|
302
301
|
...(request.result.kind === "structured" ? { outputSchema: request.result.schema } : {}),
|
|
303
302
|
acceptance: false,
|
|
304
303
|
artifacts: request.artifacts,
|
|
@@ -3,7 +3,7 @@ import * as fs from "node:fs";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { keyText, type ExtensionAPI, type ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
5
5
|
import { Key, matchesKey, truncateToWidth, type Component, type KeyId, type TUI } from "@earendil-works/pi-tui";
|
|
6
|
-
import { BUILTIN_AGENT_NAMES, discoverAgents, discoverAgentsAll, findBlockingAgentDiagnostic, resolveAgentName, type AgentConfig, type AgentDiscoveryDiagnostic, type AgentScope } from "../agents/agents.ts";
|
|
6
|
+
import { BUILTIN_AGENT_NAMES, discoverAgents, discoverAgentsAll, findBlockingAgentDiagnostic, formatUnknownAgentError, resolveAgentName, unknownAgentDiagnosticContext, type AgentConfig, type AgentDiscoveryDiagnostic, type AgentScope, type UnknownAgentDiagnosticContext } from "../agents/agents.ts";
|
|
7
7
|
import { listRuntimeAgentConfigs, mergeRuntimeAgents } from "../agents/runtime-agent-registry.ts";
|
|
8
8
|
import { resolveExistingReadPaths } from "../shared/settings.ts";
|
|
9
9
|
import {
|
|
@@ -22,6 +22,7 @@ import { listAsyncRuns, formatAsyncRunProgressLabel, type AsyncRunSummary } from
|
|
|
22
22
|
import { encodeInspectReply, handleInspectRpcArgs, INSPECT_WIDGET_KEY } from "../runs/background/inspect-rpc.ts";
|
|
23
23
|
import { listScheduledRunSummaries } from "../runs/background/scheduled-runs.ts";
|
|
24
24
|
import { SUBAGENT_FANOUT_CHILD_ENV } from "../runs/shared/pi-args.ts";
|
|
25
|
+
import { FLEET_OPEN_SHORTCUT } from "../shared/shortcuts.ts";
|
|
25
26
|
import type { SlashSubagentResponse, SlashSubagentUpdate } from "./slash-bridge.ts";
|
|
26
27
|
import { registerPromptWorkflowCommands } from "./prompt-workflows.ts";
|
|
27
28
|
import { openSubagentsAdmin } from "./subagents-admin.ts";
|
|
@@ -108,9 +109,9 @@ const extractExecutionFlags = (rawArgs: string): { args: string; bg: boolean; fo
|
|
|
108
109
|
return { args, bg, fork };
|
|
109
110
|
};
|
|
110
111
|
|
|
111
|
-
function discoverSlashAgents(pi: ExtensionAPI, cwd: string, scope: AgentScope): { agents: AgentConfig[]; agentDiagnostics?: AgentDiscoveryDiagnostic[] } {
|
|
112
|
+
function discoverSlashAgents(pi: ExtensionAPI, cwd: string, scope: AgentScope): { agents: AgentConfig[]; agentDiagnostics?: AgentDiscoveryDiagnostic[]; unknownAgentDiagnosticContext: UnknownAgentDiagnosticContext } {
|
|
112
113
|
const discovered = discoverAgents(cwd, scope);
|
|
113
|
-
if (listRuntimeAgentConfigs(pi).length === 0) return discovered;
|
|
114
|
+
if (listRuntimeAgentConfigs(pi).length === 0) return { ...discovered, unknownAgentDiagnosticContext: unknownAgentDiagnosticContext(discovered) };
|
|
114
115
|
const all = discoverAgentsAll(cwd);
|
|
115
116
|
const configuredAgents: AgentConfig[] = [
|
|
116
117
|
...all.builtin,
|
|
@@ -118,7 +119,8 @@ function discoverSlashAgents(pi: ExtensionAPI, cwd: string, scope: AgentScope):
|
|
|
118
119
|
...(scope !== "project" ? all.user : []),
|
|
119
120
|
...(scope !== "user" ? all.project : []),
|
|
120
121
|
];
|
|
121
|
-
|
|
122
|
+
const merged = mergeRuntimeAgents(pi, discovered, configuredAgents);
|
|
123
|
+
return { ...merged, unknownAgentDiagnosticContext: { ...unknownAgentDiagnosticContext(discovered), agents: merged.agents } };
|
|
122
124
|
}
|
|
123
125
|
|
|
124
126
|
const makeAgentCompletions = (pi: ExtensionAPI, state: SubagentState) => (prefix: string) => {
|
|
@@ -693,7 +695,7 @@ export function registerSlashCommands(
|
|
|
693
695
|
: resolvedAgent.agent;
|
|
694
696
|
const diagnostic = findBlockingAgentDiagnostic(agentName, candidates, discovered.agentDiagnostics);
|
|
695
697
|
if (diagnostic || resolvedAgent.error || !resolvedAgent.agent) {
|
|
696
|
-
ctx.ui.notify(diagnostic ? `Agent '${agentName}' has invalid configuration: ${diagnostic.error}` : resolvedAgent.error ??
|
|
698
|
+
ctx.ui.notify(diagnostic ? `Agent '${agentName}' has invalid configuration: ${diagnostic.error}` : resolvedAgent.error ?? formatUnknownAgentError(agentName, discovered.unknownAgentDiagnosticContext), "error");
|
|
697
699
|
return;
|
|
698
700
|
}
|
|
699
701
|
|
|
@@ -776,7 +778,7 @@ export function registerSlashCommands(
|
|
|
776
778
|
handler: async (_args, ctx) => showFleet(ctx),
|
|
777
779
|
});
|
|
778
780
|
|
|
779
|
-
pi.registerShortcut(
|
|
781
|
+
pi.registerShortcut(FLEET_OPEN_SHORTCUT, {
|
|
780
782
|
description: "Open subagent fleet inspector",
|
|
781
783
|
handler: async (ctx) => showFleet(ctx),
|
|
782
784
|
});
|