@selesai/code 0.8.5 → 0.8.7
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 +28 -0
- package/dist/core/agent-session.js +13 -1
- package/dist/core/extensions/types.d.ts +2 -0
- package/dist/core/provider-composer.js +17 -4
- package/dist/core/settings-manager.d.ts +2 -0
- package/dist/core/settings-manager.js +3 -0
- package/dist/core/system-prompt.js +2 -8
- package/dist/core/system-prompt.test.js +6 -0
- package/dist/core/tools/index.d.ts +1 -0
- package/dist/core/tools/index.js +1 -0
- package/dist/core/tools/schema-prune.d.ts +16 -0
- package/dist/core/tools/schema-prune.js +39 -0
- package/dist/core/tools/schema-prune.test.d.ts +1 -0
- package/dist/core/tools/schema-prune.test.js +111 -0
- package/dist/defaults/models.json +5 -0
- package/dist/defaults/settings.json +1 -0
- package/dist/extensions/agent-browser.test.ts +178 -2
- package/dist/extensions/agent-browser.ts +2 -0
- package/dist/extensions/copy-turn.test.ts +229 -0
- package/dist/extensions/copy-turn.ts +11 -0
- package/dist/extensions/grep-app/index.test.ts +356 -1
- package/dist/extensions/grep-app/index.ts +6 -1
- package/dist/extensions/handoff-new.test.ts +351 -161
- package/dist/extensions/handoff-new.ts +3 -0
- package/dist/extensions/inline-skills.test.ts +93 -0
- package/dist/extensions/inline-skills.ts +3 -0
- package/dist/extensions/model-prompt-injector/config.json +10 -0
- package/dist/extensions/model-prompt-injector/index.test.ts +112 -0
- package/dist/extensions/model-prompt-injector/index.ts +151 -0
- package/dist/extensions/package.json +1 -0
- package/dist/extensions/pi-subagents/CHANGELOG.md +158 -90
- package/dist/extensions/pi-subagents/UPSTREAM-V0.50-MAPPING.md +172 -0
- package/dist/extensions/pi-subagents/agents/builder.md +5 -2
- package/dist/extensions/pi-subagents/agents/commentator.md +1 -1
- package/dist/extensions/pi-subagents/agents/oracle.md +7 -5
- package/dist/extensions/pi-subagents/agents/reviewer.md +2 -2
- package/dist/extensions/pi-subagents/agents/scout.md +1 -1
- package/dist/extensions/pi-subagents/agents/worker.md +1 -1
- package/dist/extensions/pi-subagents/docs/configuration.md +78 -11
- package/dist/extensions/pi-subagents/docs/extension-api.md +36 -0
- package/dist/extensions/pi-subagents/docs/missions.md +5 -3
- package/dist/extensions/pi-subagents/docs/models.md +1 -1
- package/dist/extensions/pi-subagents/docs/observability.md +42 -2
- package/dist/extensions/pi-subagents/docs/tool-reference.md +20 -3
- package/dist/extensions/pi-subagents/docs/workflows.md +4 -4
- package/dist/extensions/pi-subagents/install.mjs +2 -2
- package/dist/extensions/pi-subagents/package-lock.json +1470 -1472
- package/dist/extensions/pi-subagents/package.json +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +5 -4
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +16 -15
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +5 -5
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +46 -26
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +2 -0
- package/dist/extensions/pi-subagents/src/agents/agents.ts +37 -12
- package/dist/extensions/pi-subagents/src/api/external-runs.ts +174 -84
- package/dist/extensions/pi-subagents/src/api/preflight.ts +13 -7
- package/dist/extensions/pi-subagents/src/extension/config.ts +59 -0
- package/dist/extensions/pi-subagents/src/extension/index.ts +146 -23
- package/dist/extensions/pi-subagents/src/extension/public-execution.ts +34 -6
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +5 -1
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +31 -30
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +10 -9
- package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +13 -8
- package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +16 -3
- package/dist/extensions/pi-subagents/src/inspectors/herdr/project-panes.ts +2 -6
- package/dist/extensions/pi-subagents/src/inspectors/herdr/shell-command.ts +16 -0
- package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +5 -4
- package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +19 -42
- package/dist/extensions/pi-subagents/src/missions/goal-driver.ts +3 -1
- package/dist/extensions/pi-subagents/src/missions/store.ts +8 -3
- package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +82 -25
- package/dist/extensions/pi-subagents/src/runs/background/active-run-index.ts +71 -1
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +73 -43
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +17 -6
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +14 -6
- package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +277 -0
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +11 -3
- package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/background/completion-replay.ts +11 -1
- package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +21 -6
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +5 -2
- package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +437 -0
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +224 -42
- package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +27 -7
- package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +76 -19
- package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +35 -26
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +108 -9
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +54 -28
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +27 -13
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +298 -33
- package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +2 -0
- package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +5 -2
- package/dist/extensions/pi-subagents/src/runs/background/wait-subscriptions.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/async-dismiss-action.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +16 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +219 -15
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +7 -4
- package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +4 -3
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +368 -50
- package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +107 -1
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +4 -0
- package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +39 -23
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +16 -2
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +66 -62
- package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +376 -0
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +2 -0
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +15 -0
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +1 -9
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +12 -0
- package/dist/extensions/pi-subagents/src/runs/shared/tool-timeout.ts +95 -0
- package/dist/extensions/pi-subagents/src/shared/agent-stream-options.ts +5 -0
- package/dist/extensions/pi-subagents/src/shared/artifacts.ts +0 -4
- package/dist/extensions/pi-subagents/src/shared/display-text.ts +50 -0
- package/dist/extensions/pi-subagents/src/shared/node-executable.ts +21 -0
- package/dist/extensions/pi-subagents/src/shared/session-lineage.ts +71 -0
- package/dist/extensions/pi-subagents/src/shared/types.ts +66 -4
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +34 -25
- package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +4 -0
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +160 -45
- package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +1 -48
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +129 -17
- package/dist/extensions/pi-subagents/src/tui/render.ts +122 -44
- package/dist/extensions/pi-subagents/src/watchdog/permission-arbiter.ts +2 -1
- package/dist/extensions/pi-subagents/src/watchdog/review.ts +4 -3
- package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +10 -2
- package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +272 -76
- package/dist/extensions/pi-subagents/src/workflows/workflow-auto-relaunch.ts +28 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/types.d.ts +2 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +68 -9
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +27 -1
- package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +49 -0
- package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +26 -1
- package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +144 -0
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +26 -0
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +369 -98
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +111 -78
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +49 -1
- package/dist/extensions/pi-subagents/test/integration/slash-live-state.test.ts +12 -0
- package/dist/extensions/pi-subagents/test/support/node-command.ts +15 -0
- package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +50 -0
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +28 -0
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +61 -0
- package/dist/extensions/pi-subagents/test/unit/agent-stream-options.test.ts +14 -0
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +76 -0
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +2 -0
- package/dist/extensions/pi-subagents/test/unit/async-status-snapshot.test.ts +162 -0
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +209 -10
- package/dist/extensions/pi-subagents/test/unit/completion-replay.test.ts +41 -1
- package/dist/extensions/pi-subagents/test/unit/external-runs.test.ts +135 -42
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +252 -1
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +192 -6
- package/dist/extensions/pi-subagents/test/unit/handoff-adoption.test.ts +103 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-inspector-bootstrap.test.ts +32 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +59 -0
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +91 -0
- package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +23 -4
- package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +56 -1
- package/dist/extensions/pi-subagents/test/unit/mission-goal-driver.test.ts +67 -3
- package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +14 -0
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +18 -0
- package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +25 -2
- package/dist/extensions/pi-subagents/test/unit/node-executable.test.ts +26 -0
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +348 -0
- package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +5 -2
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +6 -1
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +92 -0
- package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +175 -0
- package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +127 -17
- package/dist/extensions/pi-subagents/test/unit/run-id-resolver.test.ts +44 -0
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +247 -0
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +107 -2
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +5 -8
- package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +456 -4
- package/dist/extensions/pi-subagents/test/unit/session-lineage.test.ts +73 -0
- package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +128 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +28 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +16 -7
- package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +15 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +79 -15
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +12 -12
- package/dist/extensions/pi-subagents/test/unit/tool-timeout.test.ts +109 -0
- package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-auto-relaunch.test.ts +45 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +94 -1
- package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +42 -2
- package/dist/extensions/ponytail/index.js +11 -0
- package/dist/extensions/ponytail/ponytail-config.cjs +2 -0
- package/dist/extensions/ponytail/ponytail-instructions.cjs +6 -0
- package/dist/extensions/ponytail/test/extension.test.js +274 -140
- package/dist/extensions/ponytail/test/helpers.test.js +280 -92
- package/dist/extensions/question/index.ts +33 -0
- package/dist/extensions/question/question-list.ts +28 -0
- package/dist/extensions/question/row-layout.ts +3 -0
- package/dist/extensions/question/tests/batch.test.ts +103 -65
- package/dist/extensions/question/tests/exp.test.ts +70 -0
- package/dist/extensions/question/tests/exp2.test.ts +59 -0
- package/dist/extensions/question/tests/exp3.test.ts +47 -0
- package/dist/extensions/question/tests/helpers.test.ts +75 -35
- package/dist/extensions/question/tests/question-list.test.ts +640 -198
- package/dist/extensions/question/tests/row-layout.test.ts +193 -114
- package/dist/extensions/question/tests/schemas.test.ts +42 -19
- package/dist/extensions/question/tests/selection-mode.test.ts +54 -0
- package/dist/extensions/question/tests/shortcuts.test.ts +106 -84
- package/dist/extensions/question/tests/wizard.test.ts +771 -50
- package/dist/extensions/question/tests/zz-ig3.test.ts +20 -0
- package/dist/extensions/question/tests/zz-probe.test.ts +29 -0
- package/dist/extensions/rtk.test.ts +180 -1
- package/dist/extensions/tokenin-onboarding.ts +3 -0
- package/dist/extensions/undo.test.ts +720 -0
- package/dist/extensions/undo.ts +6 -0
- package/dist/extensions/web-agent-onboarding.test.ts +415 -0
- package/dist/extensions/workflow/extension.ts +3 -3
- package/dist/extensions/workflow/modes.ts +41 -19
- package/dist/skills/pi-subagents/SKILL.md +1 -1
- package/dist/skills/pi-subagents/references/constraints-and-recipes.md +5 -4
- package/dist/skills/pi-subagents/references/execution-controls.md +16 -15
- package/dist/skills/pi-subagents/references/management-authoring-rpc.md +5 -5
- package/dist/skills/pi-subagents/references/prompting-and-roles.md +46 -26
- package/docs/plans/workflow-autoloop-reference.md +1 -2
- package/docs/plans/workflow-handoff-carryover.md +108 -0
- package/docs/settings.md +6 -0
- package/package.json +4 -1
|
@@ -3,6 +3,7 @@ import * as path from "node:path";
|
|
|
3
3
|
import type { AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
4
4
|
import { getMarkdownTheme, type ExtensionContext } from "@selesai/code";
|
|
5
5
|
import { matchesKey, truncateToWidth, visibleWidth, wrapTextWithAnsi, type Component, type MarkdownTheme } from "@earendil-works/pi-tui";
|
|
6
|
+
import { snapshotExternalRuns, type ExternalRun } from "../api/external-runs.ts";
|
|
6
7
|
import { getArtifactPaths, getArtifactsDir } from "../shared/artifacts.ts";
|
|
7
8
|
import { formatDuration, formatModelThinking, formatTokens, shortenPath } from "../shared/formatters.ts";
|
|
8
9
|
import { DIRS, type AsyncJobState, type Details, type FleetKeybindingAction, type FleetKeybindingsConfig, type ForegroundChildControl, type ForegroundResumeChild, type ForegroundResumeRun, type ForegroundRunControl, type SubagentState } from "../shared/types.ts";
|
|
@@ -20,6 +21,7 @@ import { handleHerdrInspectorAction } from "../inspectors/herdr/actions.ts";
|
|
|
20
21
|
import { getLivePromptAudit, type LivePromptAudit, type PromptAuditView } from "../runs/foreground/prompt-audit.ts";
|
|
21
22
|
|
|
22
23
|
const REFRESH_MS = 750;
|
|
24
|
+
const MIN_REFRESH_MS = 250;
|
|
23
25
|
const MAX_RECENT_ASYNC_RUNS = 20;
|
|
24
26
|
const MAX_FLEET_HISTORY_CANDIDATES = 100;
|
|
25
27
|
const TRANSCRIPT_LINES = 200;
|
|
@@ -77,6 +79,7 @@ export type FleetItem = (
|
|
|
77
79
|
| { key: string; kind: "foreground-active"; runId: string; index?: number; agent: string; state: "running"; updatedAt: number; control: ForegroundRunControl; activeChild?: ForegroundChildControl }
|
|
78
80
|
| { key: string; kind: "foreground-recent"; runId: string; index: number; agent: string; state: ForegroundResumeChild["status"]; updatedAt: number; run: ForegroundResumeRun; child: ForegroundResumeChild }
|
|
79
81
|
| { key: string; kind: "async"; runId: string; index?: number; agent: string; state: string; updatedAt: number; run: AsyncRunSummary; step?: AsyncStep }
|
|
82
|
+
| { key: string; kind: "external"; runId: string; agent: string; state: ExternalRun["state"]; updatedAt: number; run: ExternalRun }
|
|
80
83
|
) & { description?: string };
|
|
81
84
|
|
|
82
85
|
export interface FleetSnapshot {
|
|
@@ -186,8 +189,13 @@ export function collectFleetSnapshot(
|
|
|
186
189
|
): FleetSnapshot {
|
|
187
190
|
const items: FleetItem[] = [];
|
|
188
191
|
const activeForegroundIds = new Set<string>();
|
|
192
|
+
const trackedJobs = state.fleetJobs ?? state.asyncJobs;
|
|
193
|
+
const workflowParentIds = new Set([...trackedJobs.values()]
|
|
194
|
+
.filter((job) => job.mode === "workflow" && belongsToCurrentSession(job.sessionId, state.currentSessionId))
|
|
195
|
+
.map((job) => job.asyncId));
|
|
189
196
|
for (const control of [...state.foregroundControls.values()].sort((left, right) => right.updatedAt - left.updatedAt)) {
|
|
190
197
|
activeForegroundIds.add(control.runId);
|
|
198
|
+
if (control.parentWorkflowRunId && workflowParentIds.has(control.parentWorkflowRunId)) continue;
|
|
191
199
|
if (control.activeChildren) {
|
|
192
200
|
for (const child of [...control.activeChildren.values()].sort((left, right) => left.index - right.index)) {
|
|
193
201
|
items.push({
|
|
@@ -222,7 +230,7 @@ export function collectFleetSnapshot(
|
|
|
222
230
|
try {
|
|
223
231
|
let runs: AsyncRunSummary[];
|
|
224
232
|
const descriptions = new Map<string, string>();
|
|
225
|
-
const tracked = [...
|
|
233
|
+
const tracked = [...trackedJobs.values()]
|
|
226
234
|
.filter((job) => belongsToCurrentSession(job.sessionId, state.currentSessionId));
|
|
227
235
|
const byUpdate = (left: AsyncJobState, right: AsyncJobState) => (right.updatedAt ?? right.startedAt ?? 0) - (left.updatedAt ?? left.startedAt ?? 0);
|
|
228
236
|
const active = tracked.filter((job) => job.status === "queued" || job.status === "running").sort(byUpdate);
|
|
@@ -239,7 +247,7 @@ export function collectFleetSnapshot(
|
|
|
239
247
|
if (options.asyncDirRoot !== undefined) {
|
|
240
248
|
const trackedIds = new Set(trackedRuns.map((run) => run.id));
|
|
241
249
|
const history = listAsyncRuns(options.asyncDirRoot, {
|
|
242
|
-
...(state.currentSessionId ? { sessionId: state.currentSessionId } : {}),
|
|
250
|
+
...(state.sessionLineage?.length ? { sessionIds: state.sessionLineage } : state.currentSessionId ? { sessionId: state.currentSessionId } : {}),
|
|
243
251
|
entryLimit: MAX_FLEET_HISTORY_CANDIDATES,
|
|
244
252
|
resultsDir: options.resultsDir ?? DIRS.results,
|
|
245
253
|
reconcile: false,
|
|
@@ -255,6 +263,26 @@ export function collectFleetSnapshot(
|
|
|
255
263
|
error = cause instanceof Error ? cause.message : String(cause);
|
|
256
264
|
}
|
|
257
265
|
|
|
266
|
+
if (state.currentSessionId) {
|
|
267
|
+
try {
|
|
268
|
+
for (const run of snapshotExternalRuns(state.currentSessionId, { ignoreMalformed: true, onMalformedRecord: (message) => console.warn(`[pi-subagents] Removed ${message}`) })) {
|
|
269
|
+
items.push({
|
|
270
|
+
key: `external:${run.id}`,
|
|
271
|
+
kind: "external",
|
|
272
|
+
runId: run.id,
|
|
273
|
+
agent: run.label,
|
|
274
|
+
state: run.state,
|
|
275
|
+
updatedAt: run.updatedAt ?? run.endedAt ?? run.startedAt,
|
|
276
|
+
run,
|
|
277
|
+
...(run.currentAction ? { description: run.currentAction } : {}),
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
} catch (cause) {
|
|
281
|
+
const message = `Failed to inspect external jobs: ${cause instanceof Error ? cause.message : String(cause)}`;
|
|
282
|
+
error = error ? `${error}; ${message}` : message;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
258
286
|
const recentForeground = [...(state.foregroundRuns?.values() ?? [])]
|
|
259
287
|
.filter((run) => belongsToCurrentSession(run.sessionId, state.currentSessionId) && !activeForegroundIds.has(run.runId))
|
|
260
288
|
.sort((left, right) => right.updatedAt - left.updatedAt);
|
|
@@ -276,6 +304,27 @@ export function collectFleetSnapshot(
|
|
|
276
304
|
return { items, ...(error ? { error } : {}) };
|
|
277
305
|
}
|
|
278
306
|
|
|
307
|
+
function visibleWorkflowParentKeyForForegroundKey(state: SubagentState, key: string, items: FleetItem[]): string | undefined {
|
|
308
|
+
for (const control of state.foregroundControls.values()) {
|
|
309
|
+
if (!control.parentWorkflowRunId) continue;
|
|
310
|
+
let matches = false;
|
|
311
|
+
if (control.activeChildren) {
|
|
312
|
+
for (const child of control.activeChildren.values()) {
|
|
313
|
+
if (`foreground-active:${control.runId}:${child.index}` === key) {
|
|
314
|
+
matches = true;
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
} else {
|
|
319
|
+
matches = `foreground-active:${control.runId}:${control.currentIndex ?? 0}` === key;
|
|
320
|
+
}
|
|
321
|
+
if (!matches) continue;
|
|
322
|
+
const parentKey = `async:${control.parentWorkflowRunId}`;
|
|
323
|
+
return items.some((item) => item.key === parentKey) ? parentKey : undefined;
|
|
324
|
+
}
|
|
325
|
+
return undefined;
|
|
326
|
+
}
|
|
327
|
+
|
|
279
328
|
function statusGlyph(item: FleetItem, theme: Theme): string {
|
|
280
329
|
if (item.state === "running") return theme.fg("accent", "●");
|
|
281
330
|
if (item.state === "queued" || item.state === "pending") return theme.fg("muted", "◦");
|
|
@@ -424,6 +473,11 @@ function foregroundRecentDetail(item: Extract<FleetItem, { kind: "foreground-rec
|
|
|
424
473
|
return lines.filter((line): line is string => line !== undefined);
|
|
425
474
|
}
|
|
426
475
|
|
|
476
|
+
function externalElapsedEnd(run: ExternalRun): number {
|
|
477
|
+
const terminal = run.state !== "queued" && run.state !== "running";
|
|
478
|
+
return terminal ? (run.endedAt ?? run.updatedAt ?? Date.now()) : Date.now();
|
|
479
|
+
}
|
|
480
|
+
|
|
427
481
|
function asyncDetail(item: Extract<FleetItem, { kind: "async" }>): string[] {
|
|
428
482
|
const status = readStatus(item.run.asyncDir);
|
|
429
483
|
if (status) {
|
|
@@ -444,13 +498,36 @@ function asyncDetail(item: Extract<FleetItem, { kind: "async" }>): string[] {
|
|
|
444
498
|
].filter((line): line is string => line !== undefined);
|
|
445
499
|
}
|
|
446
500
|
|
|
501
|
+
function externalDetail(item: Extract<FleetItem, { kind: "external" }>): string[] {
|
|
502
|
+
return [
|
|
503
|
+
`Run: ${item.runId}`,
|
|
504
|
+
"Source: external · display-only",
|
|
505
|
+
`Owner: ${item.run.source}`,
|
|
506
|
+
`State: ${item.state}`,
|
|
507
|
+
`Started: ${new Date(item.run.startedAt).toISOString()}`,
|
|
508
|
+
item.run.updatedAt !== undefined ? `Updated: ${new Date(item.run.updatedAt).toISOString()}` : undefined,
|
|
509
|
+
item.run.endedAt !== undefined ? `Ended: ${new Date(item.run.endedAt).toISOString()}` : undefined,
|
|
510
|
+
`Elapsed: ${formatDuration(Math.max(0, externalElapsedEnd(item.run) - item.run.startedAt))}`,
|
|
511
|
+
item.run.currentAction ? `Current action: ${item.run.currentAction}` : undefined,
|
|
512
|
+
item.run.reportPath ? `Report path: ${item.run.reportPath}` : undefined,
|
|
513
|
+
item.run.transcriptPath ? `Transcript path: ${item.run.transcriptPath}` : undefined,
|
|
514
|
+
"",
|
|
515
|
+
"Preview",
|
|
516
|
+
item.run.preview ?? "(no preview supplied)",
|
|
517
|
+
"",
|
|
518
|
+
"The owning extension controls execution, persistence, cancellation, and results.",
|
|
519
|
+
].filter((line): line is string => line !== undefined);
|
|
520
|
+
}
|
|
521
|
+
|
|
447
522
|
function detailLines(item: FleetItem | undefined, error: string | undefined, state: SubagentState): string[] {
|
|
448
|
-
if (!item) return [error ? `Fleet scan failed: ${error}` : "No current-session
|
|
523
|
+
if (!item) return [error ? `Fleet scan failed: ${error}` : "No current-session Fleet jobs.", "", "New jobs appear here automatically while this inspector remains open."];
|
|
449
524
|
const lines = item.kind === "foreground-active"
|
|
450
525
|
? foregroundActiveDetail(item, state)
|
|
451
526
|
: item.kind === "foreground-recent"
|
|
452
527
|
? foregroundRecentDetail(item, state)
|
|
453
|
-
:
|
|
528
|
+
: item.kind === "external"
|
|
529
|
+
? externalDetail(item)
|
|
530
|
+
: asyncDetail(item);
|
|
454
531
|
if (error) lines.unshift(`Fleet scan warning: ${error}`, "");
|
|
455
532
|
return lines;
|
|
456
533
|
}
|
|
@@ -473,11 +550,12 @@ function fleetArtifactsRoot(state: SubagentState, cwd: string): string {
|
|
|
473
550
|
return getArtifactsDir(
|
|
474
551
|
state.parentSessionFile ?? null,
|
|
475
552
|
cwd,
|
|
476
|
-
state.artifactDirPreference
|
|
553
|
+
state.artifactDirPreference,
|
|
477
554
|
);
|
|
478
555
|
}
|
|
479
556
|
|
|
480
557
|
function transcriptTarget(item: FleetItem, state: SubagentState): { path: string; trustedRoots: string[] } | undefined {
|
|
558
|
+
if (item.kind === "external") return undefined;
|
|
481
559
|
if (item.kind === "foreground-active") {
|
|
482
560
|
const artifactsRoot = fleetArtifactsRoot(state, item.control.cwd ?? state.baseCwd);
|
|
483
561
|
return {
|
|
@@ -510,6 +588,7 @@ function transcriptTarget(item: FleetItem, state: SubagentState): { path: string
|
|
|
510
588
|
item.run.asyncDir,
|
|
511
589
|
fleetArtifactsRoot(state, state.baseCwd),
|
|
512
590
|
trackedJob?.cwd ? fleetArtifactsRoot(state, trackedJob.cwd) : undefined,
|
|
591
|
+
item.run.sessionFile ? getArtifactsDir(item.run.sessionFile, item.run.cwd ?? state.baseCwd, state.artifactDirPreference) : undefined,
|
|
513
592
|
]),
|
|
514
593
|
};
|
|
515
594
|
}
|
|
@@ -521,10 +600,12 @@ function itemContext(item: FleetItem): string | undefined {
|
|
|
521
600
|
}
|
|
522
601
|
|
|
523
602
|
function itemMode(item: FleetItem): string {
|
|
603
|
+
if (item.kind === "external") return "display-only";
|
|
524
604
|
return item.kind === "foreground-active" ? item.control.mode : item.run.mode;
|
|
525
605
|
}
|
|
526
606
|
|
|
527
607
|
function itemSource(item: FleetItem): string {
|
|
608
|
+
if (item.kind === "external") return `external · ${item.run.source}`;
|
|
528
609
|
if (item.kind === "async") return "background";
|
|
529
610
|
return item.kind === "foreground-active" ? "foreground · live" : "foreground · recent";
|
|
530
611
|
}
|
|
@@ -544,6 +625,8 @@ function itemStats(item: FleetItem): string[] {
|
|
|
544
625
|
model = formatModelThinking(item.child.model, item.child.thinking) || undefined;
|
|
545
626
|
tokens = item.child.tokens;
|
|
546
627
|
tools = item.child.toolCount;
|
|
628
|
+
} else if (item.kind === "external") {
|
|
629
|
+
durationMs = Math.max(0, externalElapsedEnd(item.run) - item.run.startedAt);
|
|
547
630
|
} else {
|
|
548
631
|
model = formatModelThinking(item.step?.model, item.step?.thinking) || undefined;
|
|
549
632
|
tokens = item.step?.tokens?.total ?? (item.index === undefined ? item.run.totalTokens?.total : undefined);
|
|
@@ -563,7 +646,7 @@ function itemStats(item: FleetItem): string[] {
|
|
|
563
646
|
function structuredHeader(item: FleetItem, width: number, theme: Theme, conversationState: string, promptSummary?: string): string[] {
|
|
564
647
|
const lines: string[] = [];
|
|
565
648
|
lines.push(rightAligned(` ${statusGlyph(item, theme)} ${theme.bold(item.agent)}`, theme.fg("dim", item.state), width));
|
|
566
|
-
const child = item.index !== undefined ? ` · child ${item.index + 1}` : "";
|
|
649
|
+
const child = "index" in item && item.index !== undefined ? ` · child ${item.index + 1}` : "";
|
|
567
650
|
const context = itemContext(item);
|
|
568
651
|
const identity = `${itemSource(item)} · ${item.runId.slice(0, 8)}${child} · ${itemMode(item)}${context ? ` ${context}` : ""}`;
|
|
569
652
|
lines.push(` ${theme.fg("dim", identity)}`);
|
|
@@ -628,7 +711,8 @@ export class SubagentFleetComponent implements Component {
|
|
|
628
711
|
private actionBusy = false;
|
|
629
712
|
private transcriptCache: FleetTranscriptCache | undefined;
|
|
630
713
|
private disposed = false;
|
|
631
|
-
private
|
|
714
|
+
private refreshTimer: ReturnType<typeof setTimeout> | undefined;
|
|
715
|
+
private readonly refreshMs: number;
|
|
632
716
|
private readonly tui: FleetTui;
|
|
633
717
|
private readonly theme: Theme;
|
|
634
718
|
private readonly markdownTheme: MarkdownTheme;
|
|
@@ -651,20 +735,41 @@ export class SubagentFleetComponent implements Component {
|
|
|
651
735
|
this.done = done;
|
|
652
736
|
this.options = options;
|
|
653
737
|
this.keybindings = resolveFleetKeybindings(options.fleetKeybindings);
|
|
738
|
+
this.refreshMs = Math.max(MIN_REFRESH_MS, options.refreshMs ?? REFRESH_MS);
|
|
654
739
|
this.selectedKey = options.initialKey;
|
|
655
740
|
this.refresh();
|
|
656
|
-
this.
|
|
741
|
+
this.scheduleRefresh();
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
private scheduleRefresh(): void {
|
|
745
|
+
if (this.disposed || this.refreshTimer) return;
|
|
746
|
+
this.refreshTimer = setTimeout(() => {
|
|
747
|
+
this.refreshTimer = undefined;
|
|
657
748
|
if (this.disposed) return;
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
749
|
+
try {
|
|
750
|
+
this.invalidate();
|
|
751
|
+
this.tui.requestRender();
|
|
752
|
+
} finally {
|
|
753
|
+
this.scheduleRefresh();
|
|
754
|
+
}
|
|
755
|
+
}, this.refreshMs);
|
|
756
|
+
this.refreshTimer.unref?.();
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
private stopRefresh(): void {
|
|
760
|
+
this.disposed = true;
|
|
761
|
+
if (this.refreshTimer) clearTimeout(this.refreshTimer);
|
|
762
|
+
this.refreshTimer = undefined;
|
|
662
763
|
}
|
|
663
764
|
|
|
664
765
|
private refresh(): void {
|
|
665
766
|
const previousKey = this.snapshot.items[this.selected]?.key ?? this.selectedKey;
|
|
666
767
|
this.snapshot = collectFleetSnapshot(this.state, this.options);
|
|
667
|
-
|
|
768
|
+
let preserved = previousKey ? this.snapshot.items.findIndex((item) => item.key === previousKey) : -1;
|
|
769
|
+
if (preserved < 0 && previousKey) {
|
|
770
|
+
const parentKey = visibleWorkflowParentKeyForForegroundKey(this.state, previousKey, this.snapshot.items);
|
|
771
|
+
if (parentKey) preserved = this.snapshot.items.findIndex((item) => item.key === parentKey);
|
|
772
|
+
}
|
|
668
773
|
this.selected = preserved >= 0 ? preserved : Math.min(this.selected, Math.max(0, this.snapshot.items.length - 1));
|
|
669
774
|
this.selectedKey = this.snapshot.items[this.selected]?.key;
|
|
670
775
|
}
|
|
@@ -724,6 +829,7 @@ export class SubagentFleetComponent implements Component {
|
|
|
724
829
|
private selectedAsyncAction(): { item: Extract<FleetItem, { kind: "async" }> } | { reason: string } {
|
|
725
830
|
const item = this.snapshot.items[this.selected];
|
|
726
831
|
if (!item) return { reason: "No child is selected." };
|
|
832
|
+
if (item.kind === "external") return { reason: "External jobs are display-only and remain controlled by their owning extension." };
|
|
727
833
|
if (item.kind !== "async") return { reason: "Fleet controls are available for current-session top-level async runs only." };
|
|
728
834
|
if (!isActionableAsyncState(item.run.state) || !isActionableAsyncState(item.state)) return { reason: `Selected child is ${item.state}; controls require a running or queued async child.` };
|
|
729
835
|
return { item };
|
|
@@ -732,6 +838,7 @@ export class SubagentFleetComponent implements Component {
|
|
|
732
838
|
private selectedHerdrInspectAction(): { runId: string; asyncDir: string; index?: number } | { reason: string } {
|
|
733
839
|
const item = this.snapshot.items[this.selected];
|
|
734
840
|
if (!item) return { reason: "No child is selected." };
|
|
841
|
+
if (item.kind === "external") return { reason: "External jobs are display-only and have no Herdr controls." };
|
|
735
842
|
if (item.kind === "async") {
|
|
736
843
|
if (!isActionableAsyncState(item.run.state) || !isActionableAsyncState(item.state)) return { reason: `Selected child is ${item.state}; controls require a running or queued async child.` };
|
|
737
844
|
return { runId: item.runId, asyncDir: item.run.asyncDir, ...(item.index !== undefined ? { index: item.index } : {}) };
|
|
@@ -927,6 +1034,7 @@ export class SubagentFleetComponent implements Component {
|
|
|
927
1034
|
return;
|
|
928
1035
|
}
|
|
929
1036
|
if (matchesFleetAction(data, this.keybindings, "close")) {
|
|
1037
|
+
this.stopRefresh();
|
|
930
1038
|
this.done(undefined);
|
|
931
1039
|
return;
|
|
932
1040
|
}
|
|
@@ -1116,7 +1224,9 @@ export class SubagentFleetComponent implements Component {
|
|
|
1116
1224
|
];
|
|
1117
1225
|
const lines = [this.theme.fg("border", `╭${"─".repeat(innerWidth)}╮`)];
|
|
1118
1226
|
const selected = this.snapshot.items[this.selected];
|
|
1119
|
-
const title =
|
|
1227
|
+
const title = selected?.kind === "external"
|
|
1228
|
+
? ` ${this.theme.bold("Fleet inspector")} ${this.theme.fg("dim", "· external display-only")}`
|
|
1229
|
+
: ` ${this.theme.bold("Subagent fleet inspector")} ${this.theme.fg("dim", "· live controls")}`;
|
|
1120
1230
|
const selectedStatus = selected
|
|
1121
1231
|
? `${statusGlyph(selected, this.theme)} ${selected.agent} · ${selected.state} `
|
|
1122
1232
|
: this.theme.fg("dim", "no children ");
|
|
@@ -1135,7 +1245,9 @@ export class SubagentFleetComponent implements Component {
|
|
|
1135
1245
|
const position = this.snapshot.items.length ? `${this.selected + 1}/${this.snapshot.items.length}` : "0/0";
|
|
1136
1246
|
const footer = this.promptAuditOpen
|
|
1137
1247
|
? ` j/k child · 1/2/3 view · g redo with guidance · c copy · Esc close Prompt Audit · ${position}`
|
|
1138
|
-
:
|
|
1248
|
+
: selected?.kind === "external"
|
|
1249
|
+
? ` ${bindingLabel(this.keybindings, "selectUp")}/${bindingLabel(this.keybindings, "selectDown")} job · display-only · ${bindingLabel(this.keybindings, "refresh")} refresh · ${bindingLabel(this.keybindings, "close")} close · ${position}`
|
|
1250
|
+
: ` ${bindingLabel(this.keybindings, "selectUp")}/${bindingLabel(this.keybindings, "selectDown")} agent · p Prompt Audit · ${bindingLabel(this.keybindings, "inspect")} Herdr · ${bindingLabel(this.keybindings, "steer")} steer · ${bindingLabel(this.keybindings, "stop")} stop · ${bindingLabel(this.keybindings, "toggleTools")} tools · ${bindingLabel(this.keybindings, "refresh")} refresh · ${bindingLabel(this.keybindings, "close")} close · ${position}`;
|
|
1139
1251
|
lines.push(this.theme.fg("border", "│") + fit(this.theme.fg("dim", footer), innerWidth) + this.theme.fg("border", "│"));
|
|
1140
1252
|
lines.push(this.theme.fg("border", `╰${"─".repeat(innerWidth)}╯`));
|
|
1141
1253
|
return lines.map((line) => truncateToWidth(line, width));
|
|
@@ -1147,8 +1259,7 @@ export class SubagentFleetComponent implements Component {
|
|
|
1147
1259
|
}
|
|
1148
1260
|
|
|
1149
1261
|
dispose(): void {
|
|
1150
|
-
this.
|
|
1151
|
-
clearInterval(this.timer);
|
|
1262
|
+
this.stopRefresh();
|
|
1152
1263
|
}
|
|
1153
1264
|
}
|
|
1154
1265
|
|
|
@@ -1178,6 +1289,7 @@ export async function openSubagentFleet(ctx: ExtensionContext, state: SubagentSt
|
|
|
1178
1289
|
...(input.index !== undefined ? { index: input.index } : {}),
|
|
1179
1290
|
}, {
|
|
1180
1291
|
state,
|
|
1292
|
+
sessionRoots: state.trustedSessionRoots,
|
|
1181
1293
|
cwd: state.baseCwd,
|
|
1182
1294
|
...(state.authorityPolicy ? { authorityPolicy: state.authorityPolicy } : {}),
|
|
1183
1295
|
...(state.missionStoreConfig ? { missions: state.missionStoreConfig } : {}),
|