@bastani/atomic 0.9.19-alpha.3 → 0.9.19-alpha.5
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 +35 -0
- package/dist/builtin/intercom/CHANGELOG.md +8 -0
- package/dist/builtin/intercom/index.bundle.mjs +117 -26
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +18 -0
- package/dist/builtin/subagents/README.md +15 -15
- package/dist/builtin/subagents/agents/debugger.md +2 -2
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/skills/subagent/SKILL.md +26 -26
- package/dist/builtin/subagents/src/extension/index.bundle.mjs +140 -58
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +27 -0
- package/dist/builtin/workflows/README.md +14 -15
- package/dist/builtin/workflows/builtin/{chunk-mygmtz6e.js → chunk-1nbq96fh.js} +19 -19
- package/dist/builtin/workflows/builtin/{chunk-zggjyg5z.js → chunk-n8zysf1t.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-r9qq7xfj.js → chunk-vhmnzdj9.js} +37 -37
- package/dist/builtin/workflows/builtin/{chunk-62v3gg9f.js → chunk-yeee2jrc.js} +11 -11
- package/dist/builtin/workflows/builtin/goal.js +2 -2
- package/dist/builtin/workflows/builtin/index.js +4 -4
- package/dist/builtin/workflows/builtin/open-claude-design.js +1 -1
- package/dist/builtin/workflows/builtin/ralph.js +2 -2
- package/dist/builtin/workflows/package.json +5 -5
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +180 -239
- package/dist/builtin/workflows/src/index.js +19 -2
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +2 -1
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +1 -1
- package/dist/core/agent-session-auto-compaction.js +1 -1
- package/dist/core/agent-session-auto-compaction.js.map +1 -1
- package/dist/core/agent-session-compaction.js +1 -1
- package/dist/core/agent-session-compaction.js.map +1 -1
- package/dist/core/agent-session-custom-message-commit.d.ts.map +1 -1
- package/dist/core/agent-session-custom-message-commit.js +33 -2
- package/dist/core/agent-session-custom-message-commit.js.map +1 -1
- package/dist/core/agent-session-message-queue.d.ts +1 -1
- package/dist/core/agent-session-message-queue.d.ts.map +1 -1
- package/dist/core/agent-session-message-queue.js +20 -6
- package/dist/core/agent-session-message-queue.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +4 -1
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-persistent-custom-messages.d.ts +1 -1
- package/dist/core/agent-session-persistent-custom-messages.d.ts.map +1 -1
- package/dist/core/agent-session-persistent-custom-messages.js +13 -3
- package/dist/core/agent-session-persistent-custom-messages.js.map +1 -1
- package/dist/core/agent-session-post-tool-compaction.js +1 -1
- package/dist/core/agent-session-post-tool-compaction.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +83 -0
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-queue-pause.d.ts.map +1 -1
- package/dist/core/agent-session-queue-pause.js +11 -0
- package/dist/core/agent-session-queue-pause.js.map +1 -1
- package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
- package/dist/core/agent-session-tool-hooks.js +2 -0
- package/dist/core/agent-session-tool-hooks.js.map +1 -1
- package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
- package/dist/core/agent-session-tool-registry.js +12 -0
- package/dist/core/agent-session-tool-registry.js.map +1 -1
- package/dist/core/agent-session-transfer.d.ts.map +1 -1
- package/dist/core/agent-session-transfer.js +7 -0
- package/dist/core/agent-session-transfer.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +2 -0
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js +2 -0
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/agent-session.d.ts +4 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +22 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/context-types.d.ts +6 -0
- package/dist/core/extensions/context-types.d.ts.map +1 -1
- package/dist/core/extensions/context-types.js.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.js +3 -3
- package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
- package/dist/core/extensions/runner-context.d.ts +1 -1
- package/dist/core/extensions/runner-context.d.ts.map +1 -1
- package/dist/core/extensions/runner-context.js +9 -3
- package/dist/core/extensions/runner-context.js.map +1 -1
- package/dist/core/extensions/runner.js +1 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/workflow-events.d.ts +1 -1
- package/dist/core/extensions/workflow-events.d.ts.map +1 -1
- package/dist/core/extensions/workflow-events.js.map +1 -1
- package/dist/core/sdk-exports.d.ts +1 -1
- package/dist/core/sdk-exports.d.ts.map +1 -1
- package/dist/core/sdk-exports.js +1 -1
- package/dist/core/sdk-exports.js.map +1 -1
- package/dist/core/settings-manager-basic-accessors.d.ts +5 -3
- package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-basic-accessors.js +23 -8
- package/dist/core/settings-manager-basic-accessors.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-types.d.ts +5 -0
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +4 -5
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tasks/agent-adapter.d.ts +5 -2
- package/dist/core/tasks/agent-adapter.d.ts.map +1 -1
- package/dist/core/tasks/agent-adapter.js +10 -3
- package/dist/core/tasks/agent-adapter.js.map +1 -1
- package/dist/core/tasks/completion.d.ts.map +1 -1
- package/dist/core/tasks/completion.js +5 -1
- package/dist/core/tasks/completion.js.map +1 -1
- package/dist/core/tools/bash-pty-native.d.ts +16 -2
- package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
- package/dist/core/tools/bash-pty-native.js +82 -0
- package/dist/core/tools/bash-pty-native.js.map +1 -1
- package/dist/core/tools/bash.d.ts +13 -2
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +48 -3
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/index.d.ts +4 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +12 -0
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/kill.d.ts +17 -0
- package/dist/core/tools/kill.d.ts.map +1 -0
- package/dist/core/tools/kill.js +49 -0
- package/dist/core/tools/kill.js.map +1 -0
- package/dist/core/tools/powershell.d.ts +84 -28
- package/dist/core/tools/powershell.d.ts.map +1 -1
- package/dist/core/tools/powershell.js +10 -3
- package/dist/core/tools/powershell.js.map +1 -1
- package/dist/core/workflow-stage-admission.d.ts +14 -0
- package/dist/core/workflow-stage-admission.d.ts.map +1 -1
- package/dist/core/workflow-stage-admission.js +63 -3
- package/dist/core/workflow-stage-admission.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/task-row.d.ts.map +1 -1
- package/dist/modes/interactive/components/task-row.js +8 -1
- package/dist/modes/interactive/components/task-row.js.map +1 -1
- package/docs/background-tasks.md +24 -1
- package/docs/compaction.md +20 -0
- package/docs/computer-use.md +390 -0
- package/docs/docs.json +1 -0
- package/docs/extensions.md +11 -1
- package/docs/herdr.md +2 -0
- package/docs/index.md +1 -0
- package/docs/intercom.md +10 -2
- package/docs/providers.md +1 -1
- package/docs/quickstart.md +1 -1
- package/docs/sdk.md +11 -1
- package/docs/settings.md +20 -0
- package/docs/subagents.md +8 -6
- package/docs/tmux.md +2 -0
- package/docs/tools.md +7 -1
- package/docs/usage.md +1 -1
- package/docs/workflows/api-reference.md +4 -3
- package/docs/workflows/authoring.md +3 -3
- package/docs/workflows/builtins.md +9 -6
- package/docs/workflows/operations.md +36 -30
- package/docs/workflows/reliable-design.md +3 -3
- package/docs/workflows/verification.md +99 -40
- package/docs/workflows.md +4 -2
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.19-alpha.5] - 2026-09-11
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Open Claude Design now starts with Claude Fable 5.1 at medium effort, followed by Copilot Fable 5.1 and Astra at medium effort, with the same Fable-first order on OpenRouter.
|
|
10
|
+
- Tuned bundled debugger, Goal, and Ralph reasoning efforts: debugger uses Astra/Fable at medium and Sol at high; Goal and Ralph reviewers use Astra/Sol at high; orchestration, Ralph research, and design use Fable at medium and Sol at high in their fallbacks. Ralph prompt refinement and other bundled agents retain their existing configurations.
|
|
11
|
+
|
|
12
|
+
## [0.9.19-alpha.4] - 2026-09-10
|
|
13
|
+
|
|
14
|
+
### Breaking Changes
|
|
15
|
+
|
|
16
|
+
- Workflow controls, completion, help, and status hints use `/workflow pause`, `/workflow quit`, and `/workflow resume`. The workflow tool supports run, stage, and individual durable-tool pause targets; `/workflow pause [run-id|--all]` controls runs. Workflow lifecycle control events report `action: "pause"` for pause requests.
|
|
17
|
+
- Renamed the bundled subagent `interrupt` action to `kill`. Migrate `subagent({ action: "interrupt", id })` to `subagent({ action: "kill", id })`, including calls using `runId`. The old action is no longer accepted. Kill terminally stops the child and cannot be resumed; follow-up work requires a fresh launch. Workflow controls use `/workflow pause`; parent cancellation behavior is unchanged.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- Added a model row to the `/workflow connect` graph node cards showing each stage's effective model and thinking level, including canonical fast model identity, with model-name truncation preserving the suffixes. Cards retain duration, status and dependencies in a six-row layout, reflect live fallbacks, and restore identity through durable resume ([#1859](https://github.com/bastani-inc/atomic/pull/1859) by [@sina85](https://github.com/sina85)).
|
|
22
|
+
- Added `{ action: "wait", id, budgetMs }` to Bash and PowerShell for observing existing asynchronous tasks without rerunning commands. The observation budget is optional. Waits retain output and terminal metadata, follow owner observation policy, and release on cancellation or incoming messages without stopping execution or extending task lifetime.
|
|
23
|
+
- Added the agent-callable `kill({ id })` tool for owned background bash and PowerShell tasks in main and workflow-stage chat. It cancels by task ID, preserves retained output and original outcomes, reports current cleanup state, and rejects other owners' tasks and subagents.
|
|
24
|
+
- Added exact per-model overrides through `compaction.modelOverrides` for `compaction.reserveTokens` and Atomic's `compaction.preserve_recent` message count. Each field falls back to ordinary settings and then built-in defaults, with non-negative safe-integer validation. Manual, automatic, and post-tool compaction use the active model's budgets while retaining verbatim line compaction.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- First-loaded TypeScript extensions share the live host's classes and singletons when native import falls back to transformation, avoiding duplicate host evaluation and slow startup.
|
|
29
|
+
- Fixed repeated yielded shell waits replaying the first output page instead of progressing through retained output while the task is still running ([#2972](https://github.com/bastani-inc/atomic/pull/2972)).
|
|
30
|
+
- Preserved an explicit subagent kill when parent cancellation arrives during execution-capacity waiting, and kept grouped Intercom cancellation status consistent when a killed child has parent-cancelled siblings.
|
|
31
|
+
- Embedded Postgres now starts on Windows administrative accounts. PostgreSQL refuses to run for a member of the Administrators or Power Users groups, so Atomic launches the retained server process with the same restricted access token `pg_ctl` uses, keeping exact-process shutdown semantics; non-administrative Windows accounts are unchanged. Postgres processes that exit during startup (including that administrator refusal on older builds) now fail fast with the actual server log instead of a readiness timeout.
|
|
32
|
+
- Preserved embedded Postgres startup logs on regular Windows accounts, honored Unicode environment overrides on administrative launches, and prevented Windows handle leaks across repeated launches.
|
|
33
|
+
- Preserved `PATH` lookup and relative executable paths for administrative Windows Postgres launches. Invalid launch inputs containing embedded NUL characters now fail before starting a process rather than using truncated paths, arguments, or environment values.
|
|
34
|
+
- Fixed custom Windows Postgres `.cmd` and `.bat` launchers failing with arguments on administrative accounts, including launcher paths containing spaces. Batch arguments retain their existing quoting and line-break rejection.
|
|
35
|
+
- Fixed explicit `cmd.exe` Postgres launchers and safe verbatim working directories on Windows administrative accounts. Concurrent Postgres launches no longer keep one another's log files open or expose them to unrelated commands starting at the same time.
|
|
36
|
+
- Incoming Intercom send and ask messages now act as a priority interrupt queue for working subagents and live workflow stages: the receiver's current model call or cancellable tool is cancelled immediately and the message is processed within the same task, session, and stage generation. Admission survives consumed preflight input and overlapping SDK interrupt turns. Completed tool side effects are never replayed, the original task prompt is not repeated, multiple arrivals stay in arrival order with duplicate suppression, and exact ask/reply correlation survives the cancelled turn. Explicit user abort, host stop, and terminal/closed receivers still win: late input never restarts finished work.
|
|
37
|
+
- Fixed a deadlock where an extension event hook awaiting an ordinary context-only message could wait behind an inbound Intercom delivery that was itself waiting for that event hook.
|
|
38
|
+
- Inbound delivery retries after a transient persistence failure keep their original arrival position and remain part of both child and workflow-stage settlement, and a card appended before a failed flush is completed on retry instead of being appended a second time.
|
|
39
|
+
|
|
5
40
|
## [0.9.19-alpha.3] - 2026-09-09
|
|
6
41
|
|
|
7
42
|
### Fixed
|
|
@@ -4,6 +4,14 @@ All notable changes to the `pi-intercom` extension will be documented in this fi
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.9.19-alpha.4] - 2026-09-10
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Route lazy initialization, event-relay, and rejected-candidate cleanup diagnostics through the owning interactive session's notifications, including during shutdown, instead of leaking console output and stacks. Retryable initialization uses warning color; non-interactive console diagnostics (including RPC), original failures, acknowledgements, and retry behavior are preserved even when an error cannot be rendered.
|
|
12
|
+
- `send` and `ask` to a working subagent or live workflow stage are delivered as a priority interrupt: the recipient's active model call or cancellable tool is cancelled immediately and the message is processed in the same task instead of waiting for the next natural turn or being refused as busy. Completed side effects are not undone or replayed. Arrival order holds across persistence retries for both receiver kinds; duplicate suppression, exact reply correlation, terminal-child and closed-stage rejection, unrelated headless protection, and group restrictions are unchanged.
|
|
13
|
+
- A cancelled turn that produced no reply no longer consumes the pending ask's reply context, so replies to consecutive asks stay correlated with the right sender and message.
|
|
14
|
+
|
|
7
15
|
## [0.9.19-alpha.3] - 2026-09-09
|
|
8
16
|
|
|
9
17
|
### Fixed
|
|
@@ -1989,6 +1989,11 @@ class ReplyTracker {
|
|
|
1989
1989
|
endTurn() {
|
|
1990
1990
|
this.currentTurnContext = null;
|
|
1991
1991
|
}
|
|
1992
|
+
restoreTurnContext() {
|
|
1993
|
+
if (this.currentTurnContext)
|
|
1994
|
+
this.pendingTurnContexts.unshift(this.currentTurnContext);
|
|
1995
|
+
this.currentTurnContext = null;
|
|
1996
|
+
}
|
|
1992
1997
|
reset() {
|
|
1993
1998
|
this.pendingAsks.clear();
|
|
1994
1999
|
this.pendingTurnContexts.length = 0;
|
|
@@ -4579,10 +4584,15 @@ function registerIntercomLifecycle(pi, deps) {
|
|
|
4579
4584
|
hasActiveSession = false;
|
|
4580
4585
|
await cleanupRuntime("Session shutting down");
|
|
4581
4586
|
});
|
|
4582
|
-
pi.on("turn_end", () => {
|
|
4587
|
+
pi.on("turn_end", (event) => {
|
|
4583
4588
|
if (!deps.getLiveContext())
|
|
4584
4589
|
return;
|
|
4585
|
-
|
|
4590
|
+
const message = event.message;
|
|
4591
|
+
const cancelledBeforeReply = message?.role === "assistant" && message.stopReason === "aborted" && message.content?.length === 0;
|
|
4592
|
+
if (cancelledBeforeReply)
|
|
4593
|
+
activeReplyTracker().restoreTurnContext();
|
|
4594
|
+
else
|
|
4595
|
+
activeReplyTracker().endTurn();
|
|
4586
4596
|
deps.scheduleInboundFlush();
|
|
4587
4597
|
});
|
|
4588
4598
|
pi.on("agent_start", () => {
|
|
@@ -5674,7 +5684,7 @@ function createIncomingMessageSender(input) {
|
|
|
5674
5684
|
if (!input.canDeliver(generation)) {
|
|
5675
5685
|
return Promise.reject(new Error("Intercom session retired before inbound delivery"));
|
|
5676
5686
|
}
|
|
5677
|
-
if (delivery === "trigger" && trackReplyContext) {
|
|
5687
|
+
if ((delivery === "trigger" || delivery === "interrupt") && trackReplyContext) {
|
|
5678
5688
|
input.queueTurnContext(turnContext ?? { from: entry.from, message: entry.message, receivedAt: Date.now() });
|
|
5679
5689
|
}
|
|
5680
5690
|
const baseOptions = {
|
|
@@ -5682,7 +5692,7 @@ function createIncomingMessageSender(input) {
|
|
|
5682
5692
|
persistWhenStreaming: true,
|
|
5683
5693
|
...stageAdmissionBarrier ? { stageAdmissionBarrier } : {}
|
|
5684
5694
|
};
|
|
5685
|
-
const options = delivery === "trigger" ? { ...baseOptions, triggerTurn: true } : delivery === "followUp" ? { ...baseOptions, deliverAs: "followUp" } : baseOptions;
|
|
5695
|
+
const options = delivery === "interrupt" ? { ...baseOptions, triggerTurn: true, deliverAs: "interrupt" } : delivery === "trigger" ? { ...baseOptions, triggerTurn: true } : delivery === "followUp" ? { ...baseOptions, deliverAs: "followUp" } : baseOptions;
|
|
5686
5696
|
return Promise.resolve(input.pi.sendMessage(buildIncomingCustomMessage(entry), options));
|
|
5687
5697
|
};
|
|
5688
5698
|
}
|
|
@@ -6034,13 +6044,15 @@ function retryStableDelivery(options) {
|
|
|
6034
6044
|
function admitWorkflowStageInbound(ctx, deliver, firstRefusal, onAdmissionFailure) {
|
|
6035
6045
|
if (ctx.orchestrationContext?.kind !== "workflow-stage")
|
|
6036
6046
|
return false;
|
|
6047
|
+
const boundary = ctx.orchestrationContext.messageAdmission?.boundary;
|
|
6048
|
+
const run = (barrier) => boundary?.runMessageDelivery(() => deliver(barrier), () => deliver(), true) ?? Promise.resolve(deliver(barrier));
|
|
6037
6049
|
try {
|
|
6038
6050
|
let busy = false;
|
|
6039
6051
|
try {
|
|
6040
6052
|
busy = ctx.isIdle?.() === false;
|
|
6041
6053
|
} catch {}
|
|
6042
6054
|
if (!busy || !firstRefusal)
|
|
6043
|
-
return
|
|
6055
|
+
return run();
|
|
6044
6056
|
let firstRefusalPromise;
|
|
6045
6057
|
const admissionBarrier = () => {
|
|
6046
6058
|
firstRefusalPromise ??= (async () => {
|
|
@@ -6053,12 +6065,29 @@ function admitWorkflowStageInbound(ctx, deliver, firstRefusal, onAdmissionFailur
|
|
|
6053
6065
|
})();
|
|
6054
6066
|
return firstRefusalPromise;
|
|
6055
6067
|
};
|
|
6056
|
-
return
|
|
6068
|
+
return run(admissionBarrier);
|
|
6057
6069
|
} catch (error) {
|
|
6058
6070
|
return Promise.reject(error);
|
|
6059
6071
|
}
|
|
6060
6072
|
}
|
|
6061
6073
|
|
|
6074
|
+
// dist/builtin/intercom/active-session-admission.ts
|
|
6075
|
+
function admitActiveSessionInbound(ctx, deliver, firstRefusal, onAdmissionFailure) {
|
|
6076
|
+
const executionEnded = ctx.subagentPolicy?.executionEnded;
|
|
6077
|
+
if (executionEnded !== undefined) {
|
|
6078
|
+
if (executionEnded.aborted || ctx.subagentPolicy?.messageAdmission?.isOpen() === false) {
|
|
6079
|
+
return Promise.reject(new Error("Subagent execution is terminal and cannot accept messages"));
|
|
6080
|
+
}
|
|
6081
|
+
try {
|
|
6082
|
+
return ctx.subagentPolicy?.messageAdmission?.run(deliver) ?? Promise.resolve(deliver());
|
|
6083
|
+
} catch (error) {
|
|
6084
|
+
return Promise.reject(error);
|
|
6085
|
+
}
|
|
6086
|
+
}
|
|
6087
|
+
return admitWorkflowStageInbound(ctx, deliver, firstRefusal, onAdmissionFailure);
|
|
6088
|
+
}
|
|
6089
|
+
var init_active_session_admission = () => {};
|
|
6090
|
+
|
|
6062
6091
|
// dist/builtin/intercom/workflow-reply-tracker.ts
|
|
6063
6092
|
function bindWorkflowReplyTracker(ctx, current) {
|
|
6064
6093
|
const state = ctx.orchestrationContext?.messageAdmission?.extensionState;
|
|
@@ -6112,7 +6141,7 @@ async function settleOpenStageDeliveryFailure(input, error) {
|
|
|
6112
6141
|
input.admission.release(input.reservation, failure);
|
|
6113
6142
|
return;
|
|
6114
6143
|
}
|
|
6115
|
-
const delivered = await sendWorkflowStageDeliveryFailure(input.entry, failure, input.tracker, input.currentClient, () => input.currentClient()?.isConnected() === true, "Running workflow stage could not admit intercom ask");
|
|
6144
|
+
const delivered = await sendWorkflowStageDeliveryFailure(input.entry, failure, input.tracker, input.currentClient, () => input.currentClient()?.isConnected() === true, input.failurePrefix ?? "Running workflow stage could not admit intercom ask");
|
|
6116
6145
|
if (delivered)
|
|
6117
6146
|
input.commit();
|
|
6118
6147
|
else
|
|
@@ -6479,17 +6508,18 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6479
6508
|
tracker: replyTracker,
|
|
6480
6509
|
replyContext,
|
|
6481
6510
|
currentClient: () => client,
|
|
6482
|
-
commit
|
|
6511
|
+
commit,
|
|
6512
|
+
failurePrefix: liveContext.subagentPolicy?.executionEnded === undefined ? undefined : "Subagent could not admit intercom ask"
|
|
6483
6513
|
});
|
|
6484
|
-
const
|
|
6514
|
+
const activeDelivery = admitActiveSessionInbound(liveContext, (admissionBarrier) => {
|
|
6485
6515
|
replyTracker.queueTurnContext(replyContext);
|
|
6486
6516
|
return retryStableDelivery({
|
|
6487
|
-
deliver: () => sendIncomingMessage(entry, "
|
|
6488
|
-
isCurrent: () => Boolean(getLiveContext(liveContext, messageGeneration))
|
|
6517
|
+
deliver: () => sendIncomingMessage(entry, "interrupt", messageGeneration, false, undefined, admissionBarrier),
|
|
6518
|
+
isCurrent: () => Boolean(getLiveContext(liveContext, messageGeneration)) && liveContext.subagentPolicy?.executionEnded?.aborted !== true && liveContext.subagentPolicy?.messageAdmission?.isOpen() !== false
|
|
6489
6519
|
});
|
|
6490
6520
|
}, () => foregroundDetachHandoff.claim(from, message, messageGeneration, () => Boolean(getLiveContext(liveContext, messageGeneration))), release);
|
|
6491
|
-
if (
|
|
6492
|
-
|
|
6521
|
+
if (activeDelivery !== false) {
|
|
6522
|
+
activeDelivery.then(commit, release);
|
|
6493
6523
|
return;
|
|
6494
6524
|
}
|
|
6495
6525
|
return (async () => {
|
|
@@ -6499,7 +6529,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6499
6529
|
release(new Error("Intercom session retired before inbound delivery"));
|
|
6500
6530
|
return;
|
|
6501
6531
|
}
|
|
6502
|
-
if (!activeContext.isIdle()) {
|
|
6532
|
+
if (!activeContext.isIdle() && !activeContext.getAgentTaskHost?.().hasActiveTaskWaits) {
|
|
6503
6533
|
if (!activeContext.hasUI) {
|
|
6504
6534
|
const activeClient = client;
|
|
6505
6535
|
if (!message.replyTo && activeClient?.isConnected()) {
|
|
@@ -6542,6 +6572,13 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6542
6572
|
});
|
|
6543
6573
|
return;
|
|
6544
6574
|
}
|
|
6575
|
+
if (!activeContext.isIdle()) {
|
|
6576
|
+
const disposition = await foregroundDetachHandoff.claim(from, message, messageGeneration, () => Boolean(getLiveContext(liveContext, messageGeneration)));
|
|
6577
|
+
if (disposition === "abandoned") {
|
|
6578
|
+
release(new Error("Intercom session retired during foreground-owner admission"));
|
|
6579
|
+
return;
|
|
6580
|
+
}
|
|
6581
|
+
}
|
|
6545
6582
|
replyTracker.queueTurnContext(replyContext);
|
|
6546
6583
|
await retryStableDelivery({ deliver: () => sendIncomingMessage(entry, "trigger", messageGeneration, false), isCurrent: () => Boolean(getLiveContext(liveContext, messageGeneration)) });
|
|
6547
6584
|
commit();
|
|
@@ -7118,6 +7155,7 @@ var init_index_heavy = __esm(() => {
|
|
|
7118
7155
|
init_terminal_ordering_barrier();
|
|
7119
7156
|
init_inbound_message_admission();
|
|
7120
7157
|
init_late_stage_message_router();
|
|
7158
|
+
init_active_session_admission();
|
|
7121
7159
|
init_workflow_reply_tracker();
|
|
7122
7160
|
init_closed_workflow_stage_message();
|
|
7123
7161
|
init_group();
|
|
@@ -7135,11 +7173,20 @@ var init_index_heavy = __esm(() => {
|
|
|
7135
7173
|
});
|
|
7136
7174
|
|
|
7137
7175
|
// dist/builtin/intercom/index.ts
|
|
7138
|
-
init_result_renderers();
|
|
7139
7176
|
import { APP_NAME as APP_NAME2, getEnvValue } from "@bastani/atomic";
|
|
7140
7177
|
import { Text as Text4 } from "@earendil-works/pi-tui";
|
|
7141
7178
|
import { Type as Type3 } from "typebox";
|
|
7142
7179
|
|
|
7180
|
+
// dist/builtin/intercom/context-owner.ts
|
|
7181
|
+
var CONTEXT_OWNERS_KEY = Symbol.for("atomic-coding-agent/extension-context-owners@1");
|
|
7182
|
+
function getExtensionContextOwner(context) {
|
|
7183
|
+
const owners = globalThis[CONTEXT_OWNERS_KEY];
|
|
7184
|
+
return owners?.get(context) ?? context;
|
|
7185
|
+
}
|
|
7186
|
+
|
|
7187
|
+
// dist/builtin/intercom/index.ts
|
|
7188
|
+
init_result_renderers();
|
|
7189
|
+
|
|
7143
7190
|
// dist/builtin/intercom/lazy-tool-execution.ts
|
|
7144
7191
|
init_recoverable_disconnect();
|
|
7145
7192
|
init_retry_policy();
|
|
@@ -7401,10 +7448,37 @@ function renderHeavyToolResult(loadedHeavy, name, args) {
|
|
|
7401
7448
|
return renderer(...args);
|
|
7402
7449
|
return renderIntercomToolResult(name, args);
|
|
7403
7450
|
}
|
|
7404
|
-
function
|
|
7451
|
+
function diagnosticDetail(error) {
|
|
7452
|
+
try {
|
|
7453
|
+
return String(error instanceof Error ? error.message : error);
|
|
7454
|
+
} catch {
|
|
7455
|
+
return "Unprintable error";
|
|
7456
|
+
}
|
|
7457
|
+
}
|
|
7458
|
+
function captureDiagnosticRoute(ctx) {
|
|
7459
|
+
try {
|
|
7460
|
+
return ctx?.hasUI && ctx.mode === "tui" ? ctx : "console";
|
|
7461
|
+
} catch {
|
|
7462
|
+
return "silent";
|
|
7463
|
+
}
|
|
7464
|
+
}
|
|
7465
|
+
function reportDiagnostic(route, message, error, level, consoleMessage = message) {
|
|
7466
|
+
if (route === "console") {
|
|
7467
|
+
console.error(consoleMessage, error);
|
|
7468
|
+
return;
|
|
7469
|
+
}
|
|
7470
|
+
if (route === "silent")
|
|
7471
|
+
return;
|
|
7472
|
+
try {
|
|
7473
|
+
route.ui.notify(message, level);
|
|
7474
|
+
} catch {}
|
|
7475
|
+
}
|
|
7476
|
+
function reportRelayFailure(route, eventName, error) {
|
|
7405
7477
|
if (isRecoverableIntercomDisconnect(error))
|
|
7406
7478
|
return;
|
|
7407
|
-
|
|
7479
|
+
const prefix = `Intercom event relay failed (${eventName}):`;
|
|
7480
|
+
const detail = diagnosticDetail(error);
|
|
7481
|
+
reportDiagnostic(route, `${prefix} ${detail}`, error, "error", prefix);
|
|
7408
7482
|
}
|
|
7409
7483
|
var WARM_UP_RETRY_ATTEMPTS = 5;
|
|
7410
7484
|
function intercom(pi, options = {}) {
|
|
@@ -7412,6 +7486,7 @@ function intercom(pi, options = {}) {
|
|
|
7412
7486
|
let heavyAttempt = null;
|
|
7413
7487
|
let loadedHeavy = null;
|
|
7414
7488
|
let sessionSnapshot = null;
|
|
7489
|
+
let shutdownDiagnosticRoute;
|
|
7415
7490
|
let lifecycleGeneration = 0;
|
|
7416
7491
|
let nextLeaseId = 1;
|
|
7417
7492
|
let activeLease = createLifecycleLease(nextLeaseId++);
|
|
@@ -7495,6 +7570,8 @@ function intercom(pi, options = {}) {
|
|
|
7495
7570
|
await promise;
|
|
7496
7571
|
}
|
|
7497
7572
|
async function loadHeavy(ctx) {
|
|
7573
|
+
let diagnosticRoute = captureDiagnosticRoute(ctx);
|
|
7574
|
+
let diagnosticOwner = ctx && getExtensionContextOwner(ctx);
|
|
7498
7575
|
const lease = activeLease;
|
|
7499
7576
|
if (lease.retired)
|
|
7500
7577
|
throw new Error("Intercom initialization unavailable: no active session");
|
|
@@ -7511,6 +7588,7 @@ function intercom(pi, options = {}) {
|
|
|
7511
7588
|
return handle;
|
|
7512
7589
|
}
|
|
7513
7590
|
let promise;
|
|
7591
|
+
let replayCtx = null;
|
|
7514
7592
|
promise = (async () => {
|
|
7515
7593
|
const captured = {
|
|
7516
7594
|
tools: new Map,
|
|
@@ -7519,7 +7597,6 @@ function intercom(pi, options = {}) {
|
|
|
7519
7597
|
shortcuts: new Map,
|
|
7520
7598
|
eventHandlers: new Map
|
|
7521
7599
|
};
|
|
7522
|
-
let replayCtx = null;
|
|
7523
7600
|
let cleaned = false;
|
|
7524
7601
|
const cleanupCandidate = async () => {
|
|
7525
7602
|
const shutdown = lease.shutdown;
|
|
@@ -7531,7 +7608,9 @@ function intercom(pi, options = {}) {
|
|
|
7531
7608
|
try {
|
|
7532
7609
|
await dispatchHandlers(captured, "session_shutdown", event, cleanupCtx);
|
|
7533
7610
|
} catch (cleanupError) {
|
|
7534
|
-
|
|
7611
|
+
const prefix = "Intercom failed to clean rejected lazy candidate:";
|
|
7612
|
+
const detail = diagnosticDetail(cleanupError);
|
|
7613
|
+
reportDiagnostic(shutdown?.diagnosticRoute ?? diagnosticRoute, `${prefix} ${detail}`, cleanupError, "error", prefix);
|
|
7535
7614
|
}
|
|
7536
7615
|
};
|
|
7537
7616
|
try {
|
|
@@ -7543,6 +7622,11 @@ function intercom(pi, options = {}) {
|
|
|
7543
7622
|
sessionSnapshot = { event: createSyntheticSessionStartEvent(), ctx, generation: ++lifecycleGeneration, lease };
|
|
7544
7623
|
}
|
|
7545
7624
|
await ensureSessionStartReplayed(captured, lease, (replayContext) => {
|
|
7625
|
+
const owner = getExtensionContextOwner(replayContext);
|
|
7626
|
+
if (owner !== diagnosticOwner) {
|
|
7627
|
+
diagnosticRoute = captureDiagnosticRoute(replayContext);
|
|
7628
|
+
diagnosticOwner = owner;
|
|
7629
|
+
}
|
|
7546
7630
|
replayCtx = replayContext;
|
|
7547
7631
|
});
|
|
7548
7632
|
assertLease(lease);
|
|
@@ -7561,8 +7645,8 @@ function intercom(pi, options = {}) {
|
|
|
7561
7645
|
if (heavyAttempt?.promise === promise)
|
|
7562
7646
|
heavyAttempt = null;
|
|
7563
7647
|
if (!isRecoverableIntercomDisconnect(error)) {
|
|
7564
|
-
const message =
|
|
7565
|
-
|
|
7648
|
+
const message = diagnosticDetail(error);
|
|
7649
|
+
reportDiagnostic(diagnosticRoute, `Intercom heavy initialization failed; a later call will retry: ${message}`, error, "warning");
|
|
7566
7650
|
}
|
|
7567
7651
|
});
|
|
7568
7652
|
return promise;
|
|
@@ -7673,6 +7757,7 @@ function intercom(pi, options = {}) {
|
|
|
7673
7757
|
}
|
|
7674
7758
|
const generation = ++lifecycleGeneration;
|
|
7675
7759
|
sessionSnapshot = { event, ctx, generation, lease };
|
|
7760
|
+
shutdownDiagnosticRoute = undefined;
|
|
7676
7761
|
cancelWarmUpRetry();
|
|
7677
7762
|
if (ctx.orchestrationContext?.kind === "workflow-stage" && ctx.orchestrationContext.pendingStageDelivery !== undefined) {
|
|
7678
7763
|
const pendingStageDelivery = ctx.orchestrationContext.pendingStageDelivery;
|
|
@@ -7690,7 +7775,9 @@ function intercom(pi, options = {}) {
|
|
|
7690
7775
|
pi.on("session_shutdown", async (event, ctx) => {
|
|
7691
7776
|
const lease = activeLease;
|
|
7692
7777
|
const generation = ++lifecycleGeneration;
|
|
7693
|
-
|
|
7778
|
+
const diagnosticRoute = captureDiagnosticRoute(ctx);
|
|
7779
|
+
retireLifecycleLease(lease, { event, ctx, generation, diagnosticRoute });
|
|
7780
|
+
shutdownDiagnosticRoute = diagnosticRoute;
|
|
7694
7781
|
cancelWarmUpRetry();
|
|
7695
7782
|
const retiredHeavy = loadedHeavy?.heavy ?? null;
|
|
7696
7783
|
const retiredAttempt = heavyAttempt?.lease === lease ? heavyAttempt.promise : null;
|
|
@@ -7811,13 +7898,15 @@ function intercom(pi, options = {}) {
|
|
|
7811
7898
|
return;
|
|
7812
7899
|
payload.handled = true;
|
|
7813
7900
|
const forwarded = { ...payload, handled: false, completion: undefined };
|
|
7814
|
-
|
|
7901
|
+
const ctx = latestLifecycleContext();
|
|
7902
|
+
const diagnosticRoute = ctx ? captureDiagnosticRoute(ctx) : shutdownDiagnosticRoute ?? "console";
|
|
7903
|
+
payload.completion = loadHeavy(ctx).then(async (handle) => {
|
|
7815
7904
|
handle.assertCurrent();
|
|
7816
7905
|
await dispatchEventHandlers(handle.heavy, PENDING_STAGE_UNDELIVERABLE_EVENT2, forwarded);
|
|
7817
7906
|
handle.assertCurrent();
|
|
7818
7907
|
return forwarded.handled === true && forwarded.completion !== undefined ? await forwarded.completion : false;
|
|
7819
7908
|
}).catch((error) => {
|
|
7820
|
-
reportRelayFailure(PENDING_STAGE_UNDELIVERABLE_EVENT2, error);
|
|
7909
|
+
reportRelayFailure(diagnosticRoute, PENDING_STAGE_UNDELIVERABLE_EVENT2, error);
|
|
7821
7910
|
return false;
|
|
7822
7911
|
});
|
|
7823
7912
|
});
|
|
@@ -7827,7 +7916,9 @@ function intercom(pi, options = {}) {
|
|
|
7827
7916
|
PENDING_STAGE_ROUTE_EVENT2
|
|
7828
7917
|
]) {
|
|
7829
7918
|
pi.events.on(eventName, (payload) => {
|
|
7830
|
-
const
|
|
7919
|
+
const ctx = latestLifecycleContext();
|
|
7920
|
+
const diagnosticRoute = ctx ? captureDiagnosticRoute(ctx) : shutdownDiagnosticRoute ?? "console";
|
|
7921
|
+
const completion = loadHeavy(ctx).then(async (handle) => {
|
|
7831
7922
|
handle.assertCurrent();
|
|
7832
7923
|
await dispatchEventHandlers(handle.heavy, eventName, payload);
|
|
7833
7924
|
handle.assertCurrent();
|
|
@@ -7842,7 +7933,7 @@ function intercom(pi, options = {}) {
|
|
|
7842
7933
|
}
|
|
7843
7934
|
completion.catch((error) => {
|
|
7844
7935
|
rejectLazyResultRelay(pi, eventName, payload, error);
|
|
7845
|
-
reportRelayFailure(eventName, error);
|
|
7936
|
+
reportRelayFailure(diagnosticRoute, eventName, error);
|
|
7846
7937
|
});
|
|
7847
7938
|
});
|
|
7848
7939
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/intercom",
|
|
3
|
-
"version": "0.9.19-alpha.
|
|
3
|
+
"version": "0.9.19-alpha.5",
|
|
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": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/mcp",
|
|
3
|
-
"version": "0.9.19-alpha.
|
|
3
|
+
"version": "0.9.19-alpha.5",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension that adapts MCP (Model Context Protocol) servers into the coding agent. Fork of: https://github.com/nicobailon/pi-mcp-adapter",
|
|
6
6
|
"contributors": [
|
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.19-alpha.5] - 2026-09-11
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- The bundled debugger now uses GPT-6 Astra at `medium`, with Astra/Fable 5.1/Fable 5 fallbacks at `medium` and Sol at `high`. Its complete fallback order, other model efforts, and all other bundled agent configurations remain unchanged.
|
|
10
|
+
|
|
11
|
+
## [0.9.19-alpha.4] - 2026-09-10
|
|
12
|
+
|
|
13
|
+
### Breaking Changes
|
|
14
|
+
|
|
15
|
+
- Renamed the terminal subagent control action from `interrupt` to `kill`. Replace `subagent({ action: "interrupt", id })` with `subagent({ action: "kill", id })`, including calls using `runId`. The old action is rejected, not aliased. Killed children cannot be resumed; launch a fresh child with explicit context for follow-up work. Command results and status report killed, while parent cancellation and lower-level host/native interruption retain their existing semantics.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Preserved an explicit kill when parent cancellation arrives during execution-capacity waiting, without allowing a late kill to replace an earlier parent cancellation.
|
|
20
|
+
- Kept grouped Intercom cancellation status consistent when a killed child has parent-cancelled siblings, while retaining each child's outcome.
|
|
21
|
+
- Intercom `send` and `ask` interrupt a working foreground or background child immediately: its current model call or cancellable tool is cancelled and the message is handled in the same child execution without relaunch. Messages admitted during startup, consumed input preflight, overlapping SDK interrupt turns, or final settlement still join the original task rather than creating competing work or disappearing ahead of the result; explicit user abort and owner cancellation remain terminal.
|
|
22
|
+
|
|
5
23
|
## [0.9.19-alpha.3] - 2026-09-09
|
|
6
24
|
|
|
7
25
|
### Changed
|
|
@@ -125,7 +125,7 @@ There is no generic `reviewer` or `planner` agent; pick the specialist whose ang
|
|
|
125
125
|
|
|
126
126
|
## Changing a builtin agent's model
|
|
127
127
|
|
|
128
|
-
Builtin agents
|
|
128
|
+
Builtin agents declare role-specific models and ordered fallbacks. The debugger starts with `openai-codex/gpt-6-astra:medium`, with Astra/Fable fallbacks at `medium` and Sol/Opus fallbacks at `high`. See the [bundled defaults](../coding-agent/docs/subagents.md#bundled-agents) for the other roles. If you want a role to use a specific model, set an override instead of copying the bundled agent file.
|
|
129
129
|
|
|
130
130
|
For one run, pass `model` on the `subagent` call:
|
|
131
131
|
|
|
@@ -134,7 +134,7 @@ subagent({ agent: "codebase-analyzer", task: "Review this diff", model: "anthrop
|
|
|
134
134
|
```
|
|
135
135
|
|
|
136
136
|
|
|
137
|
-
For a persistent override, edit settings. This example pins the codebase-analyzer everywhere, adds a backup model for provider failures, and keeps the other builtins on
|
|
137
|
+
For a persistent override, edit settings. This example pins the codebase-analyzer everywhere, adds a backup model for provider failures, and keeps the other builtins on their configured defaults:
|
|
138
138
|
|
|
139
139
|
```json
|
|
140
140
|
{
|
|
@@ -181,7 +181,7 @@ subagent({ agent: "codebase-analyzer", task: "Trace authentication.", wait: { ki
|
|
|
181
181
|
subagent({ agent: "codebase-analyzer", task: "Trace authentication.", wait: { kind: "foreground", budgetMs: 30000 } })
|
|
182
182
|
subagent({ action: "wait", id: taskId, budgetMs: 1000 })
|
|
183
183
|
subagent({ action: "status", id: taskId })
|
|
184
|
-
subagent({ action: "
|
|
184
|
+
subagent({ action: "kill", id: taskId })
|
|
185
185
|
```
|
|
186
186
|
|
|
187
187
|
In owner-bound sessions, omitted `wait` means background. Explicit foreground waits use the owner's agent observation budget, normally 30 seconds, unless overridden. Expiry releases the caller, not the execution. Wait or inspect the returned task ID instead of launching a duplicate. Existing SDK callers without an owner retain their original execution path.
|
|
@@ -200,7 +200,7 @@ clarify → gather context → worker → fresh reviewers → worker
|
|
|
200
200
|
|
|
201
201
|
Packaged `worker` defaults to forked context when a launch omits `context`; every other builtin runs fresh. Pass `context: "fresh"` when you intentionally want a fresh `worker` run.
|
|
202
202
|
|
|
203
|
-
Child-safety boundaries are enforced at runtime by typed admission policy. In-process child sessions load bundled extensions through normal discovery. The `subagent` tool may therefore be registered when the child's active tool selection permits it, including the default no-allowlist case; an explicit allowlist may omit it. Tool presence does not grant fanout: fanout is authorized only when the resolved builtin `tools` list includes `subagent`. Typed admission policy lets a non-fanout child use only `list`, `get`, and `status`; delegation and `
|
|
203
|
+
Child-safety boundaries are enforced at runtime by typed admission policy. In-process child sessions load bundled extensions through normal discovery. The `subagent` tool may therefore be registered when the child's active tool selection permits it, including the default no-allowlist case; an explicit allowlist may omit it. Tool presence does not grant fanout: fanout is authorized only when the resolved builtin `tools` list includes `subagent`. Typed admission policy lets a non-fanout child use only `list`, `get`, and `status`; delegation and `kill` receive the fanout refusal. A management-restricted child is also refused `create`, `update`, and `delete`. The bundled `pi-subagents` skill remains parent-only and is stripped from child prompts, including fanout-authorized children. No admitted child may delegate or control another child: launches and `kill` are refused for every child regardless of its fanout authorization. Children receive boundary instructions that they are not the parent orchestrator and must complete their assigned task directly. Forked child context filtering also removes parent-only subagent artifacts (including old hidden orchestration-instruction messages, slash/status/control messages, and prior parent `subagent` tool-call/tool-result history) while preserving ordinary prose and unrelated tool calls/results.
|
|
204
204
|
|
|
205
205
|
|
|
206
206
|
|
|
@@ -230,13 +230,13 @@ The child can use one dedicated coordination tool:
|
|
|
230
230
|
|
|
231
231
|
Child-side routine completion handoffs are still not expected. In parallel runs, blocking `contact_supervisor` decisions/interviews and parent-targeted `intercom.ask` wait only in the requesting child. The supervisor replies through Intercom to the exact question; the same child continues with its original context and run identity. Sends and progress updates return without a reply.
|
|
232
232
|
|
|
233
|
-
An exact-child probe/commit handshake may release parallel foreground observations, including queued slots, so the parent can respond. It does not end any execution or spend a running concurrency slot. Active siblings keep working, queued siblings start once capacity becomes available, and worktrees remain until their owners finish. Do not relaunch children to answer an ask. Targeted
|
|
233
|
+
An exact-child probe/commit handshake may release parallel foreground observations, including queued slots, so the parent can respond. It does not end any execution or spend a running concurrency slot. Active siblings keep working, queued siblings start once capacity becomes available, and worktrees remain until their owners finish. Do not relaunch children to answer an ask. Targeted kill, explicit batch cancellation, and owner closure remain separate controls.
|
|
234
234
|
|
|
235
235
|
Single-child launches retain their existing terminal parent-ask handoff: the exact live child ends before broker send or waiter admission and the parent receives the verbatim question, ordered attachments, identity, and `[TASK_CONTEXT]` for a fresh child. The bridge still obtains each child's capability during admission; the child connects only when it uses Intercom.
|
|
236
236
|
|
|
237
237
|
Parent-side Atomic sends grouped completion results through Intercom: one grouped message per foreground parent `subagent` run and one per detached child completion while its owning session remains live. When a workflow stage completes, Atomic cancels its still-running detached children and suppresses their late findings and completion notifications instead of forwarding them to the parent/main chat. Intercom-confirmed delivery returns a compact receipt with artifact/session paths; without that confirmation, the normal full output is preserved. Grouped messages include child Intercom targets and full child summaries.
|
|
238
238
|
|
|
239
|
-
If a child appears stalled, needs-attention notices can show up in the parent session with useful next actions, such as checking `subagent({ action: "status" })`,
|
|
239
|
+
If a child appears stalled, needs-attention notices can show up in the parent session with useful next actions, such as checking `subagent({ action: "status" })`, killing the run, or nudging the child.
|
|
240
240
|
|
|
241
241
|
If messages do not show up, check the bridge from the intercom side with `intercom({ action: "status" })`.
|
|
242
242
|
|
|
@@ -263,7 +263,7 @@ Agent locations, lowest to highest priority:
|
|
|
263
263
|
|
|
264
264
|
Project discovery also reads legacy `.agents/**/*.md` and `.pi/agents/**/*.md` files. Nested subdirectories are discovered recursively. If primary Atomic and legacy paths define the same parsed runtime agent name, the primary `.atomic/agents/` definition wins. Use `agentScope: "user" | "project" | "both"` to control discovery; `both` is the default and project definitions win runtime-name collisions.
|
|
265
265
|
|
|
266
|
-
Builtin agents load at the lowest priority, so a user or project agent with the same name overrides them.
|
|
266
|
+
Builtin agents load at the lowest priority, so a user or project agent with the same name overrides them. Their declared models and fallback chains apply unless you set an override such as `subagents.agentOverrides.<name>.model`. `worker` is the implementation agent for normal tasks and approved orchestrator handoffs.
|
|
267
267
|
|
|
268
268
|
The `codebase-online-researcher` builtin uses `web_search`, `fetch_content`, and `get_search_content`; those require [pi-web-access](https://github.com/nicobailon/pi-web-access):
|
|
269
269
|
|
|
@@ -434,7 +434,7 @@ What the bundled skill covers:
|
|
|
434
434
|
- **Role-agent prompting guidance**: compact contract prompts instead of long scripts, what to include in role-specific meta prompts, and retrieval budgets for researchers
|
|
435
435
|
- **Safety boundaries**: child agents must not run subagents, must not invent intercom targets, and must escalate unapproved decisions
|
|
436
436
|
- **Intercom conventions**: when to ask vs send, and how parent-side result delivery works with `pi-intercom`
|
|
437
|
-
- **Control signals**: attention signals,
|
|
437
|
+
- **Control signals**: attention signals, terminal kills, and status
|
|
438
438
|
|
|
439
439
|
If you are writing an agent that orchestrates subagents, the bundled skill helps it behave correctly without guessing the patterns. If you are a human user, you do not need to read it directly; the README and prompt shortcuts encode the same workflows in user-facing form.
|
|
440
440
|
|
|
@@ -524,11 +524,11 @@ Agent definitions are not loaded into context by default. Management actions let
|
|
|
524
524
|
|-------|------|---------|-------------|
|
|
525
525
|
| `agent` | string | - | Agent name for single mode, or target for management actions. |
|
|
526
526
|
| `task` | string | - | Task string for single mode. |
|
|
527
|
-
| `action` | string | - | `list`, `get`, `create`, `update`, `delete`, `status`, `wait`, or `
|
|
527
|
+
| `action` | string | - | `list`, `get`, `create`, `update`, `delete`, `status`, `wait`, or `kill`. |
|
|
528
528
|
| `config` | object/string | - | Agent config for create/update. |
|
|
529
529
|
| `wait` | object | background in owner-bound sessions | `{ kind: "background" }` yields after admission; `{ kind: "foreground", budgetMs?: number }` waits before automatically yielding. |
|
|
530
530
|
| `budgetMs` | number | owner wait policy | Observation budget for `action: "wait"`; not a child execution deadline. |
|
|
531
|
-
| `id` | string | - | Task ID returned by an owner-bound launch for `wait`, `status`, or `
|
|
531
|
+
| `id` | string | - | Task ID returned by an owner-bound launch for `wait`, `status`, or `kill`. |
|
|
532
532
|
| `output` | `string \| false` | agent default | Override single-agent output file. |
|
|
533
533
|
| `outputMode` | `"inline" \| "file-only"` | `inline` | Return saved output inline or as a concise saved-file reference. `file-only` requires an `output` path. |
|
|
534
534
|
| `reads` | `string[] \| false` | - | Single-agent files to read before execution, or `false` to disable. Relative paths resolve against the effective child `cwd`; absolute paths pass through. |
|
|
@@ -557,10 +557,10 @@ Status and control actions:
|
|
|
557
557
|
```ts
|
|
558
558
|
subagent({ action: "status" })
|
|
559
559
|
subagent({ action: "status", id: "<run-id>" })
|
|
560
|
-
subagent({ action: "
|
|
560
|
+
subagent({ action: "kill", id: "<run-id>" })
|
|
561
561
|
```
|
|
562
562
|
|
|
563
|
-
Completed, interrupted, and single-child terminal-handoff children cannot be revived by a prior run ID; 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.
|
|
563
|
+
Completed, killed, interrupted, and single-child terminal-handoff children cannot be revived by a prior run ID; 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: "interrupt"` to `action: "kill"`; the old action is rejected. Kill is terminal and cannot be resumed. Workflow controls use `pause`; host interrupt APIs are unchanged.
|
|
564
564
|
|
|
565
565
|
## Worktree isolation
|
|
566
566
|
|
|
@@ -681,7 +681,7 @@ Foreground runs persist their session and user-facing artifacts beside the paren
|
|
|
681
681
|
run-history.jsonl
|
|
682
682
|
```
|
|
683
683
|
|
|
684
|
-
Task-ID status, wait, and
|
|
684
|
+
Task-ID status, wait, and kill resolve the same owner as launch. Run-ID status uses the existing Rust subagent registry. Owner-bound completion delivery uses persisted intent and acknowledgement records in session history; no second PID registry or execution is created for the UI.
|
|
685
685
|
|
|
686
686
|
## Completion and output
|
|
687
687
|
|
|
@@ -716,7 +716,7 @@ This is disabled by default. Session data may contain source code, paths, enviro
|
|
|
716
716
|
|
|
717
717
|
## Delegation boundary
|
|
718
718
|
|
|
719
|
-
Delegation is exactly one level deep, and nothing configures it. A top-level session
|
|
719
|
+
Delegation is exactly one level deep, and nothing configures it. A top-level session, main chat or a workflow stage, may call `subagent`. A session that was itself admitted as a subagent child may not: every launch and `kill` it attempts is refused with guidance to complete its assigned task directly. The observing actions `list`, `get`, and `status` stay available to a child. Child sessions retain bundled workflow definitions as resources but do not load the workflows extension or expose its `workflow` tool; orchestration stays owned by the parent session.
|
|
720
720
|
|
|
721
721
|
There is no configuration option, agent frontmatter field, or tool parameter for the delegation level. The rule is enforced twice: the subagent executor refuses a child before any run starts, and the Rust `SubagentControl` admission door refuses a child deeper than the single permitted level. Admitted depth is typed admission state and is not inherited through an environment variable.
|
|
722
722
|
|
|
@@ -773,7 +773,7 @@ The main runtime files are:
|
|
|
773
773
|
|------|---------|
|
|
774
774
|
| `src/extension/index.ts` | Extension registration, tool registration, message/render wiring. |
|
|
775
775
|
| `src/agents/agents.ts` | Agent discovery and frontmatter parsing. |
|
|
776
|
-
| `src/runs/foreground/subagent-executor.ts` | Main execution routing for single, parallel, management, status, and
|
|
776
|
+
| `src/runs/foreground/subagent-executor.ts` | Main execution routing for single, parallel, management, status, and kill actions. |
|
|
777
777
|
| `src/runs/foreground/execution.ts` | Core foreground `runSync` handling. |
|
|
778
778
|
| `src/runs/foreground/notify.ts` | Completion-notification delivery for a detached Intercom child. |
|
|
779
779
|
| `src/runs/foreground/completion-notification.ts` | Local completion acknowledgement and ordering barrier for detached children. |
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
name: debugger
|
|
3
3
|
description: Debug and fix errors, test failures, and unexpected behavior. Use PROACTIVELY when encountering issues, analyzing stack traces, or investigating system problems.
|
|
4
4
|
tools: read, edit, write, search, find, ls, bash, web_search, fetch_content, get_search_content, intercom, contact_supervisor, todo
|
|
5
|
-
model: openai-codex/gpt-6-astra:
|
|
6
|
-
fallbackModels: github-copilot/gpt-6-astra:
|
|
5
|
+
model: openai-codex/gpt-6-astra:medium
|
|
6
|
+
fallbackModels: github-copilot/gpt-6-astra:medium, openai/gpt-6-astra:medium, anthropic/claude-fable-5-1:medium, github-copilot/claude-fable-5-1:medium, anthropic/claude-opus-5:high, github-copilot/claude-opus-5:high, anthropic/claude-fable-5:medium, github-copilot/claude-fable-5:medium, openai-codex/gpt-5.6-sol:high, github-copilot/gpt-5.6-sol:high, openai/gpt-5.6-sol:high, kimi-coding/k3:max, moonshotai/kimi-k3:max, moonshotai-cn/kimi-k3:max, openai-codex/gpt-5.5:xhigh, github-copilot/gpt-5.5:xhigh, openai/gpt-5.5:xhigh, anthropic/claude-opus-4-8:high, github-copilot/claude-opus-4.8:high, xai/grok-4.6:xhigh, github-copilot/grok-4.6:xhigh, zai/glm-5.3:high, zai-coding-cn/glm-5.3:high, zai/glm-5.3-flash:high, zai-coding-cn/glm-5.3-flash:high, baseten/zai-org/GLM-5.3:high, baseten/zai-org/GLM-5.3-Flash:high, openrouter/openai/gpt-6-astra:medium, openrouter/anthropic/claude-fable-5-1:medium, openrouter/anthropic/claude-opus-5:high, openrouter/anthropic/claude-fable-5:medium, openrouter/openai/gpt-5.6-sol:high, openrouter/moonshotai/kimi-k3:max, openrouter/sakana/fugu-ultra:high, openrouter/openai/gpt-5.5:xhigh, openrouter/anthropic/claude-opus-4-8:high, openrouter/x-ai/grok-4.6:xhigh, openrouter/z-ai/glm-5.3:high, openrouter/z-ai/glm-5.3-flash:high
|
|
7
7
|
skills: tdd, playwright-cli, tmux
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/subagents",
|
|
3
|
-
"version": "0.9.19-alpha.
|
|
3
|
+
"version": "0.9.19-alpha.5",
|
|
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": [
|