pi-subagents 0.40.0 → 0.41.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 +76 -0
- package/README.md +246 -525
- package/agents/oracle.md +1 -0
- package/package.json +12 -4
- package/prompts/parallel-context-build.md +1 -1
- package/prompts/parallel-handoff-plan.md +1 -1
- package/prompts/review-loop.md +1 -1
- package/skills/pi-subagents/SKILL.md +6 -6
- package/skills/pi-subagents/references/constraints-and-recipes.md +19 -26
- package/skills/pi-subagents/references/execution-controls.md +98 -97
- package/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
- package/skills/pi-subagents/references/prompting-and-roles.md +18 -27
- package/src/agents/agent-management.ts +155 -65
- package/src/agents/agent-serializer.ts +19 -0
- package/src/agents/agents.ts +154 -71
- package/src/agents/chain-serializer.ts +10 -7
- package/src/agents/frontmatter.ts +5 -3
- package/src/agents/identity.ts +1 -1
- package/src/agents/proactive-skills.ts +13 -10
- package/src/agents/skills.ts +23 -6
- package/src/api/control-channel.ts +4 -0
- package/src/api/delegation.ts +26 -194
- package/src/api/external-runs.ts +129 -0
- package/src/api/intercom-bridge.ts +3 -0
- package/src/api/pi-args.ts +5 -0
- package/src/api/preflight.ts +3 -3
- package/src/api/shared-types.ts +19 -0
- package/src/extension/config.ts +10 -0
- package/src/extension/control-notices.ts +5 -39
- package/src/extension/doctor.ts +10 -9
- package/src/extension/fanout-child.ts +7 -4
- package/src/extension/index.ts +232 -68
- package/src/extension/rpc.ts +18 -12
- package/src/extension/schemas.ts +48 -37
- package/src/extension/tool-description.ts +36 -86
- package/src/inspectors/herdr/actions.ts +229 -0
- package/src/inspectors/herdr/client.ts +130 -0
- package/src/inspectors/herdr/inspector-runner.ts +141 -0
- package/src/inspectors/herdr/project-panes.ts +154 -0
- package/src/integrations/herdr-status.ts +330 -0
- package/src/intercom/intercom-bridge.ts +3 -2
- package/src/intercom/result-intercom.ts +5 -1
- package/src/missions/actions.ts +372 -0
- package/src/missions/lifecycle.ts +314 -0
- package/src/missions/store.ts +442 -0
- package/src/missions/types.ts +135 -0
- package/src/policy/authority.ts +46 -0
- package/src/profiles/profiles.ts +29 -3
- package/src/runs/background/async-execution.ts +98 -49
- package/src/runs/background/async-job-tracker.ts +10 -2
- package/src/runs/background/async-resume.ts +6 -6
- package/src/runs/background/async-status.ts +29 -1
- package/src/runs/background/auto-drain.ts +3 -3
- package/src/runs/background/chain-append.ts +3 -2
- package/src/runs/background/control-channel.ts +9 -7
- package/src/runs/background/fleet-view.ts +3 -4
- package/src/runs/background/notify.ts +2 -1
- package/src/runs/background/process-terminal.ts +5 -5
- package/src/runs/background/result-watcher.ts +13 -5
- package/src/runs/background/run-id-resolver.ts +3 -3
- package/src/runs/background/run-status.ts +35 -8
- package/src/runs/background/scheduled-runs.ts +602 -375
- package/src/runs/background/stale-run-reconciler.ts +3 -3
- package/src/runs/background/subagent-runner.ts +608 -445
- package/src/runs/background/subagent-wait.ts +50 -9
- package/src/runs/background/wait-subscriptions.ts +253 -0
- package/src/runs/background/wait-tool.ts +12 -4
- package/src/runs/foreground/async-steering-action.ts +3 -3
- package/src/runs/foreground/chain-clarify.ts +8 -4
- package/src/runs/foreground/chain-execution.ts +56 -30
- package/src/runs/foreground/execution.ts +15 -2
- package/src/runs/foreground/subagent-executor.ts +1023 -273
- package/src/runs/shared/acceptance.ts +28 -6
- package/src/runs/shared/child-protocol.ts +302 -22
- package/src/runs/shared/dynamic-fanout.ts +1 -1
- package/src/runs/shared/external-cli-runner.ts +130 -0
- package/src/runs/shared/long-running-guard.ts +42 -1
- package/src/runs/shared/nested-events.ts +59 -5
- package/src/runs/shared/nested-render.ts +9 -4
- package/src/runs/shared/parallel-handoff.ts +86 -2
- package/src/runs/shared/parallel-utils.ts +11 -2
- package/src/runs/shared/permissions.ts +95 -0
- package/src/runs/shared/pi-args.ts +11 -1
- package/src/runs/shared/pi-spawn.ts +11 -1
- package/src/runs/shared/run-history.ts +1 -1
- package/src/runs/shared/subagent-prompt-runtime.ts +36 -5
- package/src/runs/shared/subagent-startup-retry.ts +5 -2
- package/src/runs/shared/turn-budget.ts +6 -6
- package/src/runs/shared/worktree.ts +122 -12
- package/src/shared/accessible-dir.ts +29 -7
- package/src/shared/artifacts.ts +18 -1
- package/src/shared/fork-context.ts +3 -2
- package/src/shared/launch-contract.ts +1 -0
- package/src/shared/settings.ts +10 -0
- package/src/shared/types.ts +156 -14
- package/src/shared/utils.ts +8 -6
- package/src/slash/delegation-adapters.ts +32 -194
- package/src/slash/delegation-request.ts +43 -126
- package/src/slash/prompt-template-bridge.ts +158 -205
- package/src/slash/prompt-workflows.ts +21 -57
- package/src/slash/slash-bridge.ts +14 -0
- package/src/slash/slash-commands.ts +31 -632
- package/src/slash/subagents-admin.ts +18 -14
- package/src/tui/fleet-status.ts +156 -21
- package/src/tui/fleet-transcript.ts +110 -5
- package/src/tui/fleet.ts +56 -24
- package/src/tui/render.ts +291 -109
- package/src/types/pi-runtime-compat.d.ts +14 -0
- package/src/watchdog/lsp-diagnostics.ts +12 -7
- package/src/watchdog/model-selection.ts +2 -2
- package/src/watchdog/permission-arbiter.ts +145 -0
- package/src/watchdog/register-child.ts +1 -1
- package/src/watchdog/register-main.ts +1 -1
- package/src/watchdog/review.ts +4 -1
- package/src/watchdog/runtime.ts +3 -2
- package/src/workflows/chat-progress.ts +140 -0
- package/src/workflows/scripted-workflow.ts +415 -0
- package/agents/advisor.md +0 -73
- package/src/extension/chain-validation.ts +0 -181
|
@@ -4,8 +4,7 @@ import type { AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
|
4
4
|
import { formatDuration, formatModelThinking, formatTokens, shortenPath } from "../../shared/formatters.ts";
|
|
5
5
|
import { formatActivityLabel } from "../../shared/status-format.ts";
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
RESULTS_DIR,
|
|
7
|
+
DIRS,
|
|
9
8
|
type ActivityState,
|
|
10
9
|
type AsyncJobStep,
|
|
11
10
|
type AsyncStatus,
|
|
@@ -321,10 +320,10 @@ export function inspectSubagentFleet(_params: FleetViewParams, deps: FleetViewDe
|
|
|
321
320
|
|
|
322
321
|
let asyncRuns: AsyncRunSummary[];
|
|
323
322
|
try {
|
|
324
|
-
asyncRuns = listAsyncRuns(deps.asyncDirRoot ??
|
|
323
|
+
asyncRuns = listAsyncRuns(deps.asyncDirRoot ?? DIRS.async, {
|
|
325
324
|
states: ["queued", "running"],
|
|
326
325
|
sessionId: deps.state?.currentSessionId ?? undefined,
|
|
327
|
-
resultsDir: deps.resultsDir ??
|
|
326
|
+
resultsDir: deps.resultsDir ?? DIRS.results,
|
|
328
327
|
kill: deps.kill,
|
|
329
328
|
now: deps.now,
|
|
330
329
|
});
|
|
@@ -170,12 +170,13 @@ function sendCompletion(pi: Pick<ExtensionAPI, "sendMessage">, items: PendingCom
|
|
|
170
170
|
if (items.length === 0) return true;
|
|
171
171
|
const details = items.map((item) => item.details);
|
|
172
172
|
const content = details.length === 1 ? formatSingleCompletion(details[0]!) : formatGroupedCompletion(details);
|
|
173
|
+
const display = details.some((detail) => detail.source === "foreground" || detail.status !== "completed");
|
|
173
174
|
try {
|
|
174
175
|
pi.sendMessage(
|
|
175
176
|
{
|
|
176
177
|
customType: "subagent-notify",
|
|
177
178
|
content,
|
|
178
|
-
display
|
|
179
|
+
display,
|
|
179
180
|
},
|
|
180
181
|
{ triggerTurn: items.some((item) => item.triggerTurn) },
|
|
181
182
|
);
|
|
@@ -90,9 +90,9 @@ export function readProcessTerminalCandidate(asyncDir: string): ProcessTerminalC
|
|
|
90
90
|
runnerProcessInstanceId: raw.runnerProcessInstanceId,
|
|
91
91
|
writers,
|
|
92
92
|
...(expectedWriters ? { expectedWriters } : {}),
|
|
93
|
-
...(raw.sessionFile ? { sessionFile: raw.sessionFile } : {}),
|
|
94
|
-
...(raw.revivalLeaseToken ? { revivalLeaseToken: raw.revivalLeaseToken } : {}),
|
|
95
|
-
...(raw.revivalLeaseReleaseAcknowledged
|
|
93
|
+
...(typeof raw.sessionFile === "string" && raw.sessionFile ? { sessionFile: raw.sessionFile } : {}),
|
|
94
|
+
...(typeof raw.revivalLeaseToken === "string" && raw.revivalLeaseToken ? { revivalLeaseToken: raw.revivalLeaseToken } : {}),
|
|
95
|
+
...(typeof raw.revivalLeaseReleaseAcknowledged === "boolean" ? { revivalLeaseReleaseAcknowledged: raw.revivalLeaseReleaseAcknowledged } : {}),
|
|
96
96
|
};
|
|
97
97
|
} catch (error) {
|
|
98
98
|
if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
|
|
@@ -154,7 +154,7 @@ export function sanitizeProcessTerminal(value: unknown, fallback: { runId?: stri
|
|
|
154
154
|
if (value === undefined) return undefined;
|
|
155
155
|
try {
|
|
156
156
|
validateProof(value, label, fallback);
|
|
157
|
-
return value;
|
|
157
|
+
return value as ProcessTerminalV1;
|
|
158
158
|
} catch (error) {
|
|
159
159
|
return unknownProof(fallback.runId ?? label, fallback.runnerProcessInstanceId ?? "unknown", "proof-write-failed", errorMessage(error));
|
|
160
160
|
}
|
|
@@ -164,7 +164,7 @@ export function readProcessTerminal(asyncDir: string, fallback?: { runId?: strin
|
|
|
164
164
|
try {
|
|
165
165
|
const raw = JSON.parse(fs.readFileSync(processTerminalPath(asyncDir), "utf-8")) as unknown;
|
|
166
166
|
validateProof(raw, asyncDir, fallback);
|
|
167
|
-
return raw;
|
|
167
|
+
return raw as ProcessTerminalV1;
|
|
168
168
|
} catch (error) {
|
|
169
169
|
if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
|
|
170
170
|
return unknownProof(fallback?.runId ?? path.basename(asyncDir), fallback?.runnerProcessInstanceId ?? "unknown", "proof-write-failed", errorMessage(error));
|
|
@@ -39,6 +39,8 @@ type ResultWatcherDeps = {
|
|
|
39
39
|
fs?: ResultWatcherFs;
|
|
40
40
|
timers?: ResultWatcherTimers;
|
|
41
41
|
notifier?: Pick<CompletionNotifier, "deliver">;
|
|
42
|
+
/** Receives persisted completions before active-session delivery filtering. */
|
|
43
|
+
observeCompletion?: (result: CompletionNotification & { runId: string }) => void;
|
|
42
44
|
/** External grouped-result transport. Disable when native completion notifications own delivery. */
|
|
43
45
|
deliverIntercomResults?: boolean;
|
|
44
46
|
};
|
|
@@ -46,6 +48,7 @@ type ResultWatcherDeps = {
|
|
|
46
48
|
type ResultFileChild = {
|
|
47
49
|
agent?: string;
|
|
48
50
|
output?: string;
|
|
51
|
+
structuredOutput?: unknown;
|
|
49
52
|
outputState?: SubagentOutputState;
|
|
50
53
|
error?: string;
|
|
51
54
|
success?: boolean;
|
|
@@ -144,10 +147,14 @@ export function createResultWatcher(
|
|
|
144
147
|
try {
|
|
145
148
|
const data = JSON.parse(fsApi.readFileSync(resultPath, "utf-8")) as ResultFileData;
|
|
146
149
|
if (typeof data.sessionId !== "string" || !data.sessionId) return;
|
|
150
|
+
const runId = data.runId ?? data.id ?? file.replace(/\.json$/i, "");
|
|
151
|
+
try {
|
|
152
|
+
deps.observeCompletion?.({ ...data, runId });
|
|
153
|
+
} catch (error) {
|
|
154
|
+
console.error(`Completion observer failed for '${resultPath}':`, error);
|
|
155
|
+
}
|
|
147
156
|
const epoch = deliveryEpoch;
|
|
148
157
|
if (!ownsSession(data.sessionId, epoch)) return;
|
|
149
|
-
|
|
150
|
-
const runId = data.runId ?? data.id ?? file.replace(/\.json$/i, "");
|
|
151
158
|
const hasExplicitNestedChildren = data.nestedChildren !== undefined;
|
|
152
159
|
let nestedChildren = compactNestedResultChildren(sanitizeNestedResultChildren(data.nestedChildren, resultPath, "nestedChildren"));
|
|
153
160
|
if (!nestedChildren?.length && !hasExplicitNestedChildren) {
|
|
@@ -184,7 +191,8 @@ export function createResultWatcher(
|
|
|
184
191
|
const normalizedChildren = attachNestedChildrenToResultChildren(runId, resultChildren.map((result = {}, index): SubagentResultIntercomChild => {
|
|
185
192
|
const baseOutput = hasResultChildren ? result.output : result.output ?? data.summary;
|
|
186
193
|
const hasRealOutput = typeof baseOutput === "string" && baseOutput.trim().length > 0;
|
|
187
|
-
const
|
|
194
|
+
const structuredPreview = result.structuredOutput === undefined ? undefined : JSON.stringify(result.structuredOutput, null, 2).slice(0, 4_000);
|
|
195
|
+
const output = hasRealOutput ? baseOutput : structuredPreview ? `Structured output:\n${structuredPreview}` : "(no output)";
|
|
188
196
|
const summary = result.success === false && result.error
|
|
189
197
|
? `${result.error}${hasRealOutput ? `\n\nOutput:\n${baseOutput}` : ""}`
|
|
190
198
|
: output;
|
|
@@ -223,7 +231,7 @@ export function createResultWatcher(
|
|
|
223
231
|
const intercomTarget = data.intercomTarget?.trim();
|
|
224
232
|
let intercomDelivered = false;
|
|
225
233
|
if (deliverIntercomResults && intercomTarget && triggerTurn) {
|
|
226
|
-
const mode = data.mode === "single" || data.mode === "parallel" || data.mode === "chain"
|
|
234
|
+
const mode = data.mode === "single" || data.mode === "parallel" || data.mode === "chain" || data.mode === "workflow"
|
|
227
235
|
? data.mode
|
|
228
236
|
: resultChildren.length > 1 ? "chain" : "single";
|
|
229
237
|
intercomDelivered = await deliverSubagentResultIntercomEvent(pi.events, buildSubagentResultIntercomPayload({
|
|
@@ -232,7 +240,7 @@ export function createResultWatcher(
|
|
|
232
240
|
mode,
|
|
233
241
|
source: "async",
|
|
234
242
|
children: normalizedChildren,
|
|
235
|
-
asyncId: data.id,
|
|
243
|
+
asyncId: data.id ?? undefined,
|
|
236
244
|
asyncDir: data.asyncDir,
|
|
237
245
|
...(data.parallelHandoff ? { parallelHandoff: data.parallelHandoff } : {}),
|
|
238
246
|
}));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { DIRS, type SubagentState } from "../../shared/types.ts";
|
|
4
4
|
import { findAsyncRunPrefixMatches, type AsyncRunLocation } from "./async-resume.ts";
|
|
5
5
|
import { assertSafeNestedId, findNestedRunMatchesById, type NestedRoute, type NestedRunMatch, type NestedRunResolutionScope } from "../shared/nested-events.ts";
|
|
6
6
|
|
|
@@ -66,8 +66,8 @@ function asyncPrefixMatches(prefix: string, asyncDirRoot: string, resultsDir: st
|
|
|
66
66
|
|
|
67
67
|
export function resolveSubagentRunId(id: string, deps: ResolveSubagentRunIdDeps = {}): ResolvedSubagentRunId | undefined {
|
|
68
68
|
assertSafeNestedId("id", id);
|
|
69
|
-
const asyncDirRoot = deps.asyncDirRoot ??
|
|
70
|
-
const resultsDir = deps.resultsDir ??
|
|
69
|
+
const asyncDirRoot = deps.asyncDirRoot ?? DIRS.async;
|
|
70
|
+
const resultsDir = deps.resultsDir ?? DIRS.results;
|
|
71
71
|
|
|
72
72
|
const nestedScope = deps.nested ?? nestedScopeFromState(deps.state);
|
|
73
73
|
if (hasExactForegroundId(deps.state, id)) return { kind: "foreground", id };
|
|
@@ -6,18 +6,21 @@ import { formatAsyncResultTranscript, formatAsyncRunTranscript, formatNestedRunT
|
|
|
6
6
|
import { formatNestedRunStatusLines } from "../shared/nested-render.ts";
|
|
7
7
|
import { formatModelThinking } from "../../shared/formatters.ts";
|
|
8
8
|
import { formatActivityLabel } from "../../shared/status-format.ts";
|
|
9
|
-
import {
|
|
9
|
+
import { DIRS, type AsyncStatus, type Details, type ForegroundResumeRun, type NestedRunSummary, type SteeringStatus, type SubagentState } from "../../shared/types.ts";
|
|
10
10
|
import { resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.ts";
|
|
11
11
|
import { resolveSubagentResultStatus } from "../../intercom/result-intercom.ts";
|
|
12
12
|
import { readProcessTerminal, sanitizeProcessTerminal } from "./process-terminal.ts";
|
|
13
|
+
import { formatWaitSubscriptions } from "./wait-subscriptions.ts";
|
|
13
14
|
import { resolveAsyncRunLocation } from "./async-resume.ts";
|
|
14
15
|
import { resolveSubagentRunId } from "./run-id-resolver.ts";
|
|
15
16
|
import { flatToLogicalStepIndex, normalizeParallelGroups } from "./parallel-groups.ts";
|
|
16
17
|
import { reconcileAsyncRun, reconcileNestedAsyncDescendants } from "./stale-run-reconciler.ts";
|
|
17
18
|
import { attachRootChildrenToSteps, findNestedRouteForRootId, projectNestedRegistryForRoot, type NestedRunResolutionScope } from "../shared/nested-events.ts";
|
|
19
|
+
import { readMissionBinding } from "../../missions/lifecycle.ts";
|
|
20
|
+
import { formatWorkflowJsonPreview } from "../../workflows/scripted-workflow.ts";
|
|
18
21
|
|
|
19
22
|
interface RunStatusParams {
|
|
20
|
-
action?:
|
|
23
|
+
action?: string;
|
|
21
24
|
id?: string;
|
|
22
25
|
runId?: string;
|
|
23
26
|
dir?: string;
|
|
@@ -65,6 +68,7 @@ function formatResumeGuidance(runId: string | undefined, children: Array<{ agent
|
|
|
65
68
|
function stepLineLabel(status: AsyncStatus, index: number): string {
|
|
66
69
|
const steps = status.steps ?? [];
|
|
67
70
|
if (status.mode === "parallel") return `Agent ${index + 1}/${steps.length || 1}`;
|
|
71
|
+
if (status.mode === "workflow") return `Workflow child ${steps[index]?.workflowKey ?? index + 1}`;
|
|
68
72
|
if (status.mode === "chain") {
|
|
69
73
|
const chainStepCount = status.chainStepCount ?? (steps.length || 1);
|
|
70
74
|
const groups = normalizeParallelGroups(status.parallelGroups, steps.length, chainStepCount);
|
|
@@ -208,8 +212,8 @@ function formatNestedExactStatus(rootRunId: string, run: NestedRunSummary): stri
|
|
|
208
212
|
}
|
|
209
213
|
|
|
210
214
|
export function inspectSubagentStatus(params: RunStatusParams, deps: RunStatusDeps = {}): AgentToolResult<Details> {
|
|
211
|
-
const asyncDirRoot = deps.asyncDirRoot ??
|
|
212
|
-
const resultsDir = deps.resultsDir ??
|
|
215
|
+
const asyncDirRoot = deps.asyncDirRoot ?? DIRS.async;
|
|
216
|
+
const resultsDir = deps.resultsDir ?? DIRS.results;
|
|
213
217
|
const currentSessionId = deps.state?.currentSessionId ?? undefined;
|
|
214
218
|
if (params.view && params.view !== "fleet" && params.view !== "transcript") {
|
|
215
219
|
return {
|
|
@@ -239,8 +243,9 @@ export function inspectSubagentStatus(params: RunStatusParams, deps: RunStatusDe
|
|
|
239
243
|
details: { mode: "single", results: [] },
|
|
240
244
|
};
|
|
241
245
|
}
|
|
246
|
+
const waitSubscriptions = deps.state ? formatWaitSubscriptions(deps.state, deps.now?.() ?? Date.now()) : undefined;
|
|
242
247
|
return {
|
|
243
|
-
content: [{ type: "text", text: formatAsyncRunList(runs) }],
|
|
248
|
+
content: [{ type: "text", text: [formatAsyncRunList(runs), waitSubscriptions].filter(Boolean).join("\n\n") }],
|
|
244
249
|
details: { mode: "single", results: [] },
|
|
245
250
|
};
|
|
246
251
|
} catch (error) {
|
|
@@ -366,9 +371,18 @@ export function inspectSubagentStatus(params: RunStatusParams, deps: RunStatusDe
|
|
|
366
371
|
const steeringText = formatSteeringSummary(status);
|
|
367
372
|
const processTerminal = readProcessTerminal(asyncDir, { runId: status.runId, runnerProcessInstanceId: status.processTerminal?.runnerProcessInstanceId })
|
|
368
373
|
?? sanitizeProcessTerminal(status.processTerminal, { runId: status.runId, runnerProcessInstanceId: status.processTerminal?.runnerProcessInstanceId }, path.join(asyncDir, "status.json"));
|
|
374
|
+
let missionId: string | undefined;
|
|
375
|
+
try {
|
|
376
|
+
missionId = readMissionBinding(asyncDir)?.missionId;
|
|
377
|
+
} catch (error) {
|
|
378
|
+
nestedWarning = `${nestedWarning ? `${nestedWarning}; ` : ""}Mission binding unavailable: ${error instanceof Error ? error.message : String(error)}`;
|
|
379
|
+
}
|
|
369
380
|
|
|
381
|
+
const workflowReturnPreview = status.workflow?.value !== undefined ? formatWorkflowJsonPreview(status.workflow.value, 240) : undefined;
|
|
382
|
+
const workflowEmitPreview = status.workflow?.emits.length ? formatWorkflowJsonPreview(status.workflow.emits.at(-1), 240) : undefined;
|
|
370
383
|
const lines = [
|
|
371
384
|
`Run: ${status.runId}`,
|
|
385
|
+
missionId ? `Mission: ${missionId}` : undefined,
|
|
372
386
|
`State: ${status.state}`,
|
|
373
387
|
processTerminal ? `Process terminal: ${processTerminal.state}${processTerminal.reason ? ` (${processTerminal.reason})` : ""}` : undefined,
|
|
374
388
|
status.capabilityCeiling ? `Capability ceiling: ${status.capabilityCeiling.allowedTools === undefined ? "names unrestricted" : status.capabilityCeiling.allowedTools.length === 0 ? "none" : status.capabilityCeiling.allowedTools.join(", ")}\nExtensions denied: ${status.capabilityCeiling.denyExtensions ? "yes" : "no"} (sources: ${status.capabilityCeiling.sources.join(", ")})` : undefined,
|
|
@@ -377,6 +391,9 @@ export function inspectSubagentStatus(params: RunStatusParams, deps: RunStatusDe
|
|
|
377
391
|
statusActivityText ? `Activity: ${statusActivityText}` : undefined,
|
|
378
392
|
steeringText ? `Steering: ${steeringText}` : undefined,
|
|
379
393
|
`Mode: ${status.mode}`,
|
|
394
|
+
status.parentWorkflowRunId ? `Workflow parent: ${status.parentWorkflowRunId}${status.workflowKey ? ` (${status.workflowKey})` : ""}` : undefined,
|
|
395
|
+
status.mode === "workflow" && workflowReturnPreview !== undefined ? `Return: ${workflowReturnPreview}` : undefined,
|
|
396
|
+
status.mode === "workflow" && workflowEmitPreview !== undefined ? `Latest emit: ${workflowEmitPreview}` : undefined,
|
|
380
397
|
`Progress: ${progressLabel}`,
|
|
381
398
|
status.pendingAppends ? `Pending appends: ${status.pendingAppends}` : undefined,
|
|
382
399
|
`Started: ${started}`,
|
|
@@ -400,12 +417,19 @@ export function inspectSubagentStatus(params: RunStatusParams, deps: RunStatusDe
|
|
|
400
417
|
const display = step.label ? `${step.label} (${step.agent})` : step.agent;
|
|
401
418
|
const phase = step.phase ? `[${step.phase}] ` : "";
|
|
402
419
|
lines.push(`${stepLineLabel(status, index)}: ${phase}${display} ${step.status}${modelText}${stepActivityText ? `, ${stepActivityText}` : ""}${steeringSuffix}${acceptanceText}${budgetText}${errorText}`);
|
|
420
|
+
if (step.runner?.type === "external-cli") {
|
|
421
|
+
lines.push(` Runner: external-cli (${step.runner.command}${step.runner.args.length ? ` ${step.runner.args.join(" ")}` : ""})`);
|
|
422
|
+
if (step.externalProcess?.pid !== undefined) lines.push(` Process: ${step.externalProcess.pid}`);
|
|
423
|
+
if (step.externalProcess) lines.push(` Stdout: ${step.externalProcess.stdoutPath}`, ` Stderr: ${step.externalProcess.stderrPath}`);
|
|
424
|
+
}
|
|
403
425
|
lines.push(...formatNestedRunStatusLines(step.children, { indent: " ", commandHints: true, maxLines: 20 }));
|
|
404
426
|
const stepOutputPath = path.join(asyncDir, `output-${index}.log`);
|
|
405
427
|
if (stepOutputPath !== outputPath && fs.existsSync(stepOutputPath)) lines.push(` Output: ${stepOutputPath}`);
|
|
406
|
-
if (step.status === "running") {
|
|
428
|
+
if (step.status === "running" && step.runner?.type !== "external-cli") {
|
|
407
429
|
lines.push(` Intercom target: ${resolveSubagentIntercomTarget(status.runId, step.agent, index)} (if registered)`);
|
|
408
430
|
lines.push(` Steer: subagent({ action: "steer", id: "${status.runId}", index: ${index}, message: "..." })`);
|
|
431
|
+
} else if (step.status === "running" && step.runner?.type === "external-cli") {
|
|
432
|
+
lines.push(" Steer: unavailable; one-shot external CLI runners do not accept live messages.");
|
|
409
433
|
}
|
|
410
434
|
}
|
|
411
435
|
const attached = new Set((status.steps ?? []).flatMap((step) => step.children?.map((child) => child.id) ?? []));
|
|
@@ -413,9 +437,12 @@ export function inspectSubagentStatus(params: RunStatusParams, deps: RunStatusDe
|
|
|
413
437
|
lines.push(...formatNestedRunStatusLines(unattached, { indent: "", commandHints: true, maxLines: 20 }));
|
|
414
438
|
if (nestedWarning) lines.push(`Warning: ${nestedWarning}`);
|
|
415
439
|
if (status.sessionFile) lines.push(`Session: ${status.sessionFile}`);
|
|
416
|
-
|
|
440
|
+
const allExternal = (status.steps?.length ?? 0) > 0 && status.steps!.every((step) => step.runner?.type === "external-cli");
|
|
441
|
+
if (status.state === "running" && !allExternal) lines.push(`Steer running child: subagent({ action: "steer", id: "${status.runId}", message: "..." })`);
|
|
417
442
|
if (status.state !== "running") {
|
|
418
|
-
lines.push(
|
|
443
|
+
lines.push(allExternal
|
|
444
|
+
? "Resume: unavailable; one-shot external CLI runners do not persist sessions."
|
|
445
|
+
: formatCheckpointGuidance(status.runId, status.checkpoint) ?? formatResumeGuidance(status.runId, status.steps ?? [], status.sessionFile, { stopped: status.state === "stopped" || status.stopped === true }));
|
|
419
446
|
}
|
|
420
447
|
if (fs.existsSync(logPath)) lines.push(`Log: ${logPath}`);
|
|
421
448
|
if (fs.existsSync(eventsPath)) lines.push(`Events: ${eventsPath}`);
|