@bastani/atomic 0.9.58-alpha.1 → 0.9.59-alpha.1
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 +27 -0
- package/dist/builtin/intercom/CHANGELOG.md +12 -0
- package/dist/builtin/intercom/broker/spawn.ts +22 -2
- package/dist/builtin/intercom/index.bundle.mjs +11 -2
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +6 -0
- package/dist/builtin/subagents/README.md +3 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/src/extension/index.bundle.mjs +163 -33
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +11 -2
- package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +11 -2
- package/dist/builtin/workflows/src/index.js +11 -2
- package/dist/builtin/workflows/src/local-worker-entry.mjs +11 -2
- package/dist/core/child-session-options.d.ts.map +1 -1
- package/dist/core/child-session-options.js +3 -1
- package/dist/core/child-session-options.js.map +1 -1
- package/dist/core/model-runtime-providers.d.ts +2 -2
- package/dist/core/model-runtime-providers.d.ts.map +1 -1
- package/dist/core/model-runtime-providers.js +8 -4
- package/dist/core/model-runtime-providers.js.map +1 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +1 -1
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/sdk-types.d.ts +6 -1
- package/dist/core/sdk-types.d.ts.map +1 -1
- package/dist/core/sdk-types.js.map +1 -1
- package/dist/core/sdk.js +4 -2
- package/dist/core/sdk.js.map +1 -1
- package/docs/providers.md +6 -6
- package/docs/sdk.md +3 -1
- package/docs/subagents/reference.md +2 -0
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.59] - 2026-11-01
|
|
6
|
+
|
|
7
|
+
GitHub Copilot tokens that work from `/login`, and intercom that recovers on Windows.
|
|
8
|
+
|
|
9
|
+
- **Copilot tokens saved through `/login`:** a GitHub Copilot personal access token saved with `/login` → **Use an API key** now works for business and enterprise accounts, so you no longer need `COPILOT_GITHUB_TOKEN` to avoid `421 Misdirected Request` ([#4151](https://github.com/bastani-inc/atomic/pull/4151))
|
|
10
|
+
- **Intercom recovers on Windows:** when the intercom broker dies, sessions start a new one right away instead of waiting out the start-up timeout and failing with `Broker failed to start within timeout` ([#4152](https://github.com/bastani-inc/atomic/pull/4152))
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Fixed GitHub Copilot personal access tokens saved through `/login` → **Use an API key** being sent to the individual Copilot host, where business and enterprise accounts fail with `421 Misdirected Request`. Saved tokens now get the same endpoint routing as `COPILOT_GITHUB_TOKEN`, so the environment variable is no longer required. A `models.json` `baseUrl` still takes precedence, and OAuth logins are unchanged. ([#4151](https://github.com/bastani-inc/atomic/pull/4151))
|
|
15
|
+
|
|
16
|
+
## [0.9.59-alpha.1] - 2026-11-01
|
|
17
|
+
|
|
18
|
+
GitHub Copilot tokens that work from `/login`, and intercom that recovers on Windows.
|
|
19
|
+
|
|
20
|
+
- **Copilot tokens saved through `/login`:** a GitHub Copilot personal access token saved with `/login` → **Use an API key** now works for business and enterprise accounts, so you no longer need `COPILOT_GITHUB_TOKEN` to avoid `421 Misdirected Request` ([#4151](https://github.com/bastani-inc/atomic/pull/4151))
|
|
21
|
+
- **Intercom recovers on Windows:** when the intercom broker dies, sessions start a new one right away instead of waiting out the start-up timeout and failing with `Broker failed to start within timeout` ([#4152](https://github.com/bastani-inc/atomic/pull/4152))
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Fixed GitHub Copilot personal access tokens saved through `/login` → **Use an API key** being sent to the individual Copilot host, where business and enterprise accounts fail with `421 Misdirected Request`. Saved tokens now get the same endpoint routing as `COPILOT_GITHUB_TOKEN`, so the environment variable is no longer required. A `models.json` `baseUrl` still takes precedence, and OAuth logins are unchanged. ([#4151](https://github.com/bastani-inc/atomic/pull/4151))
|
|
26
|
+
|
|
5
27
|
## [0.9.58] - 2026-11-01
|
|
6
28
|
|
|
7
29
|
Task heartbeats, stage chats that work on local workers, and a local worker pool that holds up under load.
|
|
@@ -11,6 +33,7 @@ Task heartbeats, stage chats that work on local workers, and a local worker pool
|
|
|
11
33
|
- **A local worker pool that holds up under load:** reloading workflows or starting other runs no longer fails a running root's children with `Stale lease for run <id>`, a busy machine no longer fails stages on delivery or lease errors, `/workflow pause` pauses a root's stages even while its own steps run, and an overloaded machine starts stages one at a time, tunable with `workflows.localWorkers.maxLoadPerCpu` ([#4138](https://github.com/bastani-inc/atomic/pull/4138), [#4145](https://github.com/bastani-inc/atomic/pull/4145), [#4146](https://github.com/bastani-inc/atomic/pull/4146))
|
|
12
34
|
- **Resuming pooled runs:** a root that runs children on local workers resumes from a new process, including one paused or failed by 0.9.57, and runs again the children that failed on a pool fault instead of replaying the failure ([#4146](https://github.com/bastani-inc/atomic/pull/4146))
|
|
13
35
|
- **Stopped tasks finish:** a shell stopped with `kill`, from `/tasks` or with Esc no longer stays "stopping" in the Tasks indicator forever; it ends as failed with the resource that could not be cleaned up ([#4142](https://github.com/bastani-inc/atomic/pull/4142))
|
|
36
|
+
- **Subagents that start and run as asked:** a subagent launched with an effort such as `model: "openai/gpt-5.5:xhigh"`, or from a chat turn that a workflow started, no longer stays `running` with no session, and one whose session still does not start within 5 minutes fails with the cause. An effort applies exactly where the model supports it, including on a fallback that starts in place of the requested model, and `status` lists only the children your session launched ([#4148](https://github.com/bastani-inc/atomic/pull/4148), [#4150](https://github.com/bastani-inc/atomic/pull/4150))
|
|
14
37
|
- **Quieter PDF fetches:** pdf.js font warnings such as `Warning: TT: undefined function: 32` no longer print over the terminal UI when a PDF is fetched ([#4136](https://github.com/bastani-inc/atomic/pull/4136))
|
|
15
38
|
|
|
16
39
|
### Added
|
|
@@ -27,6 +50,10 @@ Task heartbeats, stage chats that work on local workers, and a local worker pool
|
|
|
27
50
|
- `/workflow pause` pauses a root's stages on local workers even while the root's own steps run, instead of reporting `No active stages to pause`, and pause or resume no longer fails with `Worker control acknowledgement unresolved` on a busy machine; the result says how many stages have not confirmed the pause yet. ([#4145](https://github.com/bastani-inc/atomic/pull/4145))
|
|
28
51
|
- Resuming a workflow root that runs children on local workers, including one paused or failed by 0.9.57, runs again the children an earlier process failed on a fault of the pool itself instead of replaying their failure, and a paused root with durable progress says it can be resumed from a new process. ([#4146](https://github.com/bastani-inc/atomic/pull/4146))
|
|
29
52
|
- On an overloaded machine, stages of workflow children on local workers start one at a time, at most one every 5 seconds, instead of all at once while earlier ones are still starting. Tune or turn off with `workflows.localWorkers.maxLoadPerCpu` (default `3`, `0` off). ([#4146](https://github.com/bastani-inc/atomic/pull/4146))
|
|
53
|
+
- A subagent launched from a chat turn that a running workflow started, for example with its completion notice, no longer stays `running` for good with no session, transcript or Intercom name. Its session waited for a permit from that workflow's resource admission (such as `admission.host.minFreeMemoryBytes` on a busy host) that it never received. A child session built from `getChildSessionOptions()` now takes its parent's admission or none, never one a `withResourceAdmission` scope the parent's turn happened to run in; SDK callers can pass `resourceAdmission: null` for a session that takes no permit inside such a scope. ([#4148](https://github.com/bastani-inc/atomic/pull/4148))
|
|
54
|
+
- A subagent whose session does not start within 5 minutes now fails with `Subagent session did not start within 5 min (still <step>)` instead of staying `running`, and `subagent({ action: "status" })` shows it failed with that cause, in its text and its expanded card. ([#4148](https://github.com/bastani-inc/atomic/pull/4148), [#4150](https://github.com/bastani-inc/atomic/pull/4150))
|
|
55
|
+
- A subagent launched with an effort, such as `model: "openai/gpt-5.5:xhigh"`, runs at exactly that effort on a model that supports it, and at that model's default level (its `modelThinkingLevels` entry, else `defaultThinkingLevel`) on one that does not, instead of the nearest level. A model its fallback chain switches to follows the same rule, so a fallback no longer drops the child to the default level silently, and a fallback the child starts on because the requested model's provider has no auth runs at its own effort. ([#4148](https://github.com/bastani-inc/atomic/pull/4148), [#4150](https://github.com/bastani-inc/atomic/pull/4150))
|
|
56
|
+
- `subagent({ action: "status" })` lists only the children this session launched, each with the child id `pause`, `resume` and `quit` take (`· id <run-id>:<n>`), and those actions also take the listed path. It no longer lists children of other sessions in the same process, such as a workflow stage's, that `quit` then refused with `this session launched no such child`, and `status` with a child id finds the child. ([#4148](https://github.com/bastani-inc/atomic/pull/4148))
|
|
30
57
|
|
|
31
58
|
## [0.9.58-alpha.1] - 2026-11-01
|
|
32
59
|
|
|
@@ -4,6 +4,18 @@ All notable changes to the `pi-intercom` extension will be documented in this fi
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.9.59] - 2026-11-01
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- On Windows, sessions reconnect to a new intercom broker right after the running one dies, instead of waiting out the whole broker start-up timeout and failing with `Broker failed to start within timeout`. The dead broker's hidden `cmd.exe` launcher holds `broker.log` for a moment after the broker exits, and the respawn mistook that for another broker still starting; it now waits up to a second for the log to be released first. ([#4152](https://github.com/bastani-inc/atomic/pull/4152))
|
|
12
|
+
|
|
13
|
+
## [0.9.59-alpha.1] - 2026-11-01
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- On Windows, sessions reconnect to a new intercom broker right after the running one dies, instead of waiting out the whole broker start-up timeout and failing with `Broker failed to start within timeout`. The dead broker's hidden `cmd.exe` launcher holds `broker.log` for a moment after the broker exits, and the respawn mistook that for another broker still starting; it now waits up to a second for the log to be released first. ([#4152](https://github.com/bastani-inc/atomic/pull/4152))
|
|
18
|
+
|
|
7
19
|
## [0.9.56] - 2026-10-30
|
|
8
20
|
|
|
9
21
|
### Fixed
|
|
@@ -291,9 +291,15 @@ export function getBrokerSpawnOptions(
|
|
|
291
291
|
};
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
+
/**
|
|
295
|
+
* How long a spawn waits for the Windows launcher of a broker that just exited to let go of the log. Its `cmd.exe`
|
|
296
|
+
* outlives the broker by a moment, and a broker that is really still starting keeps the log for as long as it runs.
|
|
297
|
+
*/
|
|
298
|
+
export const BROKER_LOG_RELEASE_WAIT_MS = 1_000;
|
|
299
|
+
|
|
294
300
|
/**
|
|
295
301
|
* Preserve a bounded previous log across truncation. Returns false when a
|
|
296
|
-
* Windows
|
|
302
|
+
* Windows launcher holds the log through its stderr redirect.
|
|
297
303
|
*/
|
|
298
304
|
function resetBrokerLog(logPath: string = BROKER_LOG): boolean {
|
|
299
305
|
ensurePrivateDirectory(dirname(logPath));
|
|
@@ -315,6 +321,20 @@ function resetBrokerLog(logPath: string = BROKER_LOG): boolean {
|
|
|
315
321
|
}
|
|
316
322
|
}
|
|
317
323
|
|
|
324
|
+
/**
|
|
325
|
+
* Reset the log, waiting up to {@link BROKER_LOG_RELEASE_WAIT_MS} for the launcher of a broker that just exited, as
|
|
326
|
+
* one does when a running broker dies and its clients reconnect at once. Returns false only when the log stays held,
|
|
327
|
+
* which means a broker is still starting.
|
|
328
|
+
*/
|
|
329
|
+
async function resetBrokerLogOnceReleased(): Promise<boolean> {
|
|
330
|
+
const deadline = Date.now() + BROKER_LOG_RELEASE_WAIT_MS;
|
|
331
|
+
while (!resetBrokerLog()) {
|
|
332
|
+
if (Date.now() >= deadline) return false;
|
|
333
|
+
await sleep(50);
|
|
334
|
+
}
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
|
|
318
338
|
/** Read at most {@link BROKER_LOG_TAIL_BYTES} trailing bytes of the broker log. */
|
|
319
339
|
export function readBrokerLogTail(logPath: string = BROKER_LOG, maxBytes: number = BROKER_LOG_TAIL_BYTES): string {
|
|
320
340
|
let fd: number | undefined;
|
|
@@ -392,7 +412,7 @@ export async function spawnBrokerIfNeeded(
|
|
|
392
412
|
writeWindowsHiddenLauncher(launch.launcherCommandLine, launch.launcherPath);
|
|
393
413
|
}
|
|
394
414
|
// Reset before spawning either way: the Windows launcher appends to this same path.
|
|
395
|
-
if (!
|
|
415
|
+
if (!(await resetBrokerLogOnceReleased())) {
|
|
396
416
|
await waitForBroker(readyTimeoutMs);
|
|
397
417
|
return;
|
|
398
418
|
}
|
|
@@ -2487,6 +2487,15 @@ function resetBrokerLog(logPath = BROKER_LOG) {
|
|
|
2487
2487
|
throw error;
|
|
2488
2488
|
}
|
|
2489
2489
|
}
|
|
2490
|
+
async function resetBrokerLogOnceReleased() {
|
|
2491
|
+
const deadline = Date.now() + BROKER_LOG_RELEASE_WAIT_MS;
|
|
2492
|
+
while (!resetBrokerLog()) {
|
|
2493
|
+
if (Date.now() >= deadline)
|
|
2494
|
+
return false;
|
|
2495
|
+
await sleep(50);
|
|
2496
|
+
}
|
|
2497
|
+
return true;
|
|
2498
|
+
}
|
|
2490
2499
|
function readBrokerLogTail(logPath = BROKER_LOG, maxBytes = BROKER_LOG_TAIL_BYTES) {
|
|
2491
2500
|
let fd;
|
|
2492
2501
|
try {
|
|
@@ -2545,7 +2554,7 @@ async function spawnBrokerIfNeeded(brokerCommand, brokerArgs, readyTimeoutMs = B
|
|
|
2545
2554
|
if (launch.kind === "windows-launcher") {
|
|
2546
2555
|
writeWindowsHiddenLauncher(launch.launcherCommandLine, launch.launcherPath);
|
|
2547
2556
|
}
|
|
2548
|
-
if (!
|
|
2557
|
+
if (!await resetBrokerLogOnceReleased()) {
|
|
2549
2558
|
await waitForBroker(readyTimeoutMs);
|
|
2550
2559
|
return;
|
|
2551
2560
|
}
|
|
@@ -2718,7 +2727,7 @@ ${describeBrokerLog()}`);
|
|
|
2718
2727
|
` + "The broker did not answer on its socket in time; it may still be starting, which a busy machine or an empty jiti " + "cache slows. Try again, or raise `brokerStartupTimeoutMs` in the Intercom config.json (default " + `${BROKER_READY_TIMEOUT_MS} ms).
|
|
2719
2728
|
${describeBrokerLog()}`);
|
|
2720
2729
|
}
|
|
2721
|
-
var INTERCOM_DIR, EXTENSION_DIR, BROKER_SOCKET2, BROKER_PID, BROKER_SPAWN_LOCK, BROKER_LOG, BROKER_START_ANNOUNCEMENT, BROKER_LOG_TAIL_BYTES, BROKER_POLL_INITIAL_INTERVAL_MS = 10, BROKER_POLL_MAX_INTERVAL_MS = 100, BROKER_SPAWN_LOCK_MAX_AGE_MS = 60000, INTERNAL_INTERCOM_BROKER_ARG = "--atomic-internal-intercom-broker";
|
|
2730
|
+
var INTERCOM_DIR, EXTENSION_DIR, BROKER_SOCKET2, BROKER_PID, BROKER_SPAWN_LOCK, BROKER_LOG, BROKER_START_ANNOUNCEMENT, BROKER_LOG_TAIL_BYTES, BROKER_POLL_INITIAL_INTERVAL_MS = 10, BROKER_POLL_MAX_INTERVAL_MS = 100, BROKER_SPAWN_LOCK_MAX_AGE_MS = 60000, INTERNAL_INTERCOM_BROKER_ARG = "--atomic-internal-intercom-broker", BROKER_LOG_RELEASE_WAIT_MS = 1000;
|
|
2722
2731
|
var init_spawn = __esm(() => {
|
|
2723
2732
|
init_socket_liveness();
|
|
2724
2733
|
init_start_announcement();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/intercom",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.59-alpha.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension providing a private coordination channel between parent and child agent sessions. Fork of: https://github.com/nicobailon/pi-intercom",
|
|
6
6
|
"contributors": [
|
|
@@ -8,6 +8,12 @@
|
|
|
8
8
|
|
|
9
9
|
- Running subagents now send the parent periodic task heartbeats (every 15 minutes by default) with their current tool call, time since their last activity, and turn, tool-call and token counts. Set `heartbeatMs` on a `subagent` call, or on a `tasks` entry, to change a child's cadence; `0` turns it off.
|
|
10
10
|
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- A subagent launched from a chat turn that a running workflow started no longer stays `running` for good with no session: its session no longer waits on that workflow's resource admission. A subagent whose session still does not start within 5 minutes fails with `Subagent session did not start within 5 min (still <step>)`, and `status` shows the cause in its text and its expanded card. ([#4148](https://github.com/bastani-inc/atomic/pull/4148), [#4150](https://github.com/bastani-inc/atomic/pull/4150))
|
|
14
|
+
- A subagent launched with an effort, such as `model: "openai/gpt-5.5:xhigh"`, runs at exactly that effort on a model that supports it, and at that model's default level on one that does not; each model in its fallback chain follows the same rule instead of falling back to the default level, including a fallback the child starts on in place of a requested model whose provider has no auth. ([#4148](https://github.com/bastani-inc/atomic/pull/4148), [#4150](https://github.com/bastani-inc/atomic/pull/4150))
|
|
15
|
+
- `status` lists only the children this session launched, with the child id `pause`, `resume` and `quit` take, and those actions also take the listed path; `status` with a child id finds the child. ([#4148](https://github.com/bastani-inc/atomic/pull/4148))
|
|
16
|
+
|
|
11
17
|
## [0.9.58-alpha.1] - 2026-11-01
|
|
12
18
|
|
|
13
19
|
### Added
|
|
@@ -570,6 +570,8 @@ subagent({ action: "quit", id: "<child-id>" })
|
|
|
570
570
|
subagent({ action: "quit", all: true })
|
|
571
571
|
```
|
|
572
572
|
|
|
573
|
+
`status` lists the children this session launched that are still in this process, each as `<run-id>/<agent>_<n> — <state> (loaded|cold) · id <child-id>`, with the cause of a failed or interrupted child after it; `pause`, `resume` and `quit` take the child id or that path, and `status` takes either to show one child. Children other sessions in the same process launched, such as a workflow stage's, are not listed, since this session cannot control them. A child whose session has not started within 5 minutes fails with `Subagent session did not start within 5 min (still <step>)` instead of staying running.
|
|
574
|
+
|
|
573
575
|
`pause` stops a child and holds its queued messages until `resume`; `quit` stops it gracefully, including a child already paused by you or with its workflow stage. Both stay resumable while the session or workflow stage that launched the child can still resume it, as do children stopped because their workflow stage was paused or quit, including by Atomic exiting or a session switch. `resume` reopens the child's own session under the same id and Intercom name. A paused, quit, or interrupted child receives `message` once as its next prompt and then continues where it left off; a completed or failed child receives `message` as one fresh prompt. Without `message`, every resumable child, including a completed or failed one, is asked to continue where it left off. Children cancelled for good (owner or batch cancellation, including a `/tasks` stop, and the removed `kill` action), children whose workflow stage ended (the stage finished, or its run ended or was cancelled; this covers all of that stage's children, including ones you paused or quit), and children reported gone after a restart cannot be resumed: `resume` returns an error that says why, and follow-up work requires a fresh launch with explicit context. A parallel child waiting for a reply is not terminal and continues in its original execution. Parent cancellation of a still-running child uses the interrupted/abort state: receipts and progress present it as cancelled rather than failed, persisted metadata keeps the abort cause, and bounded partial findings remain available. Migrate old subagent calls from `action: "kill"` or `action: "interrupt"` to `action: "quit"`; the old actions are rejected with `The subagent action "kill" was removed. Use { action: "quit", id } to stop a child gracefully; it stays resumable with { action: "resume", id, message? }.` (naming the action that was used). Host interrupt APIs are unchanged.
|
|
574
576
|
|
|
575
577
|
## Worktree isolation
|
|
@@ -814,7 +816,7 @@ The main runtime files are:
|
|
|
814
816
|
|
|
815
817
|
### Suffix-first reasoning levels
|
|
816
818
|
|
|
817
|
-
Reasoning levels are configured suffix-first using the `model_name:thinking_effort` syntax on `model` and each `fallbackModels` entry: `model: claude-sonnet-4:high` and `fallbackModels: claude-sonnet-4:medium, gpt-5:low, claude-haiku-4:off`. Canonical efforts are `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`. `xhigh`
|
|
819
|
+
Reasoning levels are configured suffix-first using the `model_name:thinking_effort` syntax on `model` and each `fallbackModels` entry: `model: claude-sonnet-4:high` and `fallbackModels: claude-sonnet-4:medium, gpt-5:low, claude-haiku-4:off`. Canonical efforts are `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`. A child runs at exactly the effort it was launched with on a model that supports it; a model that does not support it, `xhigh` or `max` on many models, runs at its own default level instead (its `modelThinkingLevels` setting, else `defaultThinkingLevel`). Fallback models follow the same rule, using their own suffix or, without one, the launch's effort. The older `thinking` field is deprecated; it remains supported as a legacy default only when a model candidate has no suffix, and a suffix always wins.
|
|
818
820
|
|
|
819
821
|
Migrate legacy `thinking` frontmatter by folding the effort into `model` and `fallbackModels`:
|
|
820
822
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/subagents",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.59-alpha.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for delegating tasks to subagents with parallel execution. Fork of: https://github.com/nicobailon/pi-subagents",
|
|
6
6
|
"contributors": [
|
|
@@ -8939,6 +8939,13 @@ function subagentChildCardRecord(childId, taskId) {
|
|
|
8939
8939
|
const id = childId ?? childIdsByTaskId.get(taskId);
|
|
8940
8940
|
return id === undefined ? undefined : latest.get(id);
|
|
8941
8941
|
}
|
|
8942
|
+
function observedSubagentRunIds(ownerSessionId) {
|
|
8943
|
+
const runIds = new Set;
|
|
8944
|
+
for (const record of latest.values())
|
|
8945
|
+
if (record.owner?.sessionId === ownerSessionId)
|
|
8946
|
+
runIds.add(record.runId);
|
|
8947
|
+
return runIds;
|
|
8948
|
+
}
|
|
8942
8949
|
function watchSubagentChildCard(card, invalidate, key, ownerSessionId) {
|
|
8943
8950
|
invalidators.set(card, invalidate);
|
|
8944
8951
|
const cards = watchers.get(key) ?? new Set;
|
|
@@ -11825,7 +11832,10 @@ import {
|
|
|
11825
11832
|
import {
|
|
11826
11833
|
SubagentControl
|
|
11827
11834
|
} from "@bastani/atomic-natives";
|
|
11828
|
-
import {
|
|
11835
|
+
import {
|
|
11836
|
+
clampThinkingLevel,
|
|
11837
|
+
getSupportedThinkingLevels
|
|
11838
|
+
} from "@bastani/pi-ai/compat";
|
|
11829
11839
|
|
|
11830
11840
|
// dist/builtin/subagents/src/agents/skills.ts
|
|
11831
11841
|
import * as fs14 from "node:fs";
|
|
@@ -12566,6 +12576,23 @@ function createInProcessChildPromptBehavior(policy) {
|
|
|
12566
12576
|
}
|
|
12567
12577
|
|
|
12568
12578
|
// dist/builtin/subagents/src/runs/inprocess/runner.ts
|
|
12579
|
+
var SUBAGENT_SESSION_START_TIMEOUT_MS = 5 * 60000;
|
|
12580
|
+
function formatStartTimeout(ms) {
|
|
12581
|
+
return ms % 60000 === 0 ? `${ms / 60000} min` : `${Math.max(1, Math.round(ms / 1000))}s`;
|
|
12582
|
+
}
|
|
12583
|
+
var DEFAULT_THINKING_LEVEL = "medium";
|
|
12584
|
+
function explicitEffortFor(model, requested, settings) {
|
|
12585
|
+
if (getSupportedThinkingLevels(model).includes(requested))
|
|
12586
|
+
return requested;
|
|
12587
|
+
return clampThinkingLevel(model, settings.getModelThinkingLevel(model.provider, model.id) ?? settings.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL);
|
|
12588
|
+
}
|
|
12589
|
+
function pinFallbackEffort(entry, requested, settings, resolve) {
|
|
12590
|
+
const resolved = resolve?.(entry);
|
|
12591
|
+
if (!resolved)
|
|
12592
|
+
return entry;
|
|
12593
|
+
const { baseModel } = splitKnownThinkingSuffix(entry.trim());
|
|
12594
|
+
return `${baseModel}:${explicitEffortFor(resolved.model, resolved.thinkingLevel ?? requested, settings)}`;
|
|
12595
|
+
}
|
|
12569
12596
|
function modelIdForCandidate(candidate, fallbackModel) {
|
|
12570
12597
|
return candidate.modelId ?? (candidate.model ? `${candidate.model.provider}/${candidate.model.id}` : undefined) ?? (fallbackModel ? `${fallbackModel.provider}/${fallbackModel.id}` : undefined);
|
|
12571
12598
|
}
|
|
@@ -13018,12 +13045,23 @@ class SubagentControlRuntime {
|
|
|
13018
13045
|
delivered = new Set;
|
|
13019
13046
|
deliveredEnvelopes = new Map;
|
|
13020
13047
|
killedChildren = new Set;
|
|
13048
|
+
childIds = new Map;
|
|
13021
13049
|
nextAttemptId = 1;
|
|
13022
13050
|
constructor(parent, sessionRoot, runningCapacity) {
|
|
13023
13051
|
this.parent = { ...parent };
|
|
13024
13052
|
this.sessionRoot = trustedSessionRoot(this.parent, sessionRoot);
|
|
13025
13053
|
this.native = new SubagentControl(this.parent.path, runningCapacity);
|
|
13026
13054
|
}
|
|
13055
|
+
childIdOf(pathValue) {
|
|
13056
|
+
return this.childIds.get(pathValue);
|
|
13057
|
+
}
|
|
13058
|
+
pathOfChildId(childId) {
|
|
13059
|
+
let latest;
|
|
13060
|
+
for (const [pathValue, id] of this.childIds)
|
|
13061
|
+
if (id === childId)
|
|
13062
|
+
latest = pathValue;
|
|
13063
|
+
return latest;
|
|
13064
|
+
}
|
|
13027
13065
|
registerAgents(agents) {
|
|
13028
13066
|
for (const agent of agents)
|
|
13029
13067
|
this.native.registerAgent(agent.name);
|
|
@@ -13041,6 +13079,8 @@ class SubagentControlRuntime {
|
|
|
13041
13079
|
if (!native.child)
|
|
13042
13080
|
return refusal(native);
|
|
13043
13081
|
const identity = native.child;
|
|
13082
|
+
if (spec.childId !== undefined)
|
|
13083
|
+
this.childIds.set(identity.path, spec.childId);
|
|
13044
13084
|
const childModePolicy = resolveChildModePolicy(spec);
|
|
13045
13085
|
const sessionDir = spec.sessionManager?.getSessionDir() || sessionDirectory(this.sessionRoot, identity.path);
|
|
13046
13086
|
mkdirSync7(sessionDir, { recursive: true });
|
|
@@ -13183,9 +13223,34 @@ class SubagentControlRuntime {
|
|
|
13183
13223
|
signals.interrupt.addEventListener("abort", interruptListener, {
|
|
13184
13224
|
once: true
|
|
13185
13225
|
});
|
|
13226
|
+
const startTimeoutMs = admitted.spec.sessionStartTimeoutMs ?? SUBAGENT_SESSION_START_TIMEOUT_MS;
|
|
13227
|
+
const startDeadline = new AbortController;
|
|
13228
|
+
let startPhase = "opening its session";
|
|
13229
|
+
const startTimer = setTimeout(() => startDeadline.abort(new Error(`Subagent session did not start within ${formatStartTimeout(startTimeoutMs)} (still ${startPhase}); it was stopped before its task ran.`)), startTimeoutMs);
|
|
13230
|
+
const beforeStartDeadline = (phase, work, abandon) => {
|
|
13231
|
+
startPhase = phase;
|
|
13232
|
+
return new Promise((resolve, reject) => {
|
|
13233
|
+
const expire = () => {
|
|
13234
|
+
work.then((late) => abandon?.(late), () => {
|
|
13235
|
+
return;
|
|
13236
|
+
});
|
|
13237
|
+
reject(startDeadline.signal.reason);
|
|
13238
|
+
};
|
|
13239
|
+
if (startDeadline.signal.aborted)
|
|
13240
|
+
return expire();
|
|
13241
|
+
startDeadline.signal.addEventListener("abort", expire, { once: true });
|
|
13242
|
+
work.then((value) => {
|
|
13243
|
+
startDeadline.signal.removeEventListener("abort", expire);
|
|
13244
|
+
resolve(value);
|
|
13245
|
+
}, (error) => {
|
|
13246
|
+
startDeadline.signal.removeEventListener("abort", expire);
|
|
13247
|
+
reject(error);
|
|
13248
|
+
});
|
|
13249
|
+
});
|
|
13250
|
+
};
|
|
13186
13251
|
try {
|
|
13187
13252
|
const workflow = workflowMetadataFromContext(admitted.spec.parent?.orchestrationContext);
|
|
13188
|
-
const sessionManager = admitted.sessionManager ?
|
|
13253
|
+
const sessionManager = await beforeStartDeadline("opening its session", admitted.sessionManager ? SessionManager3.open(admitted.sessionManager.getSessionStore(), admitted.sessionManager.getSessionId(), admitted.policy.cwd) : SessionManager3.create(admitted.policy.cwd, admitted.sessionDir, workflow ? { internal: true, workflow } : { internal: true }));
|
|
13189
13254
|
transcriptManager = sessionManager;
|
|
13190
13255
|
taskHooks?.bindTranscript?.(sessionManager);
|
|
13191
13256
|
const childSession = {
|
|
@@ -13195,7 +13260,7 @@ class SubagentControlRuntime {
|
|
|
13195
13260
|
taskHooks?.bindChildSession?.(childSession);
|
|
13196
13261
|
admitted.spec.onChildSession?.(childSession);
|
|
13197
13262
|
if (workflow)
|
|
13198
|
-
await sessionManager.markSessionInternal(workflow);
|
|
13263
|
+
await beforeStartDeadline("opening its session", sessionManager.markSessionInternal(workflow));
|
|
13199
13264
|
const launchLeafId = sessionManager.getLeafId();
|
|
13200
13265
|
ownMessages = () => messagesSinceLaunch(sessionManager, launchLeafId);
|
|
13201
13266
|
let created;
|
|
@@ -13221,6 +13286,13 @@ class SubagentControlRuntime {
|
|
|
13221
13286
|
} : inherited.extensionBindings;
|
|
13222
13287
|
const agentDir = inherited.agentDir ?? getAgentDir2();
|
|
13223
13288
|
const settingsManager = inherited.settingsManager ?? SettingsManager.create(admitted.policy.cwd, agentDir);
|
|
13289
|
+
const requested = admitted.spec.requestedThinking;
|
|
13290
|
+
const startSuffix = splitKnownThinkingSuffix(candidate.modelId ?? "").thinkingSuffix.slice(1);
|
|
13291
|
+
const startEffort = THINKING_LEVELS.find((level) => level === startSuffix) ?? requested;
|
|
13292
|
+
const explicitEffort = requested === undefined || startEffort === undefined ? {} : {
|
|
13293
|
+
...inherited.model ? { thinkingLevel: explicitEffortFor(inherited.model, startEffort, settingsManager) } : {},
|
|
13294
|
+
fallbackModels: (inherited.fallbackModels ?? settingsManager.getFallbackModels() ?? []).map((entry) => pinFallbackEffort(entry, requested, settingsManager, admitted.spec.resolveCandidateModel))
|
|
13295
|
+
};
|
|
13224
13296
|
const resourceLoader = new DefaultResourceLoader(inProcessChildResourceLoaderOptions({
|
|
13225
13297
|
cwd: admitted.policy.cwd,
|
|
13226
13298
|
agentDir,
|
|
@@ -13230,7 +13302,7 @@ class SubagentControlRuntime {
|
|
|
13230
13302
|
resourceLoaderInheritanceSnapshot: admitted.spec.parent?.resourceLoaderInheritanceSnapshot,
|
|
13231
13303
|
orchestrationContext: admitted.spec.parent?.orchestrationContext
|
|
13232
13304
|
}));
|
|
13233
|
-
await resourceLoader.reload();
|
|
13305
|
+
await beforeStartDeadline("loading its resources", resourceLoader.reload());
|
|
13234
13306
|
const selectedSkills = resolveSkillsFromCatalog([...admitted.policy.skills], resourceLoader.getSkillCatalog(), admitted.policy.cwd);
|
|
13235
13307
|
skillReport = {
|
|
13236
13308
|
...selectedSkills.resolved.length > 0 ? { skills: selectedSkills.resolved.map((skill) => skill.name) } : {},
|
|
@@ -13242,26 +13314,28 @@ class SubagentControlRuntime {
|
|
|
13242
13314
|
const skillInjection = buildSkillInjection(selectedSkills.resolved);
|
|
13243
13315
|
const promptBehavior = createInProcessChildPromptBehavior(admitted.policy);
|
|
13244
13316
|
const systemPromptTransform = createInProcessChildSystemPromptTransform(admitted.policy, skillInjection);
|
|
13245
|
-
created = {
|
|
13246
|
-
|
|
13247
|
-
|
|
13248
|
-
|
|
13249
|
-
|
|
13250
|
-
|
|
13251
|
-
|
|
13252
|
-
|
|
13253
|
-
|
|
13254
|
-
|
|
13255
|
-
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
|
|
13259
|
-
|
|
13260
|
-
|
|
13261
|
-
|
|
13262
|
-
|
|
13263
|
-
|
|
13317
|
+
created = await beforeStartDeadline("creating its agent session, which includes any wait for a resource-admission permit", createAgentSession({
|
|
13318
|
+
...inherited,
|
|
13319
|
+
...explicitEffort,
|
|
13320
|
+
extensionBindings,
|
|
13321
|
+
customTools: admitted.policy.customTools ?? inherited.customTools,
|
|
13322
|
+
resourceLoader,
|
|
13323
|
+
resourceAdmissionSignal: AbortSignal.any([signals.abort, signals.interrupt, startDeadline.signal]),
|
|
13324
|
+
subagentPolicy: {
|
|
13325
|
+
...admitted.policy,
|
|
13326
|
+
executionEnded: executionEnded.signal,
|
|
13327
|
+
...!childAllowsIntercom(inherited) ? { intercom: undefined, intercomGroup: undefined } : {}
|
|
13328
|
+
},
|
|
13329
|
+
settingsManager,
|
|
13330
|
+
orchestrationContext: admitted.spec.parent?.orchestrationContext,
|
|
13331
|
+
sessionManager,
|
|
13332
|
+
systemPromptTransform,
|
|
13333
|
+
initialContextTransform: promptBehavior.initialContextTransform
|
|
13334
|
+
}), (late) => void late.session.dispose().catch(() => {
|
|
13335
|
+
return;
|
|
13336
|
+
}));
|
|
13264
13337
|
}
|
|
13338
|
+
clearTimeout(startTimer);
|
|
13265
13339
|
session = created.session;
|
|
13266
13340
|
const transcriptSession = session;
|
|
13267
13341
|
let observedStreamingMessage;
|
|
@@ -13493,6 +13567,7 @@ class SubagentControlRuntime {
|
|
|
13493
13567
|
...skillReport
|
|
13494
13568
|
};
|
|
13495
13569
|
} finally {
|
|
13570
|
+
clearTimeout(startTimer);
|
|
13496
13571
|
executionEnded.abort();
|
|
13497
13572
|
signals.abort.removeEventListener("abort", abortListener);
|
|
13498
13573
|
signals.interrupt.removeEventListener("abort", interruptListener);
|
|
@@ -13680,11 +13755,24 @@ function findSubagentControl(id) {
|
|
|
13680
13755
|
if (direct)
|
|
13681
13756
|
return direct;
|
|
13682
13757
|
for (const control of controls.values()) {
|
|
13758
|
+
if (control.pathOfChildId(id) !== undefined)
|
|
13759
|
+
return control;
|
|
13683
13760
|
if (control.native.listChildren().some((child) => child.path === id))
|
|
13684
13761
|
return control;
|
|
13685
13762
|
}
|
|
13686
13763
|
return;
|
|
13687
13764
|
}
|
|
13765
|
+
function subagentChildPath(control, id) {
|
|
13766
|
+
return control.pathOfChildId(id) ?? id;
|
|
13767
|
+
}
|
|
13768
|
+
function subagentChildIdOfPath(id) {
|
|
13769
|
+
for (const control of controls.values()) {
|
|
13770
|
+
const childId = control.childIdOf(id);
|
|
13771
|
+
if (childId !== undefined)
|
|
13772
|
+
return childId;
|
|
13773
|
+
}
|
|
13774
|
+
return;
|
|
13775
|
+
}
|
|
13688
13776
|
function listSubagentControls() {
|
|
13689
13777
|
return [...controls.values()];
|
|
13690
13778
|
}
|
|
@@ -14030,6 +14118,8 @@ async function runSingleInProcess(runtimeCwd, agent, task, options) {
|
|
|
14030
14118
|
const resolvedCandidate = candidate ? options.resolveCandidateModel?.(candidate) : undefined;
|
|
14031
14119
|
if (options.modelRoute && !resolvedCandidate)
|
|
14032
14120
|
throw new Error("Subagent auto-selected model could not be resolved before execution. Retry explicitly with the current catalog.");
|
|
14121
|
+
const requestedSuffix = splitKnownThinkingSuffix(options.modelOverride ?? agent.model ?? "").thinkingSuffix.slice(1);
|
|
14122
|
+
const requestedThinking = options.modelRoute ? undefined : THINKING_LEVELS.find((level) => level === requestedSuffix);
|
|
14033
14123
|
const orchestrationContext = workflowOrchestrationContext(options);
|
|
14034
14124
|
const outputSnapshot = captureSingleOutputSnapshot(options.outputPath);
|
|
14035
14125
|
const parent = {
|
|
@@ -14056,6 +14146,7 @@ ${task}`);
|
|
|
14056
14146
|
const testSession = options.testSession ?? defaultTestSession();
|
|
14057
14147
|
const spec = {
|
|
14058
14148
|
taskName: agent.name,
|
|
14149
|
+
childId: `${options.runId}:${options.index ?? 0}`,
|
|
14059
14150
|
task,
|
|
14060
14151
|
agent,
|
|
14061
14152
|
cwd,
|
|
@@ -14069,6 +14160,11 @@ ${task}`);
|
|
|
14069
14160
|
...options.progressPath ? { progressPath: options.progressPath } : {},
|
|
14070
14161
|
...options.progressArtifactPath ? { progressArtifactPath: options.progressArtifactPath } : options.progressPath && artifactsDir ? { progressArtifactPath: options.progressPath } : {},
|
|
14071
14162
|
...artifactPaths?.outputPath ? { outputArtifactPath: artifactPaths.outputPath } : {},
|
|
14163
|
+
...options.sessionStartTimeoutMs === undefined ? {} : { sessionStartTimeoutMs: options.sessionStartTimeoutMs },
|
|
14164
|
+
...requestedThinking === undefined ? {} : {
|
|
14165
|
+
requestedThinking,
|
|
14166
|
+
...options.resolveCandidateModel ? { resolveCandidateModel: options.resolveCandidateModel } : {}
|
|
14167
|
+
},
|
|
14072
14168
|
tools: agent.tools,
|
|
14073
14169
|
mcpDirectTools: agent.mcpDirectTools,
|
|
14074
14170
|
skills: options.skills ?? agent.skills,
|
|
@@ -15898,34 +15994,52 @@ function handleSubagentControlNotice(input) {
|
|
|
15898
15994
|
function canonicalChildren(control) {
|
|
15899
15995
|
return [...control.listChildren()].sort((left, right) => left.path.localeCompare(right.path));
|
|
15900
15996
|
}
|
|
15997
|
+
function settledCause(control, path, status) {
|
|
15998
|
+
if (status !== "error" && status !== "interrupted")
|
|
15999
|
+
return;
|
|
16000
|
+
const cause = control.getDeliveredResult(path)?.cause?.replace(/\s+/g, " ").trim();
|
|
16001
|
+
return cause || undefined;
|
|
16002
|
+
}
|
|
15901
16003
|
function childLines(control, id) {
|
|
15902
|
-
if (!control)
|
|
15903
|
-
return [];
|
|
15904
16004
|
if (id) {
|
|
15905
|
-
const
|
|
16005
|
+
const path = subagentChildPath(control, id);
|
|
16006
|
+
const child = control.findChild(path);
|
|
15906
16007
|
if (!child)
|
|
15907
16008
|
return [];
|
|
15908
|
-
const delivered = control.getDeliveredResult(
|
|
16009
|
+
const delivered = control.getDeliveredResult(path);
|
|
16010
|
+
const childId = control.childIdOf(path);
|
|
16011
|
+
const cause = settledCause(control, path, child.status);
|
|
15909
16012
|
return [
|
|
16013
|
+
...childId ? [`Id: ${childId}`] : [],
|
|
15910
16014
|
`Child: ${child.path}`,
|
|
15911
16015
|
`Parent: ${child.parentPath}`,
|
|
15912
16016
|
`Task: ${child.taskName}`,
|
|
15913
16017
|
`Depth: ${child.depth}`,
|
|
15914
16018
|
`Status: ${child.status}`,
|
|
16019
|
+
...cause ? [`Cause: ${cause}`] : [],
|
|
15915
16020
|
`Residency: ${child.loaded ? "loaded" : "cold"}`,
|
|
15916
16021
|
...delivered?.sessionFile ? [`Session: ${delivered.sessionFile}`] : []
|
|
15917
16022
|
];
|
|
15918
16023
|
}
|
|
15919
|
-
return control.listChildren().map((child) =>
|
|
16024
|
+
return control.listChildren().map((child) => {
|
|
16025
|
+
const childId = control.childIdOf(child.path);
|
|
16026
|
+
const cause = settledCause(control, child.path, child.status);
|
|
16027
|
+
return `${child.path} — ${child.status} (${child.loaded ? "loaded" : "cold"})${childId ? ` · id ${childId}` : ""}${cause ? ` · ${cause}` : ""}`;
|
|
16028
|
+
});
|
|
15920
16029
|
}
|
|
15921
16030
|
function statusGroup(control, id) {
|
|
16031
|
+
const path = id === undefined ? undefined : subagentChildPath(control, id);
|
|
15922
16032
|
return {
|
|
15923
16033
|
parentPath: control.parent.path,
|
|
15924
|
-
children: canonicalChildren(control).filter((child) => !
|
|
16034
|
+
children: canonicalChildren(control).filter((child) => !path || path === control.parent.path || child.path === path).map((child) => {
|
|
15925
16035
|
const delivered = control.getDeliveredResult(child.path);
|
|
15926
16036
|
const metadata = control.getChildMetadata(child.path) ?? delivered;
|
|
16037
|
+
const childId = control.childIdOf(child.path);
|
|
16038
|
+
const failure = settledCause(control, child.path, child.status);
|
|
15927
16039
|
return {
|
|
15928
16040
|
...child,
|
|
16041
|
+
...childId === undefined ? {} : { childId },
|
|
16042
|
+
...failure === undefined ? {} : { failure },
|
|
15929
16043
|
sessionFile: delivered?.sessionFile,
|
|
15930
16044
|
...metadata?.model === undefined ? {} : { model: metadata.model },
|
|
15931
16045
|
...metadata?.thinking === undefined ? {} : { thinking: metadata.thinking }
|
|
@@ -15933,10 +16047,11 @@ function statusGroup(control, id) {
|
|
|
15933
16047
|
})
|
|
15934
16048
|
};
|
|
15935
16049
|
}
|
|
15936
|
-
function inspectInProcessChildStatus(id) {
|
|
16050
|
+
function inspectInProcessChildStatus(id, ownsRun) {
|
|
16051
|
+
const owned = (control) => ownsRun?.(control.parent.path) ?? true;
|
|
15937
16052
|
if (id) {
|
|
15938
16053
|
const control = findSubagentControl(id);
|
|
15939
|
-
if (!control)
|
|
16054
|
+
if (!control || !owned(control))
|
|
15940
16055
|
return;
|
|
15941
16056
|
const text = id === control.parent.path ? [`Parent: ${control.parent.path}`, ...childLines(control)].join(`
|
|
15942
16057
|
`) : childLines(control, id).join(`
|
|
@@ -15948,7 +16063,7 @@ function inspectInProcessChildStatus(id) {
|
|
|
15948
16063
|
details: { mode: "management", results: [], statusGroups: [statusGroup(control, id)] }
|
|
15949
16064
|
};
|
|
15950
16065
|
}
|
|
15951
|
-
const controls = listSubagentControls();
|
|
16066
|
+
const controls = listSubagentControls().filter(owned);
|
|
15952
16067
|
const lines = controls.flatMap((control) => [`Parent: ${control.parent.path}`, ...childLines(control)]);
|
|
15953
16068
|
if (lines.length === 0)
|
|
15954
16069
|
return;
|
|
@@ -17561,10 +17676,22 @@ function liveTaskIds(host) {
|
|
|
17561
17676
|
function ownedRecords(ctx) {
|
|
17562
17677
|
return readSubagentChildRecords(ctx.sessionManager.getEntries(), subagentChildOwner(ctx).sessionId);
|
|
17563
17678
|
}
|
|
17679
|
+
async function subagentRunsLaunchedBy(ctx) {
|
|
17680
|
+
const owner = subagentChildOwner(ctx).sessionId;
|
|
17681
|
+
await subagentChildRecordsAppended(owner);
|
|
17682
|
+
const runIds = observedSubagentRunIds(owner);
|
|
17683
|
+
for (const record of ownedRecords(ctx).values())
|
|
17684
|
+
runIds.add(record.runId);
|
|
17685
|
+
return runIds;
|
|
17686
|
+
}
|
|
17564
17687
|
function resolveRecord(records, id) {
|
|
17565
17688
|
const direct = findSubagentChildRecord(records, id);
|
|
17566
17689
|
if (direct)
|
|
17567
17690
|
return direct;
|
|
17691
|
+
const listedAs = subagentChildIdOfPath(id.trim());
|
|
17692
|
+
const byPath = listedAs === undefined ? undefined : records.get(listedAs);
|
|
17693
|
+
if (byPath)
|
|
17694
|
+
return byPath;
|
|
17568
17695
|
const inRun = [...records.values()].filter((record) => record.runId === id.trim());
|
|
17569
17696
|
if (inRun.length === 1)
|
|
17570
17697
|
return inRun[0];
|
|
@@ -17905,7 +18032,8 @@ async function handleManagementRequest(input) {
|
|
|
17905
18032
|
if (action === "status") {
|
|
17906
18033
|
const targetRunId = paramsWithResolvedCwd.id ?? paramsWithResolvedCwd.runId;
|
|
17907
18034
|
const foreground = getForegroundControl(deps.state, targetRunId);
|
|
17908
|
-
const
|
|
18035
|
+
const launched = await subagentRunsLaunchedBy(ctx);
|
|
18036
|
+
const live = inspectInProcessChildStatus(targetRunId, (runId) => launched.has(runId)) ?? (foreground ? foregroundStatusResult(foreground) : undefined);
|
|
17909
18037
|
if (awaitingResume.length > 0) {
|
|
17910
18038
|
const liveText = live?.content.map((part) => part.type === "text" ? part.text : "").join(`
|
|
17911
18039
|
`);
|
|
@@ -19263,11 +19391,13 @@ function childStatusLines(child, expanded, theme, width) {
|
|
|
19263
19391
|
return [
|
|
19264
19392
|
heading,
|
|
19265
19393
|
...metadata,
|
|
19394
|
+
...child.childId ? [theme.fg("dim", ` Id: ${displayText(child.childId)}`)] : [],
|
|
19266
19395
|
theme.fg("dim", ` Path: ${displayText(child.path)}`),
|
|
19267
19396
|
theme.fg("dim", ` Parent: ${displayText(child.parentPath)} · Depth: ${child.depth}`),
|
|
19268
19397
|
theme.fg("dim", ` Task: ${displayText(child.taskName)}`),
|
|
19269
19398
|
theme.fg("dim", ` Residency: ${child.loaded ? "loaded" : "cold"}`),
|
|
19270
19399
|
...child.cause ? [theme.fg("muted", ` Cause: ${displayText(child.cause)}`)] : [],
|
|
19400
|
+
...child.failure ? [theme.fg("error", ` Error: ${displayText(child.failure)}`)] : [],
|
|
19271
19401
|
...child.sessionFile ? [theme.fg("dim", ` Session: ${displayText(child.sessionFile)}`)] : []
|
|
19272
19402
|
];
|
|
19273
19403
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/web-access",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.59-alpha.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for web search, URL fetching, GitHub repo cloning, PDF/video extraction. Fork of: https://github.com/nicobailon/pi-web-access",
|
|
6
6
|
"contributors": [
|