pi-subagents 0.81.0 → 0.82.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 +38 -0
- package/bundle/agents.js +3 -3
- package/bundle/child-tool-plan.js +2 -2
- package/bundle/{chunk-LSRUTHT7.js → chunk-43SCHIMD.js} +1 -1
- package/bundle/{chunk-G5DKFLLI.js → chunk-4SDU2BZX.js} +15 -10
- package/bundle/{chunk-V2JWDB5U.js → chunk-52UBALJL.js} +2 -2
- package/bundle/{chunk-3DC5KBVP.js → chunk-5TYMSZX3.js} +1 -1
- package/bundle/{chunk-CEKS3TFO.js → chunk-7IVSUMQQ.js} +6 -6
- package/bundle/{chunk-KSWQVGDW.js → chunk-7PCKZHR5.js} +225 -18
- package/bundle/{chunk-563BHAZ5.js → chunk-7YMXOYEU.js} +33 -25
- package/bundle/{chunk-XMFLCKMQ.js → chunk-B5EKXDHE.js} +336 -130
- package/bundle/{chunk-ZBC44JJ3.js → chunk-CIZQXJ5Q.js} +22 -9
- package/bundle/{chunk-L5ZHE4L4.js → chunk-GC4DSPMH.js} +4 -4
- package/bundle/{chunk-ARRKBB2B.js → chunk-GJECHSAR.js} +2 -2
- package/bundle/{chunk-2ZSNH26H.js → chunk-M2CTFYT3.js} +7 -7
- package/bundle/{chunk-TUWLXTAM.js → chunk-MHZ4G23A.js} +681 -320
- package/bundle/{chunk-WSBNENFS.js → chunk-NGGAFDL6.js} +14 -4
- package/bundle/{chunk-VJHOELQP.js → chunk-NRQ75MGH.js} +160 -78
- package/bundle/{chunk-BJN5LUQY.js → chunk-OYF6AFDY.js} +1 -1
- package/bundle/{chunk-EYNJ6VL6.js → chunk-PLCCBLPY.js} +2 -2
- package/bundle/{chunk-74RT5YQE.js → chunk-RMQFMMAT.js} +123 -33
- package/bundle/{chunk-V6MR5TOQ.js → chunk-SIJ4S3EN.js} +25 -19
- package/bundle/{chunk-NNLASTQE.js → chunk-VH5OAWVG.js} +19 -5
- package/bundle/{chunk-BPS2AGBZ.js → chunk-W2SZ22EM.js} +93 -52
- package/bundle/{chunk-V3BIUPLU.js → chunk-WVD4UEL4.js} +256 -52
- package/bundle/{chunk-ZP3HODFH.js → chunk-XSWOTIA3.js} +1 -1
- package/bundle/{chunk-3IF2PGW7.js → chunk-YKEWIB4M.js} +1 -1
- package/bundle/{chunk-26C3WLYQ.js → chunk-ZLINIYTP.js} +497 -272
- package/bundle/{chunk-2XYWN7QJ.js → chunk-ZQGSDHL6.js} +2 -2
- package/bundle/control-channel.js +2 -2
- package/bundle/index.js +1 -1
- package/bundle/intercom-bridge.js +2 -2
- package/bundle/preflight.js +8 -8
- package/bundle/project-panes.js +3 -3
- package/docs/agents.md +31 -0
- package/docs/configuration.md +9 -1
- package/docs/tool-reference.md +3 -1
- package/docs/workflows.md +16 -0
- package/package.json +2 -2
- package/skills/pi-subagents/references/execution-controls.md +5 -4
- package/src/agents/agent-management.js +3 -3
- package/src/agents/agent-memory.js +3 -1
- package/src/agents/agents.js +6 -6
- package/src/agents/frontmatter.d.ts +2 -0
- package/src/agents/frontmatter.js +15 -1
- package/src/agents/skills.js +2 -1
- package/src/extension/config.js +3 -0
- package/src/extension/herdr-pi-bridge.js +17 -10
- package/src/extension/index.js +82 -2
- package/src/extension/schemas.js +3 -3
- package/src/intercom/native-supervisor-channel.js +20 -0
- package/src/missions/lifecycle.js +7 -1
- package/src/runs/background/active-async-capacity.d.ts +1 -0
- package/src/runs/background/active-async-capacity.js +9 -3
- package/src/runs/background/async-execution.js +20 -10
- package/src/runs/background/async-job-tracker.d.ts +6 -1
- package/src/runs/background/async-job-tracker.js +9 -4
- package/src/runs/background/async-status.d.ts +2 -0
- package/src/runs/background/async-status.js +21 -2
- package/src/runs/background/await-async-run.js +3 -7
- package/src/runs/background/boot-id.d.ts +12 -0
- package/src/runs/background/boot-id.js +47 -0
- package/src/runs/background/interrupted-elsewhere.d.ts +22 -0
- package/src/runs/background/interrupted-elsewhere.js +68 -0
- package/src/runs/background/notify.d.ts +2 -0
- package/src/runs/background/notify.js +13 -0
- package/src/runs/background/result-delivery-ownership.d.ts +6 -0
- package/src/runs/background/result-delivery-ownership.js +19 -1
- package/src/runs/background/result-watcher.d.ts +3 -1
- package/src/runs/background/result-watcher.js +24 -8
- package/src/runs/background/run-child-session.d.ts +1 -6
- package/src/runs/background/run-child-session.js +1 -1
- package/src/runs/background/run-status.js +2 -1
- package/src/runs/background/stale-run-reconciler.d.ts +25 -0
- package/src/runs/background/stale-run-reconciler.js +52 -13
- package/src/runs/background/subagent-runner-bootstrap.js +3 -0
- package/src/runs/background/subagent-runner.d.ts +4 -0
- package/src/runs/background/subagent-runner.js +13 -5
- package/src/runs/background/subagent-wait.d.ts +1 -1
- package/src/runs/background/subagent-wait.js +6 -1
- package/src/runs/background/terminal-run-index.d.ts +1 -0
- package/src/runs/background/terminal-run-index.js +4 -2
- package/src/runs/foreground/async-stop-action.js +3 -1
- package/src/runs/foreground/execution.js +6 -3
- package/src/runs/foreground/foreground-history.d.ts +16 -2
- package/src/runs/foreground/foreground-history.js +133 -31
- package/src/runs/foreground/subagent-executor.d.ts +11 -0
- package/src/runs/foreground/subagent-executor.js +277 -74
- package/src/runs/shared/child-launch.d.ts +2 -2
- package/src/runs/shared/child-session.d.ts +3 -2
- package/src/runs/shared/child-session.js +51 -8
- package/src/runs/shared/child-tool-plan.d.ts +7 -0
- package/src/runs/shared/child-tool-plan.js +21 -6
- package/src/runs/shared/herdr-connection.d.ts +17 -8
- package/src/runs/shared/herdr-connection.js +19 -7
- package/src/runs/shared/herdr-external-adapters.d.ts +3 -2
- package/src/runs/shared/herdr-external-adapters.js +1 -1
- package/src/runs/shared/herdr-machine.d.ts +12 -2
- package/src/runs/shared/herdr-machine.js +55 -9
- package/src/runs/shared/herdr-pane-host.d.ts +88 -0
- package/src/runs/shared/herdr-pane-host.js +155 -0
- package/src/runs/shared/herdr-placed-run.d.ts +27 -150
- package/src/runs/shared/herdr-placed-run.js +48 -395
- package/src/runs/shared/local-machine-access.d.ts +5 -0
- package/src/runs/shared/local-machine-access.js +28 -0
- package/src/runs/shared/orca-progress-tabs.d.ts +0 -1
- package/src/runs/shared/orca-progress-tabs.js +1 -24
- package/src/runs/shared/parallel-utils.d.ts +1 -1
- package/src/runs/shared/placed-run-owner.d.ts +49 -0
- package/src/runs/shared/placed-run-owner.js +93 -0
- package/src/runs/shared/placement-host.d.ts +99 -0
- package/src/runs/shared/placement-host.js +157 -0
- package/src/runs/shared/rex-machine.d.ts +25 -0
- package/src/runs/shared/rex-machine.js +83 -0
- package/src/runs/shared/rex-pane-host.d.ts +62 -0
- package/src/runs/shared/rex-pane-host.js +327 -0
- package/src/shared/completion-owner.d.ts +5 -0
- package/src/shared/completion-owner.js +5 -0
- package/src/shared/session-identity.d.ts +2 -0
- package/src/shared/session-identity.js +26 -0
- package/src/shared/types.d.ts +45 -6
- package/src/tui/fleet.d.ts +1 -0
- package/src/tui/fleet.js +24 -15
- package/src/tui/render.d.ts +6 -0
- package/src/tui/render.js +3 -3
- package/src/tui/subagent-messages.js +1 -0
- package/src/workflows/scripted-workflow.d.ts +1 -1
- package/src/workflows/workflow-auto-resume.d.ts +32 -0
- package/src/workflows/workflow-auto-resume.js +102 -0
- package/src/workflows/workflow-launch-record.d.ts +27 -0
- package/src/workflows/workflow-launch-record.js +48 -0
- package/src/workflows/workflow-resume-claim.d.ts +82 -0
- package/src/workflows/workflow-resume-claim.js +210 -0
- package/src/workflows/workflow-resume.d.ts +56 -0
- package/src/workflows/workflow-resume.js +106 -0
- package/src/workflows/workflow-reuse.d.ts +15 -9
- package/src/workflows/workflow-reuse.js +77 -14
- package/src/workflows/workflow-revival.d.ts +2 -0
- package/src/workflows/workflow-revival.js +2 -1
- package/src/workflows/workflow-stop-cause.d.ts +6 -0
- package/src/workflows/workflow-stop-cause.js +8 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,44 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.82.0] - 2026-10-24
|
|
6
|
+
|
|
7
|
+
### Highlights
|
|
8
|
+
|
|
9
|
+
- Background workflows cut off by Pi crashing, quitting or reloading resume where they stopped when you reopen their session, without running finished steps again.
|
|
10
|
+
- Background runs that finished while Pi was closed report their results when you reopen their session, and a foreground run cut off by a crash can be resumed by id.
|
|
11
|
+
- Pi children can run in their own Rex terminal tabs, on this Mac or on another Mac over SSH.
|
|
12
|
+
- After a machine restart, runs that died with it no longer show as running or hold a capacity slot.
|
|
13
|
+
- `/subagents-fleet` shows each child's task next to its agent name, so children of one run are easy to tell apart.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Background workflows cut off by Pi exiting, crashing or reloading now resume on their own when you reopen or reload their session within a day, and steps that already finished are not run again. You can also resume one yourself with `subagent({ action: "resume", id })`, or set `autoResume: false` to resume them only by hand. A stopped workflow is resumed only once, and its notice says how it resumed. If you start a new Pi in the same folder instead, it tells you which session to reopen. See [docs/workflows.md](docs/workflows.md).
|
|
18
|
+
- `machine: "local"` runs a native Pi child in a new background tab of your own Rex session, with the same controls as a Herdr-placed Pi child: prompts, steering, follow-ups, abort, `contact_supervisor` and results. The launch fails if the parent Pi is not running inside Rex, and Claude Code, Codex, Cursor and generic `external-cli` agents are rejected. A finished child's tab stays open until you close it; an aborted or stopped child's tab is closed. See [docs/agents.md](docs/agents.md#running-a-pi-child-in-a-rex-pane-on-this-machine).
|
|
19
|
+
- A native Pi child can also run in a Rex tab on another Mac over SSH. Name the Mac in your user settings with `subagents.machines.<name>.rex.ssh`, then pass `machine: "<name>"`. The child opens in that Mac's `subagents` Rex session, which is created the first time it is needed. These machines do not need Herdr, and project settings cannot name a Rex host. See [docs/agents.md](docs/agents.md#running-a-pi-child-in-a-rex-pane-on-another-mac).
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- Each background child's row in `/subagents-fleet` now shows its task after the agent name, for example `worker · Fix two Cycode Python SAST findings…`, so you can tell children of one run apart without opening each one. The selected child's header still shows the run id. Thanks to [@MattDavisRV](https://github.com/MattDavisRV) for #3020.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- A background run that was still working when Pi exited or crashed never reported its result, even after you reopened its session. Its result now shows once in the reopened session: right away if the run already finished, or as soon as it finishes.
|
|
28
|
+
- A foreground single run cut off by a Pi crash can now be resumed by id. It used to be recorded only when it ended, so nothing pointed to its transcript. It is now recorded when it starts, shows as `interrupted when Pi exited · resume <id>` when its session reopens, and `subagent({ action: "resume", id, message })` continues it from its transcript. Foreground runs remembered by earlier versions are not carried over and can no longer be resumed by id.
|
|
29
|
+
- After Pi crashed or was killed while an async workflow ran, relaunching the same workflow ran every child again. The workflow is now marked `stopCause: "owner-exited"` when its session reopens, or when `options.reuseFrom` names it from another session, and a relaunch reuses the children that already finished, the same as after `/reload`. Its failed result says the Pi process exited. See [docs/workflows.md](docs/workflows.md).
|
|
30
|
+
- A workflow relaunched more than once could start a second copy of a child that was still running, or run a finished child again. A relaunch only looked at the run it reused, and that run had no record of children still waiting for a concurrency slot when it stopped. A relaunch now looks at every earlier run in its relaunch chain and takes each child from the newest run that recorded it. Thanks to [@wireknight](https://github.com/wireknight) for the report on #3021.
|
|
31
|
+
- After a machine restart, a background run or workflow that died with the machine could show as running, and hold its capacity slot, for up to a day, because its old process id could now belong to another process. On Linux and macOS, Pi now saves a boot id next to each process id and treats a process id from an earlier boot as dead. Runs started through a `launcher` are unchanged.
|
|
32
|
+
- A background child awaited by an `async: false` workflow now gets an immediate `contact_supervisor` tool error when it asks a question, because its blocked parent cannot answer. The error tells it to report partial results or use an async workflow. Before, the question could wait until the run deadline and reach the parent after the child had timed out. Async workflows and children that are not awaited still get normal supervisor replies. Thanks to [@XLi-hub](https://github.com/XLi-hub) for #3028 and [@isjiajia01](https://github.com/isjiajia01) for the report in #3018.
|
|
33
|
+
- Agents called `bg_wait` in a loop when it returned early because a run that was still working needed attention, such as a long `bash` command or a quiet stretch. The result now says the run is still running and that `stopOnAttention: false` waits through this, and the option's description says it still stops for supervisor requests. Thanks to [@jettoblack](https://github.com/jettoblack) for #3019.
|
|
34
|
+
- A quoted name in an agent's `tools`, `excludeTools`, `mutationTools`, `extensions` or `subagentOnlyExtensions` list, such as `tools: "read", "bash"` or a `- "read"` list item, is no longer read with its quote marks. A quoted tool name made the child fail to start, and a quoted extension path pointed at a file that doesn't exist. Thanks to [@HerbertGao](https://github.com/HerbertGao) for #3017.
|
|
35
|
+
- An agent whose `tools` list has a Pi `+name` or `-name` entry, such as `tools: +codemode`, now fails before launch with an error that names the agent and the entry. Before, the entry was kept as a literal tool name, so the child required a tool named `+codemode` that no child has, and adding `read` for skills, MCP tools or `structured_output` produced a list that Pi rejects. A Herdr- or Rex-placed child whose agent definition on that machine has such an entry fails the same way before its first prompt. `tools` is a complete list: name every tool the child needs, or omit `tools` and use `excludeTools` to drop one. See [docs/agents.md](docs/agents.md#tool-and-extension-selection). Thanks to [@Nyarlathoteppppp](https://github.com/Nyarlathoteppppp) for #3029.
|
|
36
|
+
- A host-required child extension (`registerRequiredChildExtensions`) is now recognized when Pi loads it through another spelling of its path, such as a symlink, a different letter case, or a path with a Unicode space, so its load, provider-registration and startup failures still stop the launch. A required extension that Pi did not load at all now stops the launch instead of letting the child start without it. Thanks to [@pandalaohe](https://github.com/pandalaohe) for #3012.
|
|
37
|
+
- A child agent's `MEMORY.md` that is a named pipe (FIFO) no longer stalls its launch while the prompt is built; it is skipped like any other file that is not a regular file. Thanks to [@XLi-hub](https://github.com/XLi-hub) for #3027.
|
|
38
|
+
- Skill discovery no longer fails with `ENOTDIR` when a `settings.json` `packages` entry names a single extension file. Thanks to [@tara-marchand](https://github.com/tara-marchand) for #3011.
|
|
39
|
+
- Herdr-placed native Pi children no longer fail before their first prompt. The child's pane bridge looked for its active tools where Pi does not provide them, found none, and rejected every launch.
|
|
40
|
+
- A corrupt saved run status or mission file no longer prints the same warning on every status refresh or retry. The warning prints once, and again only when the file or its outcome changes. The run is still skipped or retried as before, and the file is left as it is. Thanks to [@ozand](https://github.com/ozand) for #3037 and the report in #3036.
|
|
41
|
+
- Updated `undici` from 8.10.2 to 8.12.3, outside the range of [GHSA-xjj6-f33q-929c](https://github.com/advisories/GHSA-xjj6-f33q-929c), so projects that install pi-subagents no longer fail `npm audit` because of it. Thanks to [@setanta00](https://github.com/setanta00) for #3022.
|
|
42
|
+
|
|
5
43
|
## [0.81.0] - 2026-10-22
|
|
6
44
|
|
|
7
45
|
### Highlights
|
package/bundle/agents.js
CHANGED
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
RUNTIME_AGENT_REGISTER_EVENT,
|
|
3
3
|
RUNTIME_AGENT_REGISTER_VERSION,
|
|
4
4
|
registerAgentViaEvents
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-43SCHIMD.js";
|
|
6
6
|
import {
|
|
7
7
|
registerRuntimeAgent
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-YKEWIB4M.js";
|
|
9
|
+
import "./chunk-CIZQXJ5Q.js";
|
|
10
10
|
import "./chunk-5LFLVSTM.js";
|
|
11
11
|
import "./chunk-YFCK7H2S.js";
|
|
12
12
|
import "./chunk-Z7KVHQHL.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolvePiLaunchToolPlan
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4SDU2BZX.js";
|
|
4
4
|
import "./chunk-CTPAE36Y.js";
|
|
5
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-CIZQXJ5Q.js";
|
|
6
6
|
import "./chunk-5LFLVSTM.js";
|
|
7
7
|
import "./chunk-YFCK7H2S.js";
|
|
8
8
|
import "./chunk-Z7KVHQHL.js";
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
getAgentDir,
|
|
8
8
|
getConfigDirName,
|
|
9
9
|
getProjectConfigDir
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-CIZQXJ5Q.js";
|
|
11
11
|
import {
|
|
12
12
|
TEMP_ROOT_DIR
|
|
13
13
|
} from "./chunk-5LFLVSTM.js";
|
|
@@ -935,6 +935,15 @@ function formatRuntimeSnapshotMcpServersError(agentName, serverNames) {
|
|
|
935
935
|
const subject = agentName ? `Agent '${agentName}'` : "Subagent";
|
|
936
936
|
return `${subject} selects MCP tools from servers that exist only in pi-mcp-adapter's runtime snapshot (${serverNames.join(", ")}). MCP servers from the runtime snapshot cannot be provided to in-process children; MCP tools must come from an ambient adapter extension in a background child (\`async: true\`), so add the server to the adapter's configuration file instead.`;
|
|
937
937
|
}
|
|
938
|
+
function isToolExtensionPath(entry) {
|
|
939
|
+
return entry.includes("/") || entry.endsWith(".ts") || entry.endsWith(".js");
|
|
940
|
+
}
|
|
941
|
+
function assertNoToolModifierEntries(agentName, tools) {
|
|
942
|
+
const entries = tools.filter((entry) => /^[+-]/u.test(entry) && !isToolExtensionPath(entry));
|
|
943
|
+
if (entries.length === 0) return;
|
|
944
|
+
const subject = agentName ? `Agent '${agentName}'` : "Subagent";
|
|
945
|
+
throw new Error(`${subject} lists Pi tool modifier ${entries.length === 1 ? "entry" : "entries"} in \`tools\`: ${entries.join(", ")}. A child's \`tools\` list is the complete set of tools it gets, so +name and -name entries are not supported; name every tool the child needs, or omit \`tools\` and use \`excludeTools\` to drop one.`);
|
|
946
|
+
}
|
|
938
947
|
function projectLaunchResolvedChildExtensions(toolPlan) {
|
|
939
948
|
const runtime = boundedExtensionIdentifiers(toolPlan.runtimeExtensions);
|
|
940
949
|
const configured = boundedExtensionIdentifiers(toolPlan.configuredExtensions);
|
|
@@ -1014,9 +1023,8 @@ function resolvePiLaunchToolPlan(input) {
|
|
|
1014
1023
|
throw new Error(`Capability ceiling from ${capabilityCeiling.sources.join(", ") || "unknown source"} denies extensions but this host requires: ${requiredExtensions.map(({ id }) => id).join(", ")}.`);
|
|
1015
1024
|
}
|
|
1016
1025
|
const allowedToolSet = capabilityCeiling?.allowedTools === void 0 ? void 0 : new Set(capabilityCeiling.allowedTools);
|
|
1017
|
-
const requestedBuiltinTools = input.tools?.filter(
|
|
1018
|
-
|
|
1019
|
-
) ?? [];
|
|
1026
|
+
const requestedBuiltinTools = input.tools?.filter((tool) => !isToolExtensionPath(tool)) ?? [];
|
|
1027
|
+
assertNoToolModifierEntries(input.agentName, input.tools ?? []);
|
|
1020
1028
|
if (input.requireReadTool && allowedToolSet && !allowedToolSet.has("read")) {
|
|
1021
1029
|
throw new Error(
|
|
1022
1030
|
`Capability ceiling from ${capabilityCeiling?.sources.join(", ") || "unknown source"} excludes required tool 'read' for lazy skill loading.`
|
|
@@ -1031,9 +1039,7 @@ function resolvePiLaunchToolPlan(input) {
|
|
|
1031
1039
|
if (effectiveDeclaredBuiltinTools.includes("subagent_supervisor") && !fanoutAuthorized) {
|
|
1032
1040
|
throw new Error("Tool 'subagent_supervisor' requires fanout authorization: include 'subagent' in the effective tools allowlist or enable allowNestedSubagents.");
|
|
1033
1041
|
}
|
|
1034
|
-
const toolExtensionPaths = capabilityCeiling?.denyExtensions ? [] : (input.tools ?? []).filter(
|
|
1035
|
-
(tool) => !requestedBuiltinTools.includes(tool) && (tool.includes("/") || tool.endsWith(".ts") || tool.endsWith(".js"))
|
|
1036
|
-
);
|
|
1042
|
+
const toolExtensionPaths = capabilityCeiling?.denyExtensions ? [] : (input.tools ?? []).filter(isToolExtensionPath);
|
|
1037
1043
|
const mcpResolution = capabilityCeiling?.denyExtensions ? { selections: [], unresolvedSelectors: [] } : input.builtinMcpTools ? { selections: input.builtinMcpTools, unresolvedSelectors: [], builtin: true } : resolveMcpDirectToolResolution(input.mcpDirectTools, input.cwd, input.runtimeSnapshotHost);
|
|
1038
1044
|
if (mcpResolution.runtimeServerNames?.length) {
|
|
1039
1045
|
throw new Error(formatRuntimeSnapshotMcpServersError(input.agentName, mcpResolution.runtimeServerNames));
|
|
@@ -1114,9 +1120,7 @@ function resolvePiLaunchToolPlan(input) {
|
|
|
1114
1120
|
) ?? [],
|
|
1115
1121
|
internalTools,
|
|
1116
1122
|
extensionsDenied: capabilityCeiling.denyExtensions,
|
|
1117
|
-
removedExtensionCount: capabilityCeiling.denyExtensions ? (input.extensions?.length ?? 0) + (input.subagentOnlyExtensions?.length ?? 0) + (input.tools ?? []).filter(
|
|
1118
|
-
(tool) => tool.includes("/") || tool.endsWith(".ts") || tool.endsWith(".js")
|
|
1119
|
-
).length : 0,
|
|
1123
|
+
removedExtensionCount: capabilityCeiling.denyExtensions ? (input.extensions?.length ?? 0) + (input.subagentOnlyExtensions?.length ?? 0) + (input.tools ?? []).filter(isToolExtensionPath).length : 0,
|
|
1120
1124
|
requestedMcpToolCount: input.mcpDirectTools?.length ?? 0,
|
|
1121
1125
|
effectiveMcpTools,
|
|
1122
1126
|
agentAllowed: input.agentName === void 0 ? true : isAgentAllowedByCapabilityCeiling(
|
|
@@ -1180,6 +1184,7 @@ export {
|
|
|
1180
1184
|
deriveForkPromptCacheKey,
|
|
1181
1185
|
supervisorChannelDir,
|
|
1182
1186
|
applyThinkingSuffix,
|
|
1187
|
+
assertNoToolModifierEntries,
|
|
1183
1188
|
projectLaunchResolvedChildExtensions,
|
|
1184
1189
|
resolvePiLaunchToolPlan
|
|
1185
1190
|
};
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
} from "./chunk-7J4ZXMY7.js";
|
|
4
4
|
import {
|
|
5
5
|
getProjectSubagentsDir
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-5TYMSZX3.js";
|
|
7
7
|
import {
|
|
8
8
|
getPiSpawnCommand,
|
|
9
9
|
writeAtomicJson
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-CIZQXJ5Q.js";
|
|
11
11
|
|
|
12
12
|
// src/inspectors/herdr/project-panes.ts
|
|
13
13
|
import * as fs from "node:fs";
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
|
-
currentCompletionOwnerId,
|
|
3
2
|
isTrustedRecordedSessionFile,
|
|
4
3
|
resolveSubagentRunId
|
|
5
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7PCKZHR5.js";
|
|
6
5
|
import {
|
|
7
6
|
agentStreamOptions,
|
|
8
7
|
opencodeSessionHeaders,
|
|
9
8
|
ownsRun,
|
|
10
9
|
resolveAsyncResumeTarget
|
|
11
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-VH5OAWVG.js";
|
|
12
11
|
import {
|
|
12
|
+
currentCompletionOwnerId,
|
|
13
13
|
listMissions,
|
|
14
14
|
missionRecordPath,
|
|
15
15
|
readMissionBinding,
|
|
16
16
|
reconcileAsyncRun,
|
|
17
17
|
resolveAuthorityDecision,
|
|
18
18
|
resolveMissionStoreLocation
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-NRQ75MGH.js";
|
|
20
20
|
import {
|
|
21
21
|
deliverInterruptRequest,
|
|
22
22
|
queueRevivalBrief,
|
|
23
23
|
requestAsyncSteer
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-OYF6AFDY.js";
|
|
25
25
|
import {
|
|
26
26
|
formatShellCommand
|
|
27
27
|
} from "./chunk-7J4ZXMY7.js";
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
tryLease,
|
|
33
33
|
writeAtomicJson,
|
|
34
34
|
writePrivateAtomicJson
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-CIZQXJ5Q.js";
|
|
36
36
|
import {
|
|
37
37
|
DIRS
|
|
38
38
|
} from "./chunk-5LFLVSTM.js";
|
|
@@ -11,11 +11,15 @@ import {
|
|
|
11
11
|
resolveAsyncStatusChild,
|
|
12
12
|
stopStoppableAsyncStatusChildren,
|
|
13
13
|
summarizeContextModes,
|
|
14
|
+
utf8Tail,
|
|
14
15
|
workflowPreflightLaneForRuntimeKey
|
|
15
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-VH5OAWVG.js";
|
|
16
17
|
import {
|
|
17
18
|
assertSafeNestedId,
|
|
19
|
+
checkRecordedPidLiveness,
|
|
20
|
+
encodeIndexSegment,
|
|
18
21
|
findNestedRunMatchesById,
|
|
22
|
+
isRecordedPid,
|
|
19
23
|
readActiveRunToolCallIndex,
|
|
20
24
|
readProcessTerminal,
|
|
21
25
|
readTerminalRunToolCallIndex,
|
|
@@ -26,12 +30,13 @@ import {
|
|
|
26
30
|
resultPayloadPathForIndexedRun,
|
|
27
31
|
resultPayloadPathForSessionRun,
|
|
28
32
|
updateActiveRunIndex,
|
|
33
|
+
validateModelResponseAliases,
|
|
29
34
|
writeAsyncResultFile
|
|
30
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-NRQ75MGH.js";
|
|
31
36
|
import {
|
|
32
37
|
deliverStopRequest,
|
|
33
38
|
stopInboxClosedPath
|
|
34
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-OYF6AFDY.js";
|
|
35
40
|
import {
|
|
36
41
|
SUBAGENT_STOPPED_MESSAGE,
|
|
37
42
|
formatDuration,
|
|
@@ -39,8 +44,10 @@ import {
|
|
|
39
44
|
formatTokens,
|
|
40
45
|
readStatus,
|
|
41
46
|
shortenPath,
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
validateAcceptanceInput,
|
|
48
|
+
writeAtomicJson,
|
|
49
|
+
writePrivateAtomicJson
|
|
50
|
+
} from "./chunk-CIZQXJ5Q.js";
|
|
44
51
|
import {
|
|
45
52
|
DIRS
|
|
46
53
|
} from "./chunk-5LFLVSTM.js";
|
|
@@ -49,15 +56,6 @@ import {
|
|
|
49
56
|
truncateDisplayText
|
|
50
57
|
} from "./chunk-YFCK7H2S.js";
|
|
51
58
|
|
|
52
|
-
// src/shared/completion-owner.ts
|
|
53
|
-
import { randomUUID } from "node:crypto";
|
|
54
|
-
var COMPLETION_OWNER_KEY = /* @__PURE__ */ Symbol.for("pi-subagents.completion-owner-id");
|
|
55
|
-
function currentCompletionOwnerId() {
|
|
56
|
-
const runtime = globalThis;
|
|
57
|
-
runtime[COMPLETION_OWNER_KEY] ??= randomUUID();
|
|
58
|
-
return runtime[COMPLETION_OWNER_KEY];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
59
|
// src/workflows/chat-progress.ts
|
|
62
60
|
import { spawnSync } from "node:child_process";
|
|
63
61
|
import * as fs from "node:fs";
|
|
@@ -411,8 +409,8 @@ function formatDetachedForegroundFleetLines(runs) {
|
|
|
411
409
|
}
|
|
412
410
|
function externalCliStepFacts(step, now) {
|
|
413
411
|
if (step.runner?.type !== "external-cli") return void 0;
|
|
414
|
-
const
|
|
415
|
-
const elapsed =
|
|
412
|
+
const process2 = step.externalProcess;
|
|
413
|
+
const elapsed = process2 ? process2.durationMs ?? Math.max(0, (process2.endedAt ?? now) - process2.startedAt) : void 0;
|
|
416
414
|
return `external-cli${elapsed !== void 0 ? ` \xB7 ${formatDuration(elapsed)}` : ""}`;
|
|
417
415
|
}
|
|
418
416
|
function formatAsyncFleetLines(runs, now = Date.now()) {
|
|
@@ -861,6 +859,8 @@ function sealPausedRun(asyncDir, status, resultsDir) {
|
|
|
861
859
|
sessionId: status.sessionId,
|
|
862
860
|
asyncDir,
|
|
863
861
|
...status.completionOwnerId ? { completionOwnerId: status.completionOwnerId } : {},
|
|
862
|
+
...status.completionOwnerProcess ? { completionOwnerProcess: status.completionOwnerProcess } : {},
|
|
863
|
+
...status.parentWorkflowRunId ? { parentWorkflowRunId: status.parentWorkflowRunId } : {},
|
|
864
864
|
...status.toolCallId ? { toolCallId: status.toolCallId } : {},
|
|
865
865
|
results: (status.steps ?? []).map((step) => ({
|
|
866
866
|
agent: step.agent,
|
|
@@ -1010,8 +1010,209 @@ function stopAsyncRun(state, runId, kill, location, childId) {
|
|
|
1010
1010
|
}
|
|
1011
1011
|
}
|
|
1012
1012
|
|
|
1013
|
+
// src/runs/foreground/foreground-history.ts
|
|
1014
|
+
import * as fs6 from "node:fs";
|
|
1015
|
+
import * as path6 from "node:path";
|
|
1016
|
+
var MAX_REMEMBERED_FOREGROUND_RUNS = 50;
|
|
1017
|
+
var FOREGROUND_OWNER_EXITED_STOP_ERROR = "Subagent stopped because the Pi process that ran it exited before the run finished.";
|
|
1018
|
+
var MAX_INLINE_OUTPUT_BYTES = 64 * 1024;
|
|
1019
|
+
var MAX_RESUME_CONTRACT_BYTES = 64 * 1024;
|
|
1020
|
+
function historyDir(resultsDir) {
|
|
1021
|
+
return path6.join(resultsDir, "foreground-history");
|
|
1022
|
+
}
|
|
1023
|
+
function runHistoryPath(resultsDir, runId) {
|
|
1024
|
+
return path6.join(historyDir(resultsDir), `${encodeIndexSegment(runId)}.json`);
|
|
1025
|
+
}
|
|
1026
|
+
function boundedTail(value) {
|
|
1027
|
+
return utf8Tail(value, MAX_INLINE_OUTPUT_BYTES).text;
|
|
1028
|
+
}
|
|
1029
|
+
function compactChild(child) {
|
|
1030
|
+
const outputPath = child.artifactPaths?.outputPath ?? child.savedOutputPath;
|
|
1031
|
+
return {
|
|
1032
|
+
agent: child.agent,
|
|
1033
|
+
index: child.index,
|
|
1034
|
+
...child.sessionName ? { sessionName: child.sessionName } : {},
|
|
1035
|
+
...child.context ? { context: child.context } : {},
|
|
1036
|
+
...child.sessionFile ? { sessionFile: child.sessionFile } : {},
|
|
1037
|
+
...child.model ? { model: child.model } : {},
|
|
1038
|
+
...child.thinking ? { thinking: child.thinking } : {},
|
|
1039
|
+
status: child.status,
|
|
1040
|
+
...child.activityState ? { activityState: child.activityState } : {},
|
|
1041
|
+
...child.lastActivityAt !== void 0 ? { lastActivityAt: child.lastActivityAt } : {},
|
|
1042
|
+
...child.currentTool ? { currentTool: child.currentTool } : {},
|
|
1043
|
+
...child.currentToolStartedAt !== void 0 ? { currentToolStartedAt: child.currentToolStartedAt } : {},
|
|
1044
|
+
...child.currentPath ? { currentPath: child.currentPath } : {},
|
|
1045
|
+
...child.turnCount !== void 0 ? { turnCount: child.turnCount } : {},
|
|
1046
|
+
...child.tokens !== void 0 ? { tokens: child.tokens } : {},
|
|
1047
|
+
...child.toolCount !== void 0 ? { toolCount: child.toolCount } : {},
|
|
1048
|
+
...child.exitCode !== void 0 ? { exitCode: child.exitCode } : {},
|
|
1049
|
+
...child.error ? { error: child.error } : {},
|
|
1050
|
+
...!outputPath && child.finalOutput ? { finalOutput: boundedTail(child.finalOutput) } : {},
|
|
1051
|
+
...child.outputState ? { outputState: child.outputState } : {},
|
|
1052
|
+
...child.outputPartial ? { outputPartial: true } : {},
|
|
1053
|
+
...child.outputMode ? { outputMode: child.outputMode } : {},
|
|
1054
|
+
...child.savedOutputPath ? { savedOutputPath: child.savedOutputPath } : {},
|
|
1055
|
+
...child.outputSaveError ? { outputSaveError: child.outputSaveError } : {},
|
|
1056
|
+
...child.artifactPaths ? { artifactPaths: child.artifactPaths } : {},
|
|
1057
|
+
...child.transcriptPath ? { transcriptPath: child.transcriptPath } : {},
|
|
1058
|
+
...child.transcriptError ? { transcriptError: child.transcriptError } : {},
|
|
1059
|
+
...child.acceptance ? { acceptance: child.acceptance } : {},
|
|
1060
|
+
...child.resumeContract ? { resumeContract: child.resumeContract } : {},
|
|
1061
|
+
...child.launchContractDigest ? { launchContractDigest: child.launchContractDigest } : {},
|
|
1062
|
+
...child.extensionBindings ? { extensionBindings: child.extensionBindings } : {},
|
|
1063
|
+
...child.requiredExtensions ? { requiredExtensions: child.requiredExtensions } : {},
|
|
1064
|
+
...child.capabilityCeiling ? { capabilityCeiling: child.capabilityCeiling } : {},
|
|
1065
|
+
...child.updatedAt !== void 0 ? { updatedAt: child.updatedAt } : {}
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
function isRestorableForegroundStatus(status) {
|
|
1069
|
+
return status === "completed" || status === "failed" || status === "paused" || status === "stopped";
|
|
1070
|
+
}
|
|
1071
|
+
function hasRunningChild(run) {
|
|
1072
|
+
return run.children.some((child) => child.status === "running");
|
|
1073
|
+
}
|
|
1074
|
+
function isAdmittedChildStatus(run, status) {
|
|
1075
|
+
return isRestorableForegroundStatus(status) || status === "running" && run.mode === "single" && isRecordedPid(run.owner);
|
|
1076
|
+
}
|
|
1077
|
+
function isRestorableResumeContract(value) {
|
|
1078
|
+
if (value === void 0) return true;
|
|
1079
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1080
|
+
try {
|
|
1081
|
+
if (Buffer.byteLength(JSON.stringify(value), "utf8") > MAX_RESUME_CONTRACT_BYTES) return false;
|
|
1082
|
+
validateModelResponseAliases(value?.modelResponseAliases);
|
|
1083
|
+
} catch {
|
|
1084
|
+
return false;
|
|
1085
|
+
}
|
|
1086
|
+
const contract = value;
|
|
1087
|
+
if (Object.keys(contract).some((key) => !["modelResponseAliases", "outputSchema", "agentContract", "acceptance", "output", "outputMode"].includes(key))) return false;
|
|
1088
|
+
if (contract.outputSchema !== void 0 && contract.outputSchema !== false && (!contract.outputSchema || typeof contract.outputSchema !== "object" || Array.isArray(contract.outputSchema))) return false;
|
|
1089
|
+
if (contract.agentContract !== void 0 && (!contract.agentContract || typeof contract.agentContract !== "object" || Array.isArray(contract.agentContract) || contract.agentContract.version !== 1)) return false;
|
|
1090
|
+
if (validateAcceptanceInput(contract.acceptance).length > 0) return false;
|
|
1091
|
+
if (contract.output !== void 0 && typeof contract.output !== "string" && typeof contract.output !== "boolean") return false;
|
|
1092
|
+
return contract.outputMode === void 0 || contract.outputMode === "inline" || contract.outputMode === "file-only";
|
|
1093
|
+
}
|
|
1094
|
+
function compactRun(run) {
|
|
1095
|
+
if (!run.sessionId) return void 0;
|
|
1096
|
+
if (run.children.length === 0 || !run.children.every((child) => isAdmittedChildStatus(run, child.status) && isRestorableResumeContract(child.resumeContract))) return void 0;
|
|
1097
|
+
const running = hasRunningChild(run);
|
|
1098
|
+
return {
|
|
1099
|
+
runId: run.runId,
|
|
1100
|
+
mode: run.mode,
|
|
1101
|
+
cwd: run.cwd,
|
|
1102
|
+
sessionId: run.sessionId,
|
|
1103
|
+
updatedAt: run.updatedAt,
|
|
1104
|
+
children: run.children.map(compactChild),
|
|
1105
|
+
...running ? { owner: run.owner } : {},
|
|
1106
|
+
...run.parentWorkflowRunId ? { parentWorkflowRunId: run.parentWorkflowRunId } : {}
|
|
1107
|
+
};
|
|
1108
|
+
}
|
|
1109
|
+
function readRunFile(filePath) {
|
|
1110
|
+
try {
|
|
1111
|
+
const parsed = JSON.parse(fs6.readFileSync(filePath, "utf-8"));
|
|
1112
|
+
return isRestorableRun(parsed) ? parsed : void 0;
|
|
1113
|
+
} catch {
|
|
1114
|
+
return void 0;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
function historyFiles(dir) {
|
|
1118
|
+
try {
|
|
1119
|
+
return fs6.readdirSync(dir).filter((name) => name.endsWith(".json"));
|
|
1120
|
+
} catch {
|
|
1121
|
+
return [];
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
function isRestorableRun(value) {
|
|
1125
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1126
|
+
const run = value;
|
|
1127
|
+
return typeof run.runId === "string" && Boolean(run.runId) && (run.mode === "single" || run.mode === "parallel" || run.mode === "chain") && typeof run.cwd === "string" && Boolean(run.cwd) && typeof run.sessionId === "string" && Boolean(run.sessionId) && typeof run.updatedAt === "number" && Number.isFinite(run.updatedAt) && Array.isArray(run.children) && run.children.length > 0 && (run.owner === void 0 || isRecordedPid(run.owner)) && (run.parentWorkflowRunId === void 0 || typeof run.parentWorkflowRunId === "string") && run.children.every((child) => Boolean(child && typeof child === "object" && !Array.isArray(child) && typeof child.agent === "string" && typeof child.index === "number" && isRestorableResumeContract(child.resumeContract) && isAdmittedChildStatus(run, child.status)));
|
|
1128
|
+
}
|
|
1129
|
+
function pruneHistory(dir, limit) {
|
|
1130
|
+
const files = historyFiles(dir);
|
|
1131
|
+
if (files.length <= limit) return;
|
|
1132
|
+
const byAge = files.flatMap((name) => {
|
|
1133
|
+
try {
|
|
1134
|
+
return [{ name, mtimeMs: fs6.statSync(path6.join(dir, name)).mtimeMs }];
|
|
1135
|
+
} catch {
|
|
1136
|
+
return [];
|
|
1137
|
+
}
|
|
1138
|
+
}).sort((left, right) => left.mtimeMs - right.mtimeMs);
|
|
1139
|
+
for (const { name, mtimeMs } of byAge.slice(0, byAge.length - limit)) {
|
|
1140
|
+
const filePath = path6.join(dir, name);
|
|
1141
|
+
const run = readRunFile(filePath);
|
|
1142
|
+
if (run && hasRunningChild(run) && !ownerConfirmedDead(run)) continue;
|
|
1143
|
+
try {
|
|
1144
|
+
if (fs6.statSync(filePath).mtimeMs !== mtimeMs) continue;
|
|
1145
|
+
} catch {
|
|
1146
|
+
continue;
|
|
1147
|
+
}
|
|
1148
|
+
fs6.rmSync(filePath, { force: true });
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
function persistForegroundRun(run, options = {}) {
|
|
1152
|
+
const compact = compactRun(run);
|
|
1153
|
+
if (!compact) return;
|
|
1154
|
+
const resultsDir = options.resultsDir ?? DIRS.results;
|
|
1155
|
+
const dir = historyDir(resultsDir);
|
|
1156
|
+
if (!fs6.existsSync(dir)) {
|
|
1157
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
1158
|
+
fs6.rmSync(path6.join(resultsDir, "foreground-history.json"), { force: true });
|
|
1159
|
+
}
|
|
1160
|
+
writePrivateAtomicJson(runHistoryPath(resultsDir, compact.runId), compact);
|
|
1161
|
+
pruneHistory(dir, options.limit ?? MAX_REMEMBERED_FOREGROUND_RUNS);
|
|
1162
|
+
}
|
|
1163
|
+
function discardRunningForegroundRun(runId, options = {}) {
|
|
1164
|
+
const filePath = runHistoryPath(options.resultsDir ?? DIRS.results, runId);
|
|
1165
|
+
const run = readRunFile(filePath);
|
|
1166
|
+
if (run && hasRunningChild(run) && run.owner?.pid === process.pid) fs6.rmSync(filePath, { force: true });
|
|
1167
|
+
}
|
|
1168
|
+
function ownerConfirmedDead(run) {
|
|
1169
|
+
return checkRecordedPidLiveness(run.owner) === "dead";
|
|
1170
|
+
}
|
|
1171
|
+
function restoreInterruptedRun(run) {
|
|
1172
|
+
if (!ownerConfirmedDead(run)) return void 0;
|
|
1173
|
+
const { owner: _owner, ...rest } = run;
|
|
1174
|
+
return {
|
|
1175
|
+
...rest,
|
|
1176
|
+
children: run.children.map((child) => {
|
|
1177
|
+
if (child.status !== "running") return child;
|
|
1178
|
+
const { activityState: _activityState, currentTool: _currentTool, currentToolStartedAt: _currentToolStartedAt, currentPath: _currentPath, sessionFile, ...stopped } = child;
|
|
1179
|
+
return {
|
|
1180
|
+
...stopped,
|
|
1181
|
+
status: "stopped",
|
|
1182
|
+
exitCode: 1,
|
|
1183
|
+
error: FOREGROUND_OWNER_EXITED_STOP_ERROR,
|
|
1184
|
+
finalOutput: FOREGROUND_OWNER_EXITED_STOP_ERROR,
|
|
1185
|
+
...sessionFile && fs6.existsSync(sessionFile) ? { sessionFile } : {}
|
|
1186
|
+
};
|
|
1187
|
+
})
|
|
1188
|
+
};
|
|
1189
|
+
}
|
|
1190
|
+
function foregroundChildStateLabel(run, child) {
|
|
1191
|
+
if (child.status !== "stopped" || child.error !== FOREGROUND_OWNER_EXITED_STOP_ERROR) return child.status;
|
|
1192
|
+
return child.sessionFile ? `interrupted when Pi exited \xB7 resume ${run.runId}` : "interrupted when Pi exited";
|
|
1193
|
+
}
|
|
1194
|
+
function restoreForegroundRunHistory(state, options = {}) {
|
|
1195
|
+
const sessionId = options.sessionId ?? state.currentSessionId;
|
|
1196
|
+
if (!sessionId) return 0;
|
|
1197
|
+
const dir = historyDir(options.resultsDir ?? DIRS.results);
|
|
1198
|
+
const saved = historyFiles(dir).flatMap((name) => readRunFile(path6.join(dir, name)) ?? []);
|
|
1199
|
+
if (options.observeForeign) {
|
|
1200
|
+
for (const run of saved) if (run.sessionId !== sessionId && hasRunningChild(run)) options.observeForeign(run);
|
|
1201
|
+
}
|
|
1202
|
+
const runs = saved.filter((run) => run.sessionId === sessionId).sort((left, right) => right.updatedAt - left.updatedAt).slice(0, options.limit ?? MAX_REMEMBERED_FOREGROUND_RUNS);
|
|
1203
|
+
state.foregroundRuns ??= /* @__PURE__ */ new Map();
|
|
1204
|
+
let restored = 0;
|
|
1205
|
+
for (const run of runs) {
|
|
1206
|
+
if (state.foregroundRuns.has(run.runId)) continue;
|
|
1207
|
+
const loaded = hasRunningChild(run) ? restoreInterruptedRun(run) : run;
|
|
1208
|
+
if (!loaded) continue;
|
|
1209
|
+
state.foregroundRuns.set(run.runId, loaded);
|
|
1210
|
+
restored += 1;
|
|
1211
|
+
}
|
|
1212
|
+
return restored;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1013
1215
|
export {
|
|
1014
|
-
currentCompletionOwnerId,
|
|
1015
1216
|
resolveGitRepositoryIdentity,
|
|
1016
1217
|
resolveWorkflowChatProgress,
|
|
1017
1218
|
buildWorkflowChatProgressRows,
|
|
@@ -1023,5 +1224,11 @@ export {
|
|
|
1023
1224
|
formatAsyncResultTranscript,
|
|
1024
1225
|
resolveSubagentRunId,
|
|
1025
1226
|
deliverAsyncRunStop,
|
|
1026
|
-
stopAsyncRun
|
|
1227
|
+
stopAsyncRun,
|
|
1228
|
+
MAX_REMEMBERED_FOREGROUND_RUNS,
|
|
1229
|
+
persistForegroundRun,
|
|
1230
|
+
discardRunningForegroundRun,
|
|
1231
|
+
ownerConfirmedDead,
|
|
1232
|
+
foregroundChildStateLabel,
|
|
1233
|
+
restoreForegroundRunHistory
|
|
1027
1234
|
};
|
|
@@ -6,33 +6,35 @@ import {
|
|
|
6
6
|
resolveWorkflowForegroundSteeringTarget,
|
|
7
7
|
steerAsyncRun,
|
|
8
8
|
steerWorkflowForegroundTarget
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-7IVSUMQQ.js";
|
|
10
10
|
import {
|
|
11
11
|
FLEET_STATUS_WIDGET_KEY,
|
|
12
12
|
reportFleetWarning,
|
|
13
|
-
runningTone
|
|
14
|
-
|
|
13
|
+
runningTone,
|
|
14
|
+
stepTaskSummary
|
|
15
|
+
} from "./chunk-M2CTFYT3.js";
|
|
15
16
|
import {
|
|
17
|
+
foregroundChildStateLabel,
|
|
16
18
|
formatAsyncRunTranscript,
|
|
17
19
|
stopAsyncRun
|
|
18
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-7PCKZHR5.js";
|
|
19
21
|
import {
|
|
20
22
|
contextModeBadge,
|
|
21
23
|
contextModeLabel,
|
|
22
24
|
decodeUtf8Tail,
|
|
23
25
|
listAsyncRuns
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
26
|
-
import "./chunk-
|
|
26
|
+
} from "./chunk-VH5OAWVG.js";
|
|
27
|
+
import "./chunk-NRQ75MGH.js";
|
|
28
|
+
import "./chunk-OYF6AFDY.js";
|
|
27
29
|
import "./chunk-NIXWDZZV.js";
|
|
28
|
-
import "./chunk-
|
|
30
|
+
import "./chunk-XSWOTIA3.js";
|
|
29
31
|
import "./chunk-7F6RKT6W.js";
|
|
30
32
|
import "./chunk-CTPAE36Y.js";
|
|
31
33
|
import "./chunk-7J4ZXMY7.js";
|
|
32
34
|
import {
|
|
33
35
|
getArtifactPaths,
|
|
34
36
|
getArtifactsDir
|
|
35
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-5TYMSZX3.js";
|
|
36
38
|
import {
|
|
37
39
|
snapshotExternalRuns
|
|
38
40
|
} from "./chunk-UKG4V45O.js";
|
|
@@ -44,7 +46,7 @@ import {
|
|
|
44
46
|
formatTokens,
|
|
45
47
|
readStatus,
|
|
46
48
|
shortenPath
|
|
47
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-CIZQXJ5Q.js";
|
|
48
50
|
import {
|
|
49
51
|
DIRS
|
|
50
52
|
} from "./chunk-5LFLVSTM.js";
|
|
@@ -203,18 +205,22 @@ function asyncItems(run, description) {
|
|
|
203
205
|
if (run.steps.length === 0 || run.mode === "workflow") {
|
|
204
206
|
return [{ key: `async:${run.id}`, kind: "async", runId: run.id, agent: run.mode, state: run.state, updatedAt, run, ...description ? { description } : {} }];
|
|
205
207
|
}
|
|
206
|
-
return run.steps.map((step) =>
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
208
|
+
return run.steps.map((step) => {
|
|
209
|
+
const task = stepTaskSummary(step, step.agent);
|
|
210
|
+
return {
|
|
211
|
+
key: `async:${run.id}:${step.index}`,
|
|
212
|
+
kind: "async",
|
|
213
|
+
runId: run.id,
|
|
214
|
+
index: step.index,
|
|
215
|
+
agent: step.label ? `${step.label} (${step.agent})` : step.agent,
|
|
216
|
+
state: step.status,
|
|
217
|
+
updatedAt: step.lastActivityAt ?? updatedAt,
|
|
218
|
+
run,
|
|
219
|
+
step,
|
|
220
|
+
...task ? { task } : {},
|
|
221
|
+
...description ? { description } : {}
|
|
222
|
+
};
|
|
223
|
+
});
|
|
218
224
|
}
|
|
219
225
|
function orderFleetAsyncRuns(runs, terminalLimit, trackedJobs) {
|
|
220
226
|
const updatedAt = (run) => run.lastUpdate ?? run.endedAt ?? run.startedAt;
|
|
@@ -503,7 +509,7 @@ function foregroundRecentDetail(item, state) {
|
|
|
503
509
|
const lines = [
|
|
504
510
|
`Run: ${item.runId}`,
|
|
505
511
|
"Source: foreground",
|
|
506
|
-
`State: ${child
|
|
512
|
+
`State: ${foregroundChildStateLabel(run, child)}`,
|
|
507
513
|
`Mode: ${run.mode}`,
|
|
508
514
|
`Child: ${child.index} (${child.agent})${contextModeLabel(child.context) ? ` ${contextModeLabel(child.context)}` : ""}`,
|
|
509
515
|
modelThinking ? `Model: ${modelThinking}` : void 0,
|
|
@@ -1179,8 +1185,10 @@ var SubagentFleetComponent = class {
|
|
|
1179
1185
|
const item = this.snapshot.items[index];
|
|
1180
1186
|
const marker = index === this.selected ? this.theme.fg("accent", "\u203A") : " ";
|
|
1181
1187
|
const context = item.kind === "async" ? contextModeBadge(this.theme, item.step?.context ?? item.run.context) : item.kind === "foreground-recent" ? contextModeBadge(this.theme, item.child.context) : "";
|
|
1182
|
-
const
|
|
1183
|
-
const
|
|
1188
|
+
const task = item.kind === "async" ? item.task : void 0;
|
|
1189
|
+
const name = task && item.kind === "async" && item.step ? item.step.agent : item.agent;
|
|
1190
|
+
const agent = index === this.selected ? this.theme.bold(name) : name;
|
|
1191
|
+
const identity = task ?? item.runId.slice(0, 8);
|
|
1184
1192
|
const left = `${marker} ${statusGlyph(item, this.theme)} ${agent}${context} ${this.theme.fg("dim", `\xB7 ${identity}`)}`;
|
|
1185
1193
|
return rightAligned(left, this.theme.fg("dim", item.state), layout.roster.width);
|
|
1186
1194
|
});
|