@bastani/atomic 0.9.12-alpha.1 → 0.9.13-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 +34 -0
- package/dist/builtin/intercom/CHANGELOG.md +12 -0
- package/dist/builtin/intercom/README.md +5 -12
- package/dist/builtin/intercom/broker/client.ts +11 -2
- package/dist/builtin/intercom/contact-supervisor-tool.ts +13 -3
- package/dist/builtin/intercom/index-heavy.ts +13 -3
- package/dist/builtin/intercom/index.ts +43 -19
- package/dist/builtin/intercom/intercom-utils.ts +15 -29
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/intercom/source-ownership.ts +9 -12
- package/dist/builtin/mcp/CHANGELOG.md +12 -0
- package/dist/builtin/mcp/README.md +3 -1
- package/dist/builtin/mcp/index.ts +10 -16
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/mcp/startup-warmup.ts +20 -8
- package/dist/builtin/subagents/CHANGELOG.md +36 -0
- package/dist/builtin/subagents/README.md +22 -30
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/src/extension/doctor.ts +1 -1
- package/dist/builtin/subagents/src/extension/fanout-child.ts +76 -56
- package/dist/builtin/subagents/src/extension/index.ts +23 -32
- package/dist/builtin/subagents/src/extension/startup-maintenance.ts +25 -44
- package/dist/builtin/subagents/src/intercom/result-intercom.ts +7 -7
- package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +166 -434
- package/dist/builtin/subagents/src/runs/background/notify.ts +29 -8
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-dynamic-step.ts +2 -2
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +4 -4
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +2 -2
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +2 -2
- package/dist/builtin/subagents/src/runs/foreground/execution-run-sync.ts +1 -281
- package/dist/builtin/subagents/src/runs/foreground/execution-structured-retries.ts +11 -75
- package/dist/builtin/subagents/src/runs/foreground/inprocess-run-sync.ts +457 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +119 -246
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-chain.ts +1 -1
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +18 -9
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +1 -1
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +4 -4
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +1 -646
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-runtime.ts +2 -7
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +5 -5
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +7 -8
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +14 -5
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +158 -93
- package/dist/builtin/subagents/src/runs/inprocess/background-single.ts +179 -0
- package/dist/builtin/subagents/src/runs/inprocess/background.ts +89 -0
- package/dist/builtin/subagents/src/runs/inprocess/child-policy.ts +27 -0
- package/dist/builtin/subagents/src/runs/inprocess/control-registry.ts +55 -0
- package/dist/builtin/subagents/src/runs/inprocess/control-status.ts +106 -0
- package/dist/builtin/subagents/src/runs/inprocess/index.ts +50 -0
- package/dist/builtin/subagents/src/runs/inprocess/nested-routing.ts +218 -0
- package/dist/builtin/subagents/src/runs/{shared/subagent-prompt-runtime.ts → inprocess/prompt-behavior.ts} +37 -75
- package/dist/builtin/subagents/src/runs/inprocess/runner.ts +1138 -0
- package/dist/builtin/subagents/src/runs/{shared/nested-events.ts → inprocess/runtime-support/nested-api.ts} +13 -7
- package/dist/builtin/subagents/src/runs/{shared/nested-events-control.ts → inprocess/runtime-support/nested-control.ts} +18 -17
- package/dist/builtin/subagents/src/runs/{shared/nested-events-core.ts → inprocess/runtime-support/nested-core.ts} +14 -61
- package/dist/builtin/subagents/src/runs/{shared/nested-events-projection.ts → inprocess/runtime-support/nested-projection.ts} +4 -10
- package/dist/builtin/subagents/src/runs/{shared/nested-events-registry.ts → inprocess/runtime-support/nested-registry.ts} +19 -4
- package/dist/builtin/subagents/src/runs/{shared/nested-render.ts → inprocess/runtime-support/nested-rendering.ts} +3 -3
- package/dist/builtin/subagents/src/runs/{shared/nested-events-sanitize.ts → inprocess/runtime-support/nested-sanitize.ts} +3 -3
- package/dist/builtin/subagents/src/runs/inprocess.ts +1 -0
- package/dist/builtin/subagents/src/runs/shared/dynamic-fanout.ts +10 -4
- package/dist/builtin/subagents/src/runs/shared/model-candidate-filter.ts +0 -1
- package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +15 -492
- package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +13 -11
- package/dist/builtin/subagents/src/runs/shared/run-history.ts +3 -5
- package/dist/builtin/subagents/src/runs/shared/single-output.ts +4 -4
- package/dist/builtin/subagents/src/runs/shared/workflow-graph.ts +5 -5
- package/dist/builtin/subagents/src/shared/types-async.ts +0 -1
- package/dist/builtin/subagents/src/shared/types-config.ts +18 -0
- package/dist/builtin/subagents/src/shared/types-results.ts +9 -2
- package/dist/builtin/subagents/src/slash/prompt-template-bridge.ts +2 -3
- package/dist/builtin/subagents/src/slash/slash-live-state.ts +2 -2
- package/dist/builtin/subagents/src/tui/render-chain-graph.ts +10 -4
- package/dist/builtin/subagents/src/tui/render-event-formatting.ts +12 -11
- package/dist/builtin/subagents/src/tui/render-result-compact.ts +49 -12
- package/dist/builtin/subagents/src/tui/render-result.ts +46 -17
- package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -1
- package/dist/builtin/subagents/src/tui/render-status-progress.ts +8 -5
- package/dist/builtin/subagents/src/tui/render-widget-graph.ts +0 -8
- package/dist/builtin/subagents/src/tui/render-widget.ts +0 -24
- package/dist/builtin/web-access/CHANGELOG.md +6 -0
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +38 -0
- package/dist/builtin/workflows/README.md +13 -3
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/durable/backend.ts +7 -0
- package/dist/builtin/workflows/src/durable/dbos-metadata.ts +11 -1
- package/dist/builtin/workflows/src/durable/resume-runtime.ts +1 -0
- package/dist/builtin/workflows/src/durable/tool-primitive.ts +4 -28
- package/dist/builtin/workflows/src/durable/types.ts +5 -0
- package/dist/builtin/workflows/src/engine/run.ts +17 -1
- package/dist/builtin/workflows/src/extension/atomic-stage-session.ts +12 -39
- package/dist/builtin/workflows/src/extension/config-file-loader.ts +10 -1
- package/dist/builtin/workflows/src/extension/config-loader.ts +1 -1
- package/dist/builtin/workflows/src/extension/dispatcher.ts +4 -0
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +1151 -737
- package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +303 -38
- package/dist/builtin/workflows/src/extension/render-result.ts +4 -0
- package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +6 -3
- package/dist/builtin/workflows/src/extension/runtime.ts +7 -1
- package/dist/builtin/workflows/src/extension/wiring.ts +53 -11
- package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +12 -3
- package/dist/builtin/workflows/src/extension/workflow-durable-resume-command.ts +5 -2
- package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +9 -7
- package/dist/builtin/workflows/src/extension/workflow-status-summary.ts +11 -0
- package/dist/builtin/workflows/src/extension/workflow-tool-content.ts +18 -1
- package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +10 -8
- package/dist/builtin/workflows/src/extension/workflow-tool.ts +9 -4
- package/dist/builtin/workflows/src/runs/background/quit.ts +28 -4
- package/dist/builtin/workflows/src/runs/background/resume-acknowledgements.ts +2 -1
- package/dist/builtin/workflows/src/runs/background/status.ts +55 -8
- package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +4 -0
- package/dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts +3 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +688 -38
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +3 -1
- package/dist/builtin/workflows/src/runs/shared/model-fallback-failures.ts +19 -514
- package/dist/builtin/workflows/src/runs/shared/retry.ts +44 -0
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +5 -0
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +6 -0
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +5 -1
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +5 -0
- package/dist/builtin/workflows/src/shared/persistence-restore-helpers.ts +5 -0
- package/dist/builtin/workflows/src/shared/persistence-restore.ts +3 -0
- package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +4 -0
- package/dist/builtin/workflows/src/shared/run-indicator-status.ts +75 -0
- package/dist/builtin/workflows/src/shared/store-public-types.ts +43 -7
- package/dist/builtin/workflows/src/shared/store-run-methods.ts +42 -8
- package/dist/builtin/workflows/src/shared/store-stage-methods.ts +31 -8
- package/dist/builtin/workflows/src/shared/store-types.ts +34 -0
- package/dist/builtin/workflows/src/shared/timing.ts +10 -0
- package/dist/builtin/workflows/src/tui/chat-surface-message.ts +22 -2
- package/dist/builtin/workflows/src/tui/session-list.ts +1 -1
- package/dist/builtin/workflows/src/tui/session-overlays.ts +14 -10
- package/dist/builtin/workflows/src/tui/session-picker.ts +20 -4
- package/dist/builtin/workflows/src/tui/status-list.ts +31 -47
- package/dist/builtin/workflows/src/tui/store-widget-installer.ts +9 -1
- package/dist/builtin/workflows/src/tui/widget.ts +16 -46
- package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-auto-compaction.js +54 -11
- package/dist/core/agent-session-auto-compaction.js.map +1 -1
- package/dist/core/agent-session-events.d.ts.map +1 -1
- package/dist/core/agent-session-events.js +49 -14
- package/dist/core/agent-session-events.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +13 -0
- 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-models.d.ts.map +1 -1
- package/dist/core/agent-session-models.js +12 -1
- package/dist/core/agent-session-models.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +4 -0
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-retry.d.ts +21 -4
- package/dist/core/agent-session-retry.d.ts.map +1 -1
- package/dist/core/agent-session-retry.js +232 -106
- package/dist/core/agent-session-retry.js.map +1 -1
- package/dist/core/agent-session-state.d.ts.map +1 -1
- package/dist/core/agent-session-state.js +2 -1
- package/dist/core/agent-session-state.js.map +1 -1
- package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
- package/dist/core/agent-session-tool-hooks.js +12 -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 +1 -1
- package/dist/core/agent-session-tool-registry.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +3 -1
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/agent-session.d.ts +12 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +7 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/context-types.d.ts +25 -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/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/runner-context.d.ts +2 -1
- package/dist/core/extensions/runner-context.d.ts.map +1 -1
- package/dist/core/extensions/runner-context.js +4 -0
- package/dist/core/extensions/runner-context.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -2
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +3 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/model-fallback-failures.d.ts +30 -0
- package/dist/core/model-fallback-failures.d.ts.map +1 -0
- package/dist/core/model-fallback-failures.js +610 -0
- package/dist/core/model-fallback-failures.js.map +1 -0
- package/dist/core/retry-policy.d.ts +30 -0
- package/dist/core/retry-policy.d.ts.map +1 -0
- package/dist/core/retry-policy.js +25 -0
- package/dist/core/retry-policy.js.map +1 -0
- package/dist/core/sdk-types.d.ts +8 -2
- package/dist/core/sdk-types.d.ts.map +1 -1
- package/dist/core/sdk-types.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +6 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager-core.d.ts +2 -0
- package/dist/core/session-manager-core.d.ts.map +1 -1
- package/dist/core/session-manager-core.js +7 -0
- package/dist/core/session-manager-core.js.map +1 -1
- package/dist/index-extensions.d.ts +1 -1
- package/dist/index-extensions.d.ts.map +1 -1
- package/dist/index-extensions.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/docs/intercom.md +5 -10
- package/docs/settings.md +7 -1
- package/docs/subagents.md +19 -19
- package/docs/workflows.md +21 -5
- package/examples/extensions/gondolin/package-lock.json +3 -3
- package/npm-shrinkwrap.json +29 -29
- package/package.json +2 -2
- package/dist/builtin/subagents/src/runs/background/async-event-journal.ts +0 -112
- package/dist/builtin/subagents/src/runs/background/async-execution-chain.ts +0 -543
- package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +0 -140
- package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +0 -279
- package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +0 -99
- package/dist/builtin/subagents/src/runs/background/async-execution.ts +0 -17
- package/dist/builtin/subagents/src/runs/background/async-resume.ts +0 -402
- package/dist/builtin/subagents/src/runs/background/async-status.ts +0 -411
- package/dist/builtin/subagents/src/runs/background/completion-claims.ts +0 -196
- package/dist/builtin/subagents/src/runs/background/completion-dedupe.ts +0 -102
- package/dist/builtin/subagents/src/runs/background/parallel-groups.ts +0 -59
- package/dist/builtin/subagents/src/runs/background/result-delivery-processor.ts +0 -300
- package/dist/builtin/subagents/src/runs/background/result-file-claims.ts +0 -166
- package/dist/builtin/subagents/src/runs/background/result-quarantine.ts +0 -77
- package/dist/builtin/subagents/src/runs/background/result-retry-scheduler.ts +0 -48
- package/dist/builtin/subagents/src/runs/background/result-status.ts +0 -87
- package/dist/builtin/subagents/src/runs/background/result-watcher-data.ts +0 -72
- package/dist/builtin/subagents/src/runs/background/result-watcher.ts +0 -320
- package/dist/builtin/subagents/src/runs/background/run-id-resolver.ts +0 -105
- package/dist/builtin/subagents/src/runs/background/run-status.ts +0 -358
- package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +0 -457
- package/dist/builtin/subagents/src/runs/background/subagent-runner-dynamic.ts +0 -376
- package/dist/builtin/subagents/src/runs/background/subagent-runner-finalize.ts +0 -150
- package/dist/builtin/subagents/src/runs/background/subagent-runner-output.ts +0 -109
- package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel-helpers.ts +0 -128
- package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel.ts +0 -309
- package/dist/builtin/subagents/src/runs/background/subagent-runner-sequential.ts +0 -173
- package/dist/builtin/subagents/src/runs/background/subagent-runner-state.ts +0 -578
- package/dist/builtin/subagents/src/runs/background/subagent-runner-step.ts +0 -330
- package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +0 -330
- package/dist/builtin/subagents/src/runs/background/subagent-runner-types.ts +0 -210
- package/dist/builtin/subagents/src/runs/background/subagent-runner-utils.ts +0 -69
- package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +0 -90
- package/dist/builtin/subagents/src/runs/background/top-level-async.ts +0 -12
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt-control.ts +0 -140
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt-finalize.ts +0 -108
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt-types.ts +0 -17
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +0 -558
- package/dist/builtin/subagents/src/runs/shared/attempt-watchdog.ts +0 -126
- package/dist/builtin/subagents/src/runs/shared/final-drain.ts +0 -39
- package/dist/builtin/subagents/src/runs/shared/pi-args.ts +0 -339
- package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +0 -165
- package/dist/builtin/subagents/src/runs/shared/spawn-env.ts +0 -21
- package/dist/builtin/subagents/src/shared/post-exit-stdio-guard.ts +0 -86
- /package/dist/builtin/subagents/src/runs/{shared/nested-path.ts → inprocess/runtime-support/nested-paths.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,40 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.13-alpha.1] - 2026-08-05
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `CreateAgentSessionOptions` and `ExtensionContext` now carry an immutable typed subagent child capability policy for in-process tool registration ([#2188](https://github.com/bastani-inc/atomic/issues/2188)).
|
|
10
|
+
- `CreateAgentSessionOptions` now supports construction-time system-prompt and inherited-context transforms, allowing in-process child sessions to apply typed policy without extension injection ([#2188](https://github.com/bastani-inc/atomic/issues/2188)).
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Typed child policy now includes MCP direct-tool selection and admission-issued Intercom identity/capability, allowing in-process extensions to consume child policy without inheritable environment state ([#2188](https://github.com/bastani-inc/atomic/issues/2188)).
|
|
15
|
+
- Bundled subagent launches now use in-process `AgentSession` children with typed admission, canonical identities, and live async continuation; `async: true` work is owned by the parent process and does not survive parent exit ([#2188](https://github.com/bastani-inc/atomic/issues/2188)).
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Workflow runs awaiting human input now use the blue `?` indicator in the BACKGROUND panel, `/workflow connect` picker, and `/workflow status` listing, including prompts raised by hidden nested workflow children; the indicator returns to the run's current state when the prompt resolves.
|
|
20
|
+
- Fixed main-chat model fallback to classify provider failures consistently with workflows, advance rejected credentials and incompatible or unavailable models to the next candidate, and restore the user-selected model at the next turn without overriding an explicit `/model` choice. A failure that requesting the same model again cannot repair now takes that model out of the chain for the rest of the turn at every reasoning level, so a fallback entry differing only by its `:low`/`:high` suffix is skipped instead of retrying the same dead credential; transient rate-limit and transport failures keep those reasoning variants ([#2170](https://github.com/bastani-inc/atomic/issues/2170)).
|
|
21
|
+
- Fixed a context overflow that compaction cannot resolve to advance the configured `fallbackModels` chain instead of ending the turn, so a larger-context candidate can answer. Compaction still runs first, and a compactable overflow spends no fallback candidate ([#2170](https://github.com/bastani-inc/atomic/issues/2170)).
|
|
22
|
+
- Fixed a reasoning-level change during a model fallback stranding the session on the fallback model. Changing reasoning effort is not a model choice, so it no longer cancels the pending restore; the next turn returns to the user-selected primary and keeps the reasoning level that was chosen. Only an explicit `/model` selection or model cycle cancels the restore ([#2170](https://github.com/bastani-inc/atomic/issues/2170)).
|
|
23
|
+
- Fixed gRPC `ResourceExhausted` provider errors, seen from providers such as NVIDIA NIM, bypassing the same-model auto-retry budget. They are now retried like other transient provider failures, matching upstream pi-ai, and still advance a configured fallback chain when the retries are exhausted ([#2170](https://github.com/bastani-inc/atomic/issues/2170)).
|
|
24
|
+
|
|
25
|
+
## [0.9.12] - 2026-08-04
|
|
26
|
+
|
|
27
|
+
Cumulative release of the `0.9.12-alpha.1` prerelease. The summary below covers the user-visible outcome of that work; the per-change detail remains in the prerelease section below.
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- Compaction honors `<keepContext>` / `</keepContext>` tags. Wrap any part of a prompt you never want compressed, and every line of the span — tag lines included — is protected verbatim regardless of the compression ratio. The guarantee is mechanical rather than advisory: deletion ranges are split around protected lines after the planner responds. Because the tag lines are protected too, a span is re-detected on each subsequent boundary and stays protected for the life of the session. Detection is bounded on three sides, because the transcript it scans is untrusted: a tag must be the whole line after any role header, a span is scoped to one message so an unclosed tag stops at the end of its own message rather than running to the end of the region, and tags inside tool results are inert — user and assistant messages may both protect, so prompts, steering, and an agent's own pinned information all work, but file, page, or command output an agent reads cannot mark itself unreclaimable or persist through compaction ahead of real content. Protected lines count against the keep target rather than raising it, so the compression ratio stays a real bound on output size and the unprotected remainder compresses harder. Results report force-preserved ranges as `keptRanges` ([#2172](https://github.com/bastani-inc/atomic/issues/2172)).
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- The compaction relevance query is no longer truncated to 1,000 characters. Truncation made prompt section order the retention policy: for a long structured prompt only the leading section reached the planner, so a constraint stated later could not influence what was kept, while the objective it qualified survived and was acted on. Long queries are safe — an oversized planner request surfaces as an explicit provider-overflow failure rather than silent truncation ([#2172](https://github.com/bastani-inc/atomic/issues/2172)).
|
|
36
|
+
- Cleared three advisories in the shipped dependency tree. `undici` moves 8.5.0 → 8.9.0, which covers five advisories against 8.0.0–8.8.0 — response desynchronization via the retry interceptor, two cross-user cache-directive disclosures, CRLF injection through a blob body `type`, and cookie-attribute injection — and it is the dispatcher behind `fetch_url` and every agent HTTP request. Transitively under `@modelcontextprotocol/sdk`, `ip-address` is pinned to 10.3.1 for three SSRF and trust-boundary bypasses (octal-decoded leading-zero octets, CIDR suffixes suppressing special-use classification, and misclassified IPv4-mapped/NAT64 addresses), and `hono` to 4.12.34 for a CORS-middleware ReDoS. `npm audit` is clean.
|
|
37
|
+
- Fixed bundled builtin extensions failing to load on Windows when shared modules were evaluated twice, so bundled workflows and tools initialize correctly.
|
|
38
|
+
|
|
5
39
|
## [0.9.12-alpha.1] - 2026-08-04
|
|
6
40
|
|
|
7
41
|
### Added
|
|
@@ -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.13-alpha.1] - 2026-08-05
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- In-process child identities and supervisor capabilities now arrive through typed admission policy and are captured on each `IntercomClient` at connect time instead of being read from environment for every message. Descendants cannot inherit a parent's supervisor grant through process environment; legacy Atomic/Pi bridge metadata remains available for older hosts ([#2188](https://github.com/bastani-inc/atomic/issues/2188)).
|
|
12
|
+
|
|
13
|
+
## [0.9.12] - 2026-08-04
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Fixed bundled Intercom resources failing to load on Windows when shared modules used mixed `.ts` and `.js` import spellings.
|
|
18
|
+
|
|
7
19
|
## [0.9.12-alpha.1] - 2026-08-04
|
|
8
20
|
|
|
9
21
|
### Fixed
|
|
@@ -20,7 +20,7 @@ Sometimes you're running multiple Atomic/pi sessions — one researching, one ex
|
|
|
20
20
|
|
|
21
21
|
Unlike pi-messenger (a shared chat room for multi-agent swarms), intercom is for targeted 1:1 communication where you pick the recipient.
|
|
22
22
|
|
|
23
|
-
Intercom also integrates with delegated subagents:
|
|
23
|
+
Intercom also integrates with delegated subagents: in-process children receive a typed admission-issued identity for `contact_supervisor`, including their canonical run/agent/index metadata and any supervisor capability. The child identity is bound to its `IntercomClient` when it connects, so each message uses the same client-owned source and a descendant cannot inherit a parent's capability through process environment. Atomic-prefixed bridge environment variables and legacy `PI_*` metadata remain compatible for older integrations only. Use `reason: "need_decision"` for blocking clarification, `reason: "interview_request"` for multiple structured supervisor answers, and `reason: "progress_update"` for meaningful plan-changing updates. Normal sessions only see the regular `intercom` tool.
|
|
24
24
|
|
|
25
25
|
## In One Minute
|
|
26
26
|
|
|
@@ -227,20 +227,13 @@ The planner typically uses `send`. If you prefer manual approval for outgoing no
|
|
|
227
227
|
|
|
228
228
|
## Workflow: Subagent-to-Supervisor Escalation
|
|
229
229
|
|
|
230
|
-
This workflow
|
|
230
|
+
This workflow uses Atomic's in-process subagent admission. When the runtime admits a delegated child with supervisor coordination, the child session gets a subagent-only `contact_supervisor` tool in addition to the regular `intercom` tool. Normal sessions never see `contact_supervisor`.
|
|
231
231
|
|
|
232
232
|
### When the Tool Appears
|
|
233
233
|
|
|
234
|
-
`contact_supervisor`
|
|
234
|
+
`contact_supervisor` is registered from the typed admission record. The record binds the supervisor target, canonical child identity, child index, session name, and broker-issued capability to the child session; these values are not inherited from environment variables. If the parent does not grant supervisor coordination, the session falls back to the regular `intercom` tool.
|
|
235
235
|
|
|
236
|
-
|
|
237
|
-
- `PI_SUBAGENT_RUN_ID` — the run identifier
|
|
238
|
-
- `PI_SUBAGENT_CHILD_AGENT` — the agent type
|
|
239
|
-
- `PI_SUBAGENT_CHILD_INDEX` — the child index within the run
|
|
240
|
-
|
|
241
|
-
Atomic's bundled subagent bridge additionally supplies internal `ATOMIC_SUBAGENT_SUPERVISOR_CAPABILITY` and `ATOMIC_SUBAGENT_SUPERVISOR_SESSION_ID` values issued by the broker. They are not user-configurable authentication flags: the broker accepts the capability only for the child scope and supervisor session that requested it, and the parent restores the same secret if the broker reconnects. Legacy `PI_*` aliases remain readable where applicable.
|
|
242
|
-
|
|
243
|
-
If any are missing, the session falls back to the regular `intercom` tool.
|
|
236
|
+
The child identity remains stable across foreground continuation, `async: true`, interruption, and cold resume. Intercom detach uses the same in-process continuation as async work, so the jobs widget and terminal envelope retain one canonical path.
|
|
244
237
|
|
|
245
238
|
### Three Reasons
|
|
246
239
|
|
|
@@ -254,7 +247,7 @@ Do not use `contact_supervisor` for routine completion handoffs. Return the fina
|
|
|
254
247
|
|
|
255
248
|
Cross-group delivery uses a dedicated broker protocol. Ordinary raw `send` frames always remain group-isolated and are rejected if they include a forged `channel: "supervisor"` marker. A child can cross groups only after its broker-issued capability has bound its registered socket to the exact supervisor. The broker adds the `supervisor` channel marker to validated inbound traffic so parent relays can distinguish it. Replies cross back only when `replyTo` matches a recorded supervisor message in the exact reverse direction; fabricated thread IDs do not bypass isolation.
|
|
256
249
|
|
|
257
|
-
During a foreground subagent run, Atomic probes for an exact live foreground owner before delivery. The matching child reserves the request, accepts a generation-scoped detach commit, and acknowledges it before asks, sends, decisions, interviews, and progress updates enter the parent's model-visible steering queue. A busy workflow stage first reserves the message in its AgentSession generation boundary, then waits inside that admission for the same detach handshake before model-visible queue insertion. This prevents terminal stage close from overtaking the handshake while still preventing the active subagent tool from blocking the child request that would release it; unclaimed traffic and a still-current receiver whose owner disappears before commit fall back to ordinary queue insertion. One accepted commit releases foreground supervision for every active member of a parallel group while retaining each
|
|
250
|
+
During a foreground subagent run, Atomic probes for an exact live foreground owner before delivery. The matching child reserves the request, accepts a generation-scoped detach commit, and acknowledges it before asks, sends, decisions, interviews, and progress updates enter the parent's model-visible steering queue. A busy workflow stage first reserves the message in its AgentSession generation boundary, then waits inside that admission for the same detach handshake before model-visible queue insertion. This prevents terminal stage close from overtaking the handshake while still preventing the active subagent tool from blocking the child request that would release it; unclaimed traffic and a still-current receiver whose owner disappears before commit fall back to ordinary queue insertion. One accepted commit releases foreground supervision for every active member of a parallel group while retaining each in-process session and eventual result. Blocking calls remain alive until the parent sends the exact threaded reply; fire-and-forget calls create no reply waiter. Background and unmatched traffic for ordinary sessions keeps queued-until-idle behavior, and generation cancellation/replacement invalidates stale handshakes.
|
|
258
251
|
|
|
259
252
|
### Example: Blocked Subagent Asks for Guidance
|
|
260
253
|
|
|
@@ -38,6 +38,8 @@ export class IntercomClient extends EventEmitter {
|
|
|
38
38
|
private socket: net.Socket | null = null;
|
|
39
39
|
private _sessionId: string | null = null;
|
|
40
40
|
private _supervisorSessionId: string | null = null;
|
|
41
|
+
/** Source identity is captured once at connect, never read from env per message. */
|
|
42
|
+
private _messageSource: Message["source"] | undefined;
|
|
41
43
|
private pendingSends = new PendingSendRegistry();
|
|
42
44
|
private pendingLists = new Map<string, { resolve: (sessions: SessionInfo[]) => void; reject: (e: Error) => void }>();
|
|
43
45
|
private pendingSupervisorAuthorizations = new Map<string, {
|
|
@@ -85,10 +87,16 @@ export class IntercomClient extends EventEmitter {
|
|
|
85
87
|
return socket;
|
|
86
88
|
}
|
|
87
89
|
|
|
88
|
-
connect(
|
|
90
|
+
connect(
|
|
91
|
+
session: Omit<SessionInfo, "id">,
|
|
92
|
+
supervisor?: SupervisorRegistration,
|
|
93
|
+
supervisorOwnerToken?: string,
|
|
94
|
+
messageSource?: Message["source"],
|
|
95
|
+
): Promise<void> {
|
|
89
96
|
if (this.socket) {
|
|
90
97
|
return Promise.reject(new Error("Already connected"));
|
|
91
98
|
}
|
|
99
|
+
this._messageSource = messageSource ?? readSubagentMessageSource();
|
|
92
100
|
|
|
93
101
|
return new Promise((resolve, reject) => {
|
|
94
102
|
const socket = net.connect(BROKER_SOCKET);
|
|
@@ -141,6 +149,7 @@ export class IntercomClient extends EventEmitter {
|
|
|
141
149
|
}
|
|
142
150
|
this._sessionId = null;
|
|
143
151
|
this._supervisorSessionId = null;
|
|
152
|
+
this._messageSource = undefined;
|
|
144
153
|
this.disconnectError = null;
|
|
145
154
|
if (connectionEstablished && !wasDisconnecting) {
|
|
146
155
|
this.emit("disconnected", disconnectError);
|
|
@@ -463,7 +472,7 @@ export class IntercomClient extends EventEmitter {
|
|
|
463
472
|
replyTo: options.replyTo,
|
|
464
473
|
expectsReply: options.expectsReply,
|
|
465
474
|
replyError: options.replyError,
|
|
466
|
-
source:
|
|
475
|
+
source: this._messageSource,
|
|
467
476
|
content: { text: options.text, attachments: options.attachments },
|
|
468
477
|
};
|
|
469
478
|
try {
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
} from "./intercom-utils.js";
|
|
20
20
|
|
|
21
21
|
interface ContactSupervisorDeps {
|
|
22
|
-
childOrchestratorMetadata: ChildOrchestratorMetadata | null;
|
|
22
|
+
childOrchestratorMetadata: ChildOrchestratorMetadata | null | (() => ChildOrchestratorMetadata | null);
|
|
23
23
|
ensureConnected(reason: "tool"): Promise<IntercomClient>;
|
|
24
24
|
syncPresenceIdentity(sessionId: string): void;
|
|
25
25
|
resolveSessionTarget(activeClient: IntercomClient, nameOrId: string): Promise<string | null>;
|
|
@@ -35,7 +35,10 @@ interface ContactSupervisorDeps {
|
|
|
35
35
|
|
|
36
36
|
export function registerContactSupervisorTool(pi: ExtensionAPI, deps: ContactSupervisorDeps): void {
|
|
37
37
|
const { childOrchestratorMetadata, ensureConnected, syncPresenceIdentity, resolveSessionTarget, beginReplyWait, hasReplyWaiter } = deps;
|
|
38
|
-
|
|
38
|
+
const getMetadata = typeof childOrchestratorMetadata === "function"
|
|
39
|
+
? childOrchestratorMetadata
|
|
40
|
+
: () => childOrchestratorMetadata;
|
|
41
|
+
if (childOrchestratorMetadata !== null) {
|
|
39
42
|
pi.registerTool({
|
|
40
43
|
name: "contact_supervisor",
|
|
41
44
|
label: "Contact Supervisor",
|
|
@@ -116,7 +119,14 @@ export function registerContactSupervisorTool(pi: ExtensionAPI, deps: ContactSup
|
|
|
116
119
|
};
|
|
117
120
|
}
|
|
118
121
|
|
|
119
|
-
const metadata =
|
|
122
|
+
const metadata = getMetadata();
|
|
123
|
+
if (!metadata) {
|
|
124
|
+
return {
|
|
125
|
+
content: [{ type: "text", text: "Supervisor contact is unavailable for this session" }],
|
|
126
|
+
isError: true,
|
|
127
|
+
details: { error: true },
|
|
128
|
+
};
|
|
129
|
+
}
|
|
120
130
|
let sendTo: string;
|
|
121
131
|
if (connectedClient.supervisorSessionId || metadata.supervisor) {
|
|
122
132
|
sendTo = connectedClient.supervisorSessionId ?? metadata.supervisor!.supervisorSessionId;
|
|
@@ -15,6 +15,7 @@ import { registerSubagentRelay } from "./subagent-relay.js";
|
|
|
15
15
|
import { ForegroundDetachHandoff, handleForegroundInboundDelivery } from "./foreground-detach-handoff.js";
|
|
16
16
|
import { routeIncomingReply } from "./reply-routing.js";
|
|
17
17
|
import { INBOUND_FLUSH_DELAY_MS, INBOUND_IDLE_RETRY_MS, buildPresenceIdentity, formatAttachments, readChildOrchestratorMetadata, toError } from "./intercom-utils.js";
|
|
18
|
+
import { readSubagentMessageSource } from "./source-ownership.js";
|
|
18
19
|
import { buildIncomingCustomMessage, createIncomingMessageSender } from "./incoming-message-delivery.js";
|
|
19
20
|
import { InboundIdleQueue } from "./inbound-idle-queue.js";
|
|
20
21
|
import { registerTerminalOrderingBarrier } from "./terminal-ordering-barrier.js";
|
|
@@ -46,8 +47,13 @@ export default function piIntercomExtension(pi: ExtensionAPI, testOverrides: Int
|
|
|
46
47
|
};
|
|
47
48
|
let client: IntercomClient | null = null;
|
|
48
49
|
const config: IntercomConfig = loadConfig();
|
|
49
|
-
const
|
|
50
|
+
const legacyChildOrchestratorMetadata = readChildOrchestratorMetadata();
|
|
50
51
|
let runtimeContext: ExtensionContext | null = null;
|
|
52
|
+
function currentChildOrchestratorMetadata() {
|
|
53
|
+
return runtimeContext?.subagentPolicy !== undefined
|
|
54
|
+
? readChildOrchestratorMetadata(runtimeContext.subagentPolicy)
|
|
55
|
+
: legacyChildOrchestratorMetadata;
|
|
56
|
+
}
|
|
51
57
|
let currentSessionId: string | null = null;
|
|
52
58
|
let currentModel = "unknown";
|
|
53
59
|
let sessionStartedAt: number | null = null;
|
|
@@ -389,8 +395,12 @@ export default function piIntercomExtension(pi: ExtensionAPI, testOverrides: Int
|
|
|
389
395
|
attachClientHandlers(nextClient);
|
|
390
396
|
try {
|
|
391
397
|
await spawnBrokerIfNeeded(config.brokerCommand, config.brokerArgs);
|
|
398
|
+
const childMetadata = currentChildOrchestratorMetadata();
|
|
392
399
|
await nextClient.connect(
|
|
393
|
-
buildRegistration(),
|
|
400
|
+
buildRegistration(),
|
|
401
|
+
childMetadata?.supervisor,
|
|
402
|
+
supervisorAuthorizations.ownerToken,
|
|
403
|
+
readSubagentMessageSource(runtimeContext?.subagentPolicy),
|
|
394
404
|
);
|
|
395
405
|
await supervisorAuthorizations.restore(nextClient);
|
|
396
406
|
if (!getLiveContext(contextAtStart, generationAtStart)) {
|
|
@@ -470,7 +480,7 @@ export default function piIntercomExtension(pi: ExtensionAPI, testOverrides: Int
|
|
|
470
480
|
});
|
|
471
481
|
|
|
472
482
|
registerContactSupervisorTool(pi, {
|
|
473
|
-
childOrchestratorMetadata,
|
|
483
|
+
childOrchestratorMetadata: currentChildOrchestratorMetadata,
|
|
474
484
|
ensureConnected,
|
|
475
485
|
syncPresenceIdentity,
|
|
476
486
|
resolveSessionTarget: resolveSessionTargetId,
|
|
@@ -92,10 +92,10 @@ function renderHeavyToolResult(loadedHeavy: CapturedHeavy | null, name: string,
|
|
|
92
92
|
return renderIntercomToolResult(name, args);
|
|
93
93
|
}
|
|
94
94
|
export default function intercom(pi: ExtensionAPI, options: LightweightIntercomOptions = {}) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
const inheritedDelegatedSessionName = readSubagentEnv("INTERCOM_SESSION_NAME");
|
|
96
|
+
let heavyAttempt: HeavyAttempt | null = null;
|
|
97
|
+
let loadedHeavy: IntercomHeavyHandle | null = null;
|
|
98
|
+
let sessionSnapshot: SessionSnapshot | null = null;
|
|
99
99
|
let lifecycleGeneration = 0;
|
|
100
100
|
let nextLeaseId = 1;
|
|
101
101
|
let activeLease = createLifecycleLease<ShutdownSnapshot>(nextLeaseId++);
|
|
@@ -229,21 +229,45 @@ export default function intercom(pi: ExtensionAPI, options: LightweightIntercomO
|
|
|
229
229
|
);
|
|
230
230
|
return promise;
|
|
231
231
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
232
|
+
let typedContactSupervisorRegistered = hasSubagentIntercomEnv();
|
|
233
|
+
const registerTypedContactSupervisor = (): void => {
|
|
234
|
+
if (typedContactSupervisorRegistered) return;
|
|
235
|
+
typedContactSupervisorRegistered = true;
|
|
236
|
+
pi.registerTool({
|
|
237
|
+
name: "contact_supervisor",
|
|
238
|
+
label: "Contact Supervisor",
|
|
239
|
+
description: "Subagent-only tool for contacting the supervisor agent that delegated this task.",
|
|
240
|
+
promptSnippet: "Subagent-only: contact the supervisor for decisions, interviews, or meaningful updates.",
|
|
241
|
+
parameters: Type.Object({
|
|
242
|
+
reason: Type.String({ enum: ["need_decision", "progress_update", "interview_request"] }),
|
|
243
|
+
message: Type.Optional(Type.String()),
|
|
244
|
+
interview: Type.Optional(Type.Unknown()),
|
|
245
|
+
}),
|
|
246
|
+
execute: (...args) => executeHeavyTool(loadHeavy, "contact_supervisor", args),
|
|
247
|
+
renderResult: (...args) => renderHeavyToolResult(loadedHeavy?.heavy ?? null, "contact_supervisor", args),
|
|
248
|
+
});
|
|
249
|
+
};
|
|
250
|
+
pi.on("session_start", async (event, ctx) => {
|
|
251
|
+
const typedIdentity = ctx.subagentPolicy?.intercom;
|
|
252
|
+
if (typedIdentity) {
|
|
253
|
+
if (typedIdentity.sessionName && typeof pi.setSessionName === "function") pi.setSessionName(typedIdentity.sessionName);
|
|
254
|
+
registerTypedContactSupervisor();
|
|
255
|
+
} else if (inheritedDelegatedSessionName && typeof pi.setSessionName === "function") {
|
|
256
|
+
pi.setSessionName(inheritedDelegatedSessionName);
|
|
257
|
+
}
|
|
258
|
+
if (activeLease.retired) activeLease = createLifecycleLease<ShutdownSnapshot>(nextLeaseId++, activeLease.cleanupBarrier);
|
|
259
|
+
const lease = activeLease;
|
|
260
|
+
await waitForPriorCleanup(lease);
|
|
261
|
+
if (sessionSnapshot) {
|
|
262
|
+
activeLifecycle.turnStart = null;
|
|
263
|
+
activeLifecycle.agentStart = null;
|
|
264
|
+
activeLifecycle.activeTools.clear();
|
|
265
|
+
activeLifecycle.modelSelect = null;
|
|
266
|
+
}
|
|
267
|
+
const generation = ++lifecycleGeneration;
|
|
268
|
+
sessionSnapshot = { event, ctx, generation, lease };
|
|
269
|
+
if (loadedHeavy) await ensureSessionStartReplayed(loadedHeavy.heavy, lease);
|
|
270
|
+
});
|
|
247
271
|
pi.on("session_shutdown", async (event, ctx) => {
|
|
248
272
|
const lease = activeLease;
|
|
249
273
|
const generation = ++lifecycleGeneration;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { APP_NAME, getEnvValue } from "@bastani/atomic";
|
|
1
|
+
import { type ExtensionAPI, type SubagentChildPolicy } from "@bastani/atomic";
|
|
3
2
|
import type { Attachment, Message, SessionInfo, SupervisorRegistration } from "./types.js";
|
|
4
3
|
import { DEFAULT_GROUP, normalizeGroup } from "./group.js";
|
|
5
4
|
|
|
@@ -12,14 +11,6 @@ export const SUBAGENT_SUPERVISOR_AUTHORIZATION_EVENT = "subagent:supervisor-auth
|
|
|
12
11
|
export const INBOUND_FLUSH_DELAY_MS = 200;
|
|
13
12
|
export const INBOUND_IDLE_RETRY_MS = 500;
|
|
14
13
|
export const DEFAULT_UNNAMED_SESSION_ALIAS_PREFIX = "subagent-chat";
|
|
15
|
-
const ENV_PREFIX = APP_NAME.toUpperCase();
|
|
16
|
-
const SUBAGENT_ORCHESTRATOR_TARGET_ENV = `${ENV_PREFIX}_SUBAGENT_ORCHESTRATOR_TARGET`;
|
|
17
|
-
const SUBAGENT_RUN_ID_ENV = `${ENV_PREFIX}_SUBAGENT_RUN_ID`;
|
|
18
|
-
const SUBAGENT_CHILD_AGENT_ENV = `${ENV_PREFIX}_SUBAGENT_CHILD_AGENT`;
|
|
19
|
-
const SUBAGENT_CHILD_INDEX_ENV = `${ENV_PREFIX}_SUBAGENT_CHILD_INDEX`;
|
|
20
|
-
const SUBAGENT_INTERCOM_SESSION_NAME_ENV = `${ENV_PREFIX}_SUBAGENT_INTERCOM_SESSION_NAME`;
|
|
21
|
-
const SUBAGENT_SUPERVISOR_CAPABILITY_ENV = `${ENV_PREFIX}_SUBAGENT_SUPERVISOR_CAPABILITY`;
|
|
22
|
-
const SUBAGENT_SUPERVISOR_SESSION_ID_ENV = `${ENV_PREFIX}_SUBAGENT_SUPERVISOR_SESSION_ID`;
|
|
23
14
|
|
|
24
15
|
export interface ChildOrchestratorMetadata {
|
|
25
16
|
orchestratorTarget: string;
|
|
@@ -76,28 +67,23 @@ export function formatAttachments(attachments: Attachment[]): string {
|
|
|
76
67
|
}
|
|
77
68
|
return text;
|
|
78
69
|
}
|
|
79
|
-
export function
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
const agent = getEnvValue(SUBAGENT_CHILD_AGENT_ENV)?.trim();
|
|
83
|
-
const index = getEnvValue(SUBAGENT_CHILD_INDEX_ENV)?.trim();
|
|
84
|
-
if (!orchestratorTarget || !runId || !agent || !index) {
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
const sessionName = getEnvValue(SUBAGENT_INTERCOM_SESSION_NAME_ENV)?.trim();
|
|
88
|
-
const capability = getEnvValue(SUBAGENT_SUPERVISOR_CAPABILITY_ENV)?.trim();
|
|
89
|
-
const supervisorSessionId = getEnvValue(SUBAGENT_SUPERVISOR_SESSION_ID_ENV)?.trim();
|
|
70
|
+
export function childOrchestratorMetadataFromPolicy(policy?: SubagentChildPolicy): ChildOrchestratorMetadata | null {
|
|
71
|
+
const identity = policy?.intercom;
|
|
72
|
+
if (!identity) return null;
|
|
90
73
|
return {
|
|
91
|
-
orchestratorTarget,
|
|
92
|
-
runId,
|
|
93
|
-
agent,
|
|
94
|
-
index,
|
|
95
|
-
...(sessionName ? { sessionName } : {}),
|
|
96
|
-
...(
|
|
97
|
-
? { supervisor: { capability, supervisorSessionId } }
|
|
98
|
-
: {}),
|
|
74
|
+
orchestratorTarget: identity.orchestratorTarget,
|
|
75
|
+
runId: identity.runId,
|
|
76
|
+
agent: identity.agent,
|
|
77
|
+
index: String(identity.index),
|
|
78
|
+
...(identity.sessionName ? { sessionName: identity.sessionName } : {}),
|
|
79
|
+
...(identity.supervisor ? { supervisor: identity.supervisor } : {}),
|
|
99
80
|
};
|
|
100
81
|
}
|
|
82
|
+
|
|
83
|
+
/** Resolve metadata only from the admission-issued typed child identity. */
|
|
84
|
+
export function readChildOrchestratorMetadata(policy?: SubagentChildPolicy): ChildOrchestratorMetadata | null {
|
|
85
|
+
return childOrchestratorMetadataFromPolicy(policy);
|
|
86
|
+
}
|
|
101
87
|
export function formatChildOrchestratorMessage(kind: "ask" | "update" | "interview", metadata: ChildOrchestratorMetadata, message: string): string {
|
|
102
88
|
const heading = kind === "ask"
|
|
103
89
|
? "Subagent needs a supervisor decision."
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/intercom",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.13-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": [
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type SubagentChildPolicy } from "@bastani/atomic";
|
|
2
2
|
import type { Message } from "./types.js";
|
|
3
3
|
|
|
4
|
-
const ENV_PREFIX = APP_NAME.toUpperCase();
|
|
5
|
-
const SUBAGENT_RUN_ID_ENV = `${ENV_PREFIX}_SUBAGENT_RUN_ID`;
|
|
6
|
-
const SUBAGENT_CHILD_AGENT_ENV = `${ENV_PREFIX}_SUBAGENT_CHILD_AGENT`;
|
|
7
|
-
const SUBAGENT_CHILD_INDEX_ENV = `${ENV_PREFIX}_SUBAGENT_CHILD_INDEX`;
|
|
8
|
-
|
|
9
4
|
export function buildSubagentMessageSource(
|
|
10
5
|
runIdValue: string | undefined,
|
|
11
6
|
agentValue: string | undefined,
|
|
@@ -25,10 +20,12 @@ export function buildSubagentMessageSource(
|
|
|
25
20
|
};
|
|
26
21
|
}
|
|
27
22
|
|
|
28
|
-
export function readSubagentMessageSource(): Message["source"] | undefined {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
23
|
+
export function readSubagentMessageSource(policy?: SubagentChildPolicy): Message["source"] | undefined {
|
|
24
|
+
const identity = policy?.intercom;
|
|
25
|
+
if (!identity) return undefined;
|
|
26
|
+
return {
|
|
27
|
+
subagentRunId: identity.runId,
|
|
28
|
+
subagentAgent: identity.agent,
|
|
29
|
+
subagentIndex: identity.index,
|
|
30
|
+
};
|
|
34
31
|
}
|
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.9.13-alpha.1] - 2026-08-05
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- In-process subagents now receive MCP direct-tool selection through typed admission policy. Omitted selection preserves MCP configuration defaults, a list selects exact server/tool entries, and an empty list disables direct tools; the process-era environment bridge has been removed ([#2188](https://github.com/bastani-inc/atomic/issues/2188)).
|
|
15
|
+
|
|
16
|
+
## [0.9.12] - 2026-08-04
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Fixed bundled MCP resources failing to load on Windows when shared modules used mixed `.ts` and `.js` import spellings.
|
|
21
|
+
|
|
10
22
|
## [0.9.12-alpha.1] - 2026-08-04
|
|
11
23
|
|
|
12
24
|
### Fixed
|
|
@@ -240,7 +240,9 @@ To exclude specific tools while still using `directTools: true`, add `excludeToo
|
|
|
240
240
|
|
|
241
241
|
Each direct tool costs ~150-300 tokens in the system prompt (name + description + schema). Good for targeted sets of 5-20 tools. For servers with 75+ tools, stick with the proxy or pick specific tools with a `string[]`.
|
|
242
242
|
|
|
243
|
-
Direct tools register from the metadata cache in the Pi agent dir (`~/.pi/agent/mcp-cache.json` by default, or `$PI_CODING_AGENT_DIR/mcp-cache.json` when set), so no server connections are needed at startup when the cache is warm. On the first session after adding `directTools` to a new server, or when a child/subagent selects tools
|
|
243
|
+
Direct tools register from the metadata cache in the Pi agent dir (`~/.pi/agent/mcp-cache.json` by default, or `$PI_CODING_AGENT_DIR/mcp-cache.json` when set), so no server connections are needed at startup when the cache is warm. On the first session after adding `directTools` to a new server, or when a child/subagent selects tools, the cache may not exist yet — tools fall back to proxy-only while the selected/configured direct-tool servers populate in the background, then the extension refreshes tool registration so the warmed direct tools become available in the current session. To force it immediately: `/mcp reconnect <server>`.
|
|
244
|
+
|
|
245
|
+
In-process subagents receive direct-tool selection through the typed admission policy rather than an environment bridge. An omitted `mcpDirectTools` field preserves the session's MCP configuration defaults, a list selects exactly those server/tool names, and an empty list explicitly disables direct tools. The legacy environment override is removed; parent sessions should use MCP configuration instead.
|
|
244
246
|
|
|
245
247
|
When you change direct-tool toggles in `/mcp` or write new config through `/mcp setup`, the extension triggers Pi's normal reload flow automatically. That refreshes extensions, prompts, skills, and MCP tool registration in one shot, so newly configured direct tools can appear without a manual restart.
|
|
246
248
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentToolUpdateCallback, ExtensionAPI, ExtensionContext, ToolInfo } from "@bastani/atomic";
|
|
1
|
+
import type { AgentToolUpdateCallback, ExtensionAPI, ExtensionContext, SubagentChildPolicy, ToolInfo } from "@bastani/atomic";
|
|
2
2
|
import type { McpExtensionState } from "./state.js";
|
|
3
3
|
import type { McpConfig } from "./types.ts";
|
|
4
4
|
import type { MetadataCache } from "./metadata-cache.js";
|
|
@@ -55,22 +55,15 @@ export default function mcpAdapter(pi: ExtensionAPI) {
|
|
|
55
55
|
async function registerDirectToolsFromConfig(
|
|
56
56
|
config: McpConfig,
|
|
57
57
|
cache: MetadataCache | null,
|
|
58
|
+
subagentPolicy?: SubagentChildPolicy,
|
|
58
59
|
): Promise<{ directToolCount: number; missingConfiguredDirectToolServers: string[] }> {
|
|
59
60
|
const [{ resolveDirectTools, createDirectToolExecutor, getMissingConfiguredDirectToolServers }, { truncateAtWord }] = await Promise.all([
|
|
60
61
|
import("./direct-tools.ts"),
|
|
61
62
|
import("./utils.js"),
|
|
62
63
|
]);
|
|
63
64
|
const prefix = config.settings?.toolPrefix ?? "server";
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
const directSpecs = envRaw === "__none__"
|
|
67
|
-
? []
|
|
68
|
-
: resolveDirectTools(
|
|
69
|
-
config,
|
|
70
|
-
cache,
|
|
71
|
-
prefix,
|
|
72
|
-
envDirectTools,
|
|
73
|
-
);
|
|
65
|
+
const directTools = subagentPolicy?.mcpDirectTools;
|
|
66
|
+
const directSpecs = resolveDirectTools(config, cache, prefix, directTools === undefined ? undefined : [...directTools]);
|
|
74
67
|
for (const spec of directSpecs) {
|
|
75
68
|
if (registeredDirectToolNames.has(spec.prefixedName)) continue;
|
|
76
69
|
registeredDirectToolNames.add(spec.prefixedName);
|
|
@@ -92,13 +85,13 @@ export default function mcpAdapter(pi: ExtensionAPI) {
|
|
|
92
85
|
refreshTools?.();
|
|
93
86
|
return {
|
|
94
87
|
directToolCount: directSpecs.length,
|
|
95
|
-
missingConfiguredDirectToolServers: getMissingConfiguredDirectToolServers(config, cache,
|
|
88
|
+
missingConfiguredDirectToolServers: getMissingConfiguredDirectToolServers(config, cache, directTools),
|
|
96
89
|
};
|
|
97
90
|
}
|
|
98
91
|
|
|
99
|
-
async function registerDirectTools(nextState: McpExtensionState): Promise<{ directToolCount: number; missingConfiguredDirectToolServers: string[] }> {
|
|
92
|
+
async function registerDirectTools(nextState: McpExtensionState, subagentPolicy?: SubagentChildPolicy): Promise<{ directToolCount: number; missingConfiguredDirectToolServers: string[] }> {
|
|
100
93
|
const { loadMetadataCache } = await import("./metadata-cache.js");
|
|
101
|
-
return registerDirectToolsFromConfig(nextState.config, loadMetadataCache());
|
|
94
|
+
return registerDirectToolsFromConfig(nextState.config, loadMetadataCache(), subagentPolicy);
|
|
102
95
|
}
|
|
103
96
|
|
|
104
97
|
async function shutdownOAuthFlow(reason: string): Promise<void> {
|
|
@@ -196,7 +189,7 @@ export default function mcpAdapter(pi: ExtensionAPI) {
|
|
|
196
189
|
throw new Error(`${STALE_INITIALIZATION_PREFIX} after startup`);
|
|
197
190
|
}
|
|
198
191
|
|
|
199
|
-
const directToolState = await registerDirectTools(initializedState);
|
|
192
|
+
const directToolState = await registerDirectTools(initializedState, session.ctx.subagentPolicy);
|
|
200
193
|
if (!isCurrentSession(session) || initPromise !== expectedPromise.current) {
|
|
201
194
|
throw new Error(`${STALE_INITIALIZATION_PREFIX} after tool registration`);
|
|
202
195
|
}
|
|
@@ -211,10 +204,11 @@ export default function mcpAdapter(pi: ExtensionAPI) {
|
|
|
211
204
|
updateStatusBar(initializedState);
|
|
212
205
|
let cancelWarmup: (() => void) | null = null;
|
|
213
206
|
const warmup = scheduleMcpStartupWarmup(initializedState, {
|
|
207
|
+
subagentPolicy: session.ctx.subagentPolicy,
|
|
214
208
|
shouldContinue: () => isCurrentSession(session) && state === initializedState,
|
|
215
209
|
onDirectToolsChanged: async () => {
|
|
216
210
|
if (!isCurrentSession(session) || state !== initializedState) return;
|
|
217
|
-
await registerDirectTools(initializedState);
|
|
211
|
+
await registerDirectTools(initializedState, session.ctx.subagentPolicy);
|
|
218
212
|
},
|
|
219
213
|
onSettled: () => {
|
|
220
214
|
if (isCurrentSession(session) && state === initializedState && startupWarmupCancel === cancelWarmup) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/mcp",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.13-alpha.1",
|
|
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": [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SubagentChildPolicy } from "@bastani/atomic";
|
|
1
2
|
import type { McpExtensionState } from "./state.js";
|
|
2
3
|
import { getMissingConfiguredDirectToolServers } from "./direct-tools.ts";
|
|
3
4
|
import { loadMetadataCache } from "./metadata-cache.js";
|
|
@@ -7,9 +8,11 @@ import { logger } from "./logger.ts";
|
|
|
7
8
|
import { updateMetadataCache, updateStatusBar } from "./init.js";
|
|
8
9
|
|
|
9
10
|
export interface McpStartupWarmupOptions {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
/** Typed child selection issued during in-process admission. */
|
|
12
|
+
subagentPolicy?: SubagentChildPolicy;
|
|
13
|
+
shouldContinue?: () => boolean;
|
|
14
|
+
onDirectToolsChanged?: () => void | Promise<void>;
|
|
15
|
+
onSettled?: () => void;
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
export interface McpStartupWarmupHandle {
|
|
@@ -17,6 +20,17 @@ export interface McpStartupWarmupHandle {
|
|
|
17
20
|
cancel(): void;
|
|
18
21
|
}
|
|
19
22
|
|
|
23
|
+
export interface McpDirectToolsSelection {
|
|
24
|
+
readonly disabled: boolean;
|
|
25
|
+
readonly tools?: readonly string[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Resolve direct-tool selection exclusively from typed admission policy. */
|
|
29
|
+
export function resolveMcpDirectToolsSelection(subagentPolicy?: SubagentChildPolicy): McpDirectToolsSelection {
|
|
30
|
+
const tools = subagentPolicy?.mcpDirectTools;
|
|
31
|
+
return { disabled: tools !== undefined && tools.length === 0, ...(tools === undefined ? {} : { tools: [...tools] }) };
|
|
32
|
+
}
|
|
33
|
+
|
|
20
34
|
function deferToMacrotask(): Promise<void> {
|
|
21
35
|
return new Promise((resolve) => setImmediate(resolve));
|
|
22
36
|
}
|
|
@@ -31,12 +45,10 @@ export function scheduleMcpStartupWarmup(
|
|
|
31
45
|
const promise = (async () => {
|
|
32
46
|
await deferToMacrotask();
|
|
33
47
|
if (!shouldContinue()) return;
|
|
48
|
+
const selection = resolveMcpDirectToolsSelection(options.subagentPolicy);
|
|
49
|
+
if (selection.disabled) return;
|
|
34
50
|
|
|
35
|
-
const
|
|
36
|
-
if (envDirect === "__none__") return;
|
|
37
|
-
|
|
38
|
-
const envDirectTools = envDirect?.split(",").map((item) => item.trim()).filter(Boolean);
|
|
39
|
-
const missingCacheServers = getMissingConfiguredDirectToolServers(state.config, loadMetadataCache(), envDirectTools)
|
|
51
|
+
const missingCacheServers = getMissingConfiguredDirectToolServers(state.config, loadMetadataCache(), selection.tools)
|
|
40
52
|
.filter((name) => state.manager.getConnection(name)?.status !== "connected");
|
|
41
53
|
if (missingCacheServers.length === 0) return;
|
|
42
54
|
|