@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
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { ExtensionContext } from "@selesai/code";
|
|
2
2
|
import { type EditorComponent, isKeyRelease, Key, matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
3
|
+
import { snapshotExternalRuns } from "../api/external-runs.ts";
|
|
3
4
|
import { formatModelThinking } from "../shared/formatters.ts";
|
|
4
5
|
import type { AsyncJobStep, FleetViewPlacement, NestedRunSummary, NestedStepSummary, SubagentState } from "../shared/types.ts";
|
|
5
6
|
import { formatWorkflowJsonPreview } from "../workflows/scripted-workflow.ts";
|
|
6
7
|
|
|
7
8
|
export const FLEET_STATUS_WIDGET_KEY = "subagent-fleet-status";
|
|
8
9
|
|
|
9
|
-
// Six rows fit the accepted collapsed hierarchy: one owner, four
|
|
10
|
+
// Six rows fit the accepted collapsed hierarchy: one owner, four visible descendants, and overflow.
|
|
10
11
|
const MAX_AGENT_ROWS = 6;
|
|
11
12
|
const REFRESH_MS = 500;
|
|
12
13
|
|
|
@@ -16,12 +17,15 @@ type FleetStatusTui = {
|
|
|
16
17
|
};
|
|
17
18
|
type FleetStatusEntry = {
|
|
18
19
|
key: string;
|
|
20
|
+
parentKey?: string;
|
|
21
|
+
workflowWrapper?: boolean;
|
|
19
22
|
agent: string;
|
|
20
23
|
modelThinking?: string;
|
|
21
24
|
description?: string;
|
|
22
25
|
startedAt: number;
|
|
23
26
|
tokens: number;
|
|
24
27
|
state: string;
|
|
28
|
+
external?: true;
|
|
25
29
|
nestedChildren?: NestedRunSummary[];
|
|
26
30
|
};
|
|
27
31
|
|
|
@@ -31,11 +35,13 @@ type FleetNestedRow = {
|
|
|
31
35
|
modelThinking?: string;
|
|
32
36
|
activity?: string;
|
|
33
37
|
startedAt?: number;
|
|
38
|
+
depth: number;
|
|
34
39
|
overflow?: number;
|
|
35
40
|
};
|
|
36
41
|
|
|
37
42
|
type FleetTreeRow =
|
|
38
43
|
| { kind: "owner"; entry: FleetStatusEntry }
|
|
44
|
+
| { kind: "child"; entry: FleetStatusEntry; last: boolean }
|
|
39
45
|
| { kind: "nested"; ownerKey: string; row: FleetNestedRow; last: boolean };
|
|
40
46
|
|
|
41
47
|
export interface FleetStatusOptions {
|
|
@@ -94,44 +100,112 @@ function nestedStatusGlyph(state: FleetNestedRow["state"], theme: Theme): string
|
|
|
94
100
|
return theme.fg("warning", "■");
|
|
95
101
|
}
|
|
96
102
|
|
|
97
|
-
function
|
|
98
|
-
|
|
99
|
-
for (
|
|
103
|
+
function nestedStepDisplayCount(steps: NestedStepSummary[] | undefined, start = 0): number {
|
|
104
|
+
let count = 0;
|
|
105
|
+
for (let index = start; index < (steps?.length ?? 0); index++) {
|
|
106
|
+
count += 1 + nestedDisplayCount(steps![index]!.children);
|
|
107
|
+
}
|
|
108
|
+
return count;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function nestedDisplayCount(children: NestedRunSummary[] | undefined, start = 0): number {
|
|
112
|
+
let count = 0;
|
|
113
|
+
for (let index = start; index < (children?.length ?? 0); index++) {
|
|
114
|
+
const child = children![index]!;
|
|
100
115
|
const steps = (child.mode === "parallel" || child.mode === "chain") ? child.steps ?? [] : [];
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
116
|
+
count += steps.length > 0 ? nestedStepDisplayCount(steps) : 1;
|
|
117
|
+
count += nestedDisplayCount(child.children);
|
|
118
|
+
}
|
|
119
|
+
return count;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function nestedFleetRows(children: NestedRunSummary[] | undefined, visibleLimit: number): FleetNestedRow[] {
|
|
123
|
+
const rows: FleetNestedRow[] = [];
|
|
124
|
+
let omitted = 0;
|
|
125
|
+
const appendRuns = (runs: NestedRunSummary[] | undefined, depth: number): boolean => {
|
|
126
|
+
for (let runIndex = 0; runIndex < (runs?.length ?? 0); runIndex++) {
|
|
127
|
+
const child = runs![runIndex]!;
|
|
128
|
+
const steps = (child.mode === "parallel" || child.mode === "chain") ? child.steps ?? [] : [];
|
|
129
|
+
if (steps.length > 0) {
|
|
130
|
+
for (let stepIndex = 0; stepIndex < steps.length; stepIndex++) {
|
|
131
|
+
if (rows.length >= visibleLimit) {
|
|
132
|
+
omitted += nestedStepDisplayCount(steps, stepIndex);
|
|
133
|
+
omitted += nestedDisplayCount(child.children);
|
|
134
|
+
omitted += nestedDisplayCount(runs, runIndex + 1);
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
const step = steps[stepIndex]!;
|
|
138
|
+
const modelThinking = formatModelThinking(step.model, step.thinking) || undefined;
|
|
139
|
+
const activity = nestedActivity(step);
|
|
140
|
+
rows.push({
|
|
141
|
+
name: step.agent,
|
|
142
|
+
state: step.status,
|
|
143
|
+
depth,
|
|
144
|
+
...(modelThinking ? { modelThinking } : {}),
|
|
145
|
+
...(activity ? { activity } : {}),
|
|
146
|
+
...(step.startedAt !== undefined ? { startedAt: step.startedAt } : {}),
|
|
147
|
+
});
|
|
148
|
+
if (!appendRuns(step.children, depth + 1)) {
|
|
149
|
+
omitted += nestedStepDisplayCount(steps, stepIndex + 1);
|
|
150
|
+
omitted += nestedDisplayCount(child.children);
|
|
151
|
+
omitted += nestedDisplayCount(runs, runIndex + 1);
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
if (rows.length >= visibleLimit) {
|
|
157
|
+
omitted += nestedDisplayCount(runs, runIndex);
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
const modelThinking = formatModelThinking(child.model, child.thinking) || undefined;
|
|
161
|
+
const activity = nestedActivity(child);
|
|
105
162
|
rows.push({
|
|
106
|
-
name:
|
|
107
|
-
state:
|
|
163
|
+
name: nestedRunLabel(child),
|
|
164
|
+
state: child.state,
|
|
165
|
+
depth,
|
|
108
166
|
...(modelThinking ? { modelThinking } : {}),
|
|
109
167
|
...(activity ? { activity } : {}),
|
|
110
|
-
...(
|
|
168
|
+
...(child.startedAt !== undefined ? { startedAt: child.startedAt } : {}),
|
|
111
169
|
});
|
|
112
170
|
}
|
|
113
|
-
|
|
171
|
+
if (!appendRuns(child.children, depth + 1)) {
|
|
172
|
+
omitted += nestedDisplayCount(runs, runIndex + 1);
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
114
175
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
...(modelThinking ? { modelThinking } : {}),
|
|
121
|
-
...(activity ? { activity } : {}),
|
|
122
|
-
...(child.startedAt !== undefined ? { startedAt: child.startedAt } : {}),
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
const visible = rows.slice(0, 4);
|
|
126
|
-
if (rows.length > visible.length) visible.push({ name: `… +${rows.length - visible.length} more nested leaves`, state: "complete", overflow: rows.length - visible.length });
|
|
127
|
-
return visible;
|
|
176
|
+
return true;
|
|
177
|
+
};
|
|
178
|
+
appendRuns(children, 0);
|
|
179
|
+
if (omitted > 0) rows.push({ name: `… +${omitted} more nested leaves`, state: "complete", depth: 0, overflow: omitted });
|
|
180
|
+
return rows;
|
|
128
181
|
}
|
|
129
182
|
|
|
130
183
|
function fleetTreeRows(entries: FleetStatusEntry[]): FleetTreeRow[] {
|
|
131
184
|
const rows: FleetTreeRow[] = [];
|
|
185
|
+
const entryKeys = new Set(entries.map((entry) => entry.key));
|
|
186
|
+
const childrenByParent = new Map<string, FleetStatusEntry[]>();
|
|
187
|
+
for (const entry of entries) {
|
|
188
|
+
if (!entry.parentKey || !entryKeys.has(entry.parentKey)) continue;
|
|
189
|
+
const children = childrenByParent.get(entry.parentKey) ?? [];
|
|
190
|
+
children.push(entry);
|
|
191
|
+
childrenByParent.set(entry.parentKey, children);
|
|
192
|
+
}
|
|
132
193
|
for (const entry of entries) {
|
|
194
|
+
if (entry.parentKey && entryKeys.has(entry.parentKey)) continue;
|
|
133
195
|
rows.push({ kind: "owner", entry });
|
|
134
|
-
const
|
|
196
|
+
const attached = childrenByParent.get(entry.key) ?? [];
|
|
197
|
+
for (const [index, child] of attached.entries()) {
|
|
198
|
+
const nested = nestedFleetRows(child.nestedChildren, 3);
|
|
199
|
+
const laterRows = index < attached.length - 1 || Boolean(entry.nestedChildren?.length);
|
|
200
|
+
rows.push({ kind: "child", entry: child, last: !laterRows && nested.length === 0 });
|
|
201
|
+
for (const [nestedIndex, row] of nested.entries()) rows.push({
|
|
202
|
+
kind: "nested",
|
|
203
|
+
ownerKey: child.key,
|
|
204
|
+
row: { ...row, depth: row.depth + 1 },
|
|
205
|
+
last: nestedIndex === nested.length - 1 && !laterRows,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
const nested = nestedFleetRows(entry.nestedChildren, attached.length > 0 ? 3 : 4);
|
|
135
209
|
for (const [index, row] of nested.entries()) rows.push({ kind: "nested", ownerKey: entry.key, row, last: index === nested.length - 1 });
|
|
136
210
|
}
|
|
137
211
|
return rows;
|
|
@@ -150,14 +224,24 @@ function foregroundDescription(control: { parentWorkflowRunId?: string; workflow
|
|
|
150
224
|
return description ? `${workflow} · ${description}` : workflow;
|
|
151
225
|
}
|
|
152
226
|
|
|
227
|
+
function activeLeafAgentCount(entries: FleetStatusEntry[]): number {
|
|
228
|
+
return entries.filter((entry) => !entry.workflowWrapper).length;
|
|
229
|
+
}
|
|
230
|
+
|
|
153
231
|
export function collectFleetStatusEntries(state: SubagentState): FleetStatusEntry[] {
|
|
154
232
|
const entries: FleetStatusEntry[] = [];
|
|
233
|
+
const activeWorkflowKeys = new Set([...state.asyncJobs.values()]
|
|
234
|
+
.filter((job) => job.mode === "workflow" && isActiveState(job.status))
|
|
235
|
+
.map((job) => `async:${job.asyncId}`));
|
|
155
236
|
for (const control of state.foregroundControls.values()) {
|
|
237
|
+
const parentKey = control.parentWorkflowRunId ? `async:${control.parentWorkflowRunId}` : undefined;
|
|
238
|
+
const linkedParentKey = parentKey && activeWorkflowKeys.has(parentKey) ? parentKey : undefined;
|
|
156
239
|
if (control.activeChildren) {
|
|
157
240
|
for (const child of [...control.activeChildren.values()].sort((left, right) => left.index - right.index)) {
|
|
158
241
|
const modelThinking = formatModelThinking(child.model, child.thinking) || undefined;
|
|
159
242
|
entries.push({
|
|
160
243
|
key: `foreground-active:${control.runId}:${child.index}`,
|
|
244
|
+
...(linkedParentKey ? { parentKey: linkedParentKey } : {}),
|
|
161
245
|
agent: child.agent,
|
|
162
246
|
...(modelThinking ? { modelThinking } : {}),
|
|
163
247
|
description: foregroundDescription(control, child.description),
|
|
@@ -174,6 +258,7 @@ export function collectFleetStatusEntries(state: SubagentState): FleetStatusEntr
|
|
|
174
258
|
const modelThinking = formatModelThinking(control.model, control.thinking) || undefined;
|
|
175
259
|
entries.push({
|
|
176
260
|
key: `foreground-active:${control.runId}:${control.currentIndex ?? 0}`,
|
|
261
|
+
...(linkedParentKey ? { parentKey: linkedParentKey } : {}),
|
|
177
262
|
agent: control.currentAgent ?? control.mode,
|
|
178
263
|
...(modelThinking ? { modelThinking } : {}),
|
|
179
264
|
description: foregroundDescription(control, control.description),
|
|
@@ -191,6 +276,7 @@ export function collectFleetStatusEntries(state: SubagentState): FleetStatusEntr
|
|
|
191
276
|
const latestEmit = job.workflow?.emits?.length ? formatWorkflowJsonPreview(job.workflow.emits.at(-1), 120) : undefined;
|
|
192
277
|
entries.push({
|
|
193
278
|
key: `async:${job.asyncId}`,
|
|
279
|
+
workflowWrapper: true,
|
|
194
280
|
agent: "workflow",
|
|
195
281
|
description: latestEmit !== undefined ? `latest emit: ${latestEmit}` : job.description,
|
|
196
282
|
startedAt,
|
|
@@ -241,6 +327,25 @@ export function collectFleetStatusEntries(state: SubagentState): FleetStatusEntr
|
|
|
241
327
|
}
|
|
242
328
|
}
|
|
243
329
|
|
|
330
|
+
if (state.currentSessionId) {
|
|
331
|
+
try {
|
|
332
|
+
for (const run of snapshotExternalRuns(state.currentSessionId, { ignoreMalformed: true, onMalformedRecord: (message) => console.warn(`[pi-subagents] Removed ${message}`) })) {
|
|
333
|
+
if (!isActiveState(run.state)) continue;
|
|
334
|
+
entries.push({
|
|
335
|
+
key: `external:${run.id}`,
|
|
336
|
+
agent: `external · ${run.label}`,
|
|
337
|
+
description: run.currentAction ?? `source: ${run.source}`,
|
|
338
|
+
startedAt: run.startedAt,
|
|
339
|
+
tokens: 0,
|
|
340
|
+
state: run.state,
|
|
341
|
+
external: true,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
} catch (cause) {
|
|
345
|
+
console.warn(`[pi-subagents] Failed to inspect external jobs: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
244
349
|
return entries.sort((left, right) => left.startedAt - right.startedAt || left.key.localeCompare(right.key));
|
|
245
350
|
}
|
|
246
351
|
|
|
@@ -417,10 +522,15 @@ export class SubagentFleetStatus {
|
|
|
417
522
|
if (!this.active) {
|
|
418
523
|
const tokens = this.entries.reduce((total, entry) => total + entry.tokens, 0);
|
|
419
524
|
const capacity = this.state.activeAsyncCapacity;
|
|
420
|
-
const
|
|
421
|
-
const
|
|
525
|
+
const hasNativeRows = this.entries.some((entry) => !entry.external);
|
|
526
|
+
const showNativeSummary = hasNativeRows || Boolean(capacity?.used);
|
|
527
|
+
const asyncRuns = capacity && showNativeSummary ? `Async runs ${capacity.used}/${capacity.limit || "∞"}` : "";
|
|
528
|
+
const activeEntries = activeLeafAgentCount(this.entries);
|
|
529
|
+
const noun = this.entries.some((entry) => entry.external) ? "job" : "agent";
|
|
530
|
+
const agents = activeEntries > 0 ? `${activeEntries} active ${noun}${activeEntries === 1 ? "" : "s"}` : "";
|
|
422
531
|
const label = [agents, asyncRuns].filter(Boolean).join(" · ");
|
|
423
|
-
|
|
532
|
+
const detail = [showNativeSummary ? formatFleetTokens(tokens) : undefined, "↓/← to inspect"].filter(Boolean).join(" · ");
|
|
533
|
+
return [truncateToWidth(` ${theme.fg("muted", label)} · ${theme.fg("dim", detail)}`, width)];
|
|
424
534
|
}
|
|
425
535
|
const roster = this.rosterKeys();
|
|
426
536
|
const selectedIndex = Math.max(0, roster.indexOf(this.selectedKey));
|
|
@@ -428,16 +538,16 @@ export class SubagentFleetStatus {
|
|
|
428
538
|
lines.push(truncateToWidth(` ${this.bullet(0, selectedIndex, theme)} main`, width));
|
|
429
539
|
|
|
430
540
|
const tree = fleetTreeRows(this.entries);
|
|
431
|
-
const selectedTreeIndex = Math.max(0, tree.findIndex((row) => row.kind === "owner" && row.entry.key === this.selectedKey));
|
|
541
|
+
const selectedTreeIndex = Math.max(0, tree.findIndex((row) => (row.kind === "owner" || row.kind === "child") && row.entry.key === this.selectedKey));
|
|
432
542
|
const visibleCount = Math.min(this.maxAgentRows, tree.length);
|
|
433
543
|
const start = selectedTreeIndex < visibleCount ? 0 : selectedTreeIndex - visibleCount + 1;
|
|
434
544
|
const hiddenBelow = tree.length - (start + visibleCount);
|
|
435
545
|
if (start > 0) lines.push(rightAlign("", theme.fg("dim", `↑ ${start} more`), width));
|
|
436
546
|
for (let index = start; index < start + visibleCount; index++) {
|
|
437
547
|
const row = tree[index]!;
|
|
438
|
-
if (row.kind === "owner") {
|
|
548
|
+
if (row.kind === "owner" || row.kind === "child") {
|
|
439
549
|
const ownerIndex = this.entries.findIndex((entry) => entry.key === row.entry.key);
|
|
440
|
-
lines.push(this.renderEntry(ownerIndex + 1, selectedIndex, row.entry, width, theme));
|
|
550
|
+
lines.push(this.renderEntry(ownerIndex + 1, selectedIndex, row.entry, width, theme, row.kind === "child" ? (row.last ? "└─" : "├─") : undefined));
|
|
441
551
|
} else {
|
|
442
552
|
lines.push(this.renderNestedRow(row.row, row.last, width, theme));
|
|
443
553
|
}
|
|
@@ -446,20 +556,22 @@ export class SubagentFleetStatus {
|
|
|
446
556
|
return lines;
|
|
447
557
|
}
|
|
448
558
|
|
|
449
|
-
private renderEntry(rosterIndex: number, selectedIndex: number, entry: FleetStatusEntry, width: number, theme: Theme): string {
|
|
559
|
+
private renderEntry(rosterIndex: number, selectedIndex: number, entry: FleetStatusEntry, width: number, theme: Theme, branch?: string): string {
|
|
450
560
|
const agent = entry.modelThinking ? `${entry.agent} (${entry.modelThinking})` : entry.agent;
|
|
451
|
-
const
|
|
561
|
+
const prefix = branch ? ` ${branch}` : " ";
|
|
562
|
+
const left = `${prefix} ${this.bullet(rosterIndex, selectedIndex, theme)} ${theme.fg("muted", agent)} · ${entry.state}`;
|
|
452
563
|
const elapsed = Date.now() - entry.startedAt;
|
|
453
|
-
const right = theme.fg("dim", `${formatFleetElapsed(elapsed)} · ${formatFleetTokens(entry.tokens)}`);
|
|
564
|
+
const right = theme.fg("dim", entry.external ? formatFleetElapsed(elapsed) : `${formatFleetElapsed(elapsed)} · ${formatFleetTokens(entry.tokens)}`);
|
|
454
565
|
return rightAlign(left, right, width);
|
|
455
566
|
}
|
|
456
567
|
|
|
457
568
|
private renderNestedRow(row: FleetNestedRow, last: boolean, width: number, theme: Theme): string {
|
|
458
569
|
const marker = last ? "└─" : "├─";
|
|
459
|
-
|
|
570
|
+
const indent = " ".repeat(row.depth + 1);
|
|
571
|
+
if (row.overflow !== undefined) return truncateToWidth(`${indent}${marker} ${theme.fg("dim", `+${row.overflow} nested leaves`)}`, width);
|
|
460
572
|
const modelThinking = row.modelThinking ? ` (${row.modelThinking})` : "";
|
|
461
573
|
const activity = row.activity ? ` · ${row.activity}` : "";
|
|
462
|
-
const left =
|
|
574
|
+
const left = `${indent}${marker} ${nestedStatusGlyph(row.state, theme)} ${theme.fg("muted", `${row.name}${modelThinking}`)} · ${row.state}${activity}`;
|
|
463
575
|
const elapsed = row.startedAt !== undefined ? ` · ${formatFleetElapsed(Date.now() - row.startedAt)}` : "";
|
|
464
576
|
return truncateToWidth(`${left}${theme.fg("dim", elapsed)}`, width);
|
|
465
577
|
}
|
|
@@ -504,22 +616,25 @@ export class SubagentFleetStatus {
|
|
|
504
616
|
entries: this.entries.map((entry) => this.active
|
|
505
617
|
? [
|
|
506
618
|
entry.key,
|
|
619
|
+
entry.parentKey,
|
|
507
620
|
entry.agent,
|
|
508
621
|
entry.state,
|
|
509
622
|
entry.modelThinking,
|
|
510
623
|
entry.description,
|
|
624
|
+
entry.external,
|
|
511
625
|
Math.round((now - entry.startedAt) / 1000),
|
|
512
626
|
entry.tokens,
|
|
513
|
-
entry.nestedChildren
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
627
|
+
nestedFleetRows(entry.nestedChildren, entry.parentKey ? 3 : 4).map((row) => [
|
|
628
|
+
row.name,
|
|
629
|
+
row.state,
|
|
630
|
+
row.modelThinking,
|
|
631
|
+
row.activity,
|
|
632
|
+
row.startedAt,
|
|
633
|
+
row.depth,
|
|
634
|
+
row.overflow,
|
|
520
635
|
]),
|
|
521
636
|
]
|
|
522
|
-
: [entry.key, entry.state, entry.tokens]),
|
|
637
|
+
: [entry.key, entry.state, entry.external, entry.tokens]),
|
|
523
638
|
});
|
|
524
639
|
}
|
|
525
640
|
|
|
@@ -2,59 +2,12 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { getLanguageFromPath, highlightCode, type ExtensionContext } from "@selesai/code";
|
|
4
4
|
import { Markdown, truncateToWidth, visibleWidth, wrapTextWithAnsi, type MarkdownTheme } from "@earendil-works/pi-tui";
|
|
5
|
+
import { safeTerminalText as safeDisplayText } from "../shared/display-text.ts";
|
|
5
6
|
|
|
6
7
|
const DEFAULT_MAX_RECORDS = 240;
|
|
7
8
|
const DEFAULT_MAX_BYTES = 2 * 1024 * 1024;
|
|
8
9
|
const MAX_MESSAGE_CHARS = 64 * 1024;
|
|
9
10
|
const TOOL_PREVIEW_LINES = 7;
|
|
10
|
-
const BINARY_CONTENT_PLACEHOLDER = "[binary content omitted for safe display]";
|
|
11
|
-
|
|
12
|
-
function isUnsafeDisplayCodePoint(codePoint: number): boolean {
|
|
13
|
-
const terminalControl = (codePoint <= 0x1f && codePoint !== 0x09 && codePoint !== 0x0a)
|
|
14
|
-
|| (codePoint >= 0x7f && codePoint <= 0x9f);
|
|
15
|
-
const bidiControl = codePoint === 0x061c
|
|
16
|
-
|| codePoint === 0x200e
|
|
17
|
-
|| codePoint === 0x200f
|
|
18
|
-
|| (codePoint >= 0x202a && codePoint <= 0x202e)
|
|
19
|
-
|| (codePoint >= 0x2066 && codePoint <= 0x2069);
|
|
20
|
-
const privateUse = (codePoint >= 0xe000 && codePoint <= 0xf8ff)
|
|
21
|
-
|| (codePoint >= 0xf0000 && codePoint <= 0xffffd)
|
|
22
|
-
|| (codePoint >= 0x100000 && codePoint <= 0x10fffd);
|
|
23
|
-
const invalidScalar = codePoint >= 0xd800 && codePoint <= 0xdfff;
|
|
24
|
-
const nonCharacter = (codePoint >= 0xfdd0 && codePoint <= 0xfdef)
|
|
25
|
-
|| (codePoint & 0xffff) === 0xfffe
|
|
26
|
-
|| (codePoint & 0xffff) === 0xffff;
|
|
27
|
-
return terminalControl || bidiControl || privateUse || invalidScalar || nonCharacter;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function looksLikeBinaryContent(text: string): boolean {
|
|
31
|
-
if (text.includes("\0")) return true;
|
|
32
|
-
let suspiciousControls = 0;
|
|
33
|
-
let replacementCharacters = 0;
|
|
34
|
-
let codePoints = 0;
|
|
35
|
-
for (const character of text) {
|
|
36
|
-
codePoints++;
|
|
37
|
-
const codePoint = character.codePointAt(0) ?? 0;
|
|
38
|
-
if ((codePoint <= 0x08) || (codePoint >= 0x0e && codePoint <= 0x1f)) suspiciousControls++;
|
|
39
|
-
if (codePoint === 0xfffd) replacementCharacters++;
|
|
40
|
-
}
|
|
41
|
-
if (codePoints === 0) return false;
|
|
42
|
-
return (suspiciousControls >= 4 && suspiciousControls / codePoints >= 0.1)
|
|
43
|
-
|| (replacementCharacters >= 3 && replacementCharacters / codePoints >= 0.1);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function safeDisplayText(text: string): string {
|
|
47
|
-
const normalized = text.replace(/\r\n/g, "\n");
|
|
48
|
-
if (looksLikeBinaryContent(normalized)) return BINARY_CONTENT_PLACEHOLDER;
|
|
49
|
-
let safe = "";
|
|
50
|
-
for (const character of normalized) {
|
|
51
|
-
const codePoint = character.codePointAt(0) ?? 0;
|
|
52
|
-
safe += isUnsafeDisplayCodePoint(codePoint)
|
|
53
|
-
? `[U+${codePoint.toString(16).toUpperCase().padStart(4, "0")}]`
|
|
54
|
-
: character;
|
|
55
|
-
}
|
|
56
|
-
return safe;
|
|
57
|
-
}
|
|
58
11
|
|
|
59
12
|
function sanitizeJsonDisplayValue(value: unknown): { value: unknown; changed: boolean } {
|
|
60
13
|
if (typeof value === "string") {
|