@bastani/atomic 0.9.16-alpha.9 → 0.9.16
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 +120 -0
- package/README.md +4 -4
- package/dist/builtin/intercom/CHANGELOG.md +42 -0
- package/dist/builtin/intercom/README.md +18 -17
- package/dist/builtin/intercom/broker/broker.ts +43 -18
- package/dist/builtin/intercom/broker/client.ts +138 -7
- package/dist/builtin/intercom/broker/group-isolation.ts +3 -3
- package/dist/builtin/intercom/broker/group-membership.ts +55 -0
- package/dist/builtin/intercom/broker/presence-handler.ts +62 -50
- package/dist/builtin/intercom/broker/send-handler.ts +2 -3
- package/dist/builtin/intercom/group.ts +40 -0
- package/dist/builtin/intercom/index.bundle.mjs +490 -183
- package/dist/builtin/intercom/package.json +2 -2
- package/dist/builtin/intercom/skills/intercom/SKILL.md +16 -10
- package/dist/builtin/intercom/types.ts +24 -2
- package/dist/builtin/mcp/index.bundle.mjs +202 -52
- package/dist/builtin/mcp/package.json +2 -2
- package/dist/builtin/subagents/CHANGELOG.md +51 -0
- package/dist/builtin/subagents/README.md +3 -3
- package/dist/builtin/subagents/agents/code-simplifier.md +1 -1
- package/dist/builtin/subagents/agents/codebase-analyzer.md +1 -1
- package/dist/builtin/subagents/agents/codebase-locator.md +1 -1
- package/dist/builtin/subagents/agents/codebase-online-researcher.md +1 -1
- package/dist/builtin/subagents/agents/codebase-pattern-finder.md +1 -1
- package/dist/builtin/subagents/agents/codebase-research-analyzer.md +1 -1
- package/dist/builtin/subagents/agents/codebase-research-locator.md +1 -1
- package/dist/builtin/subagents/agents/debugger.md +1 -1
- package/dist/builtin/subagents/agents/worker.md +1 -1
- package/dist/builtin/subagents/package.json +3 -3
- package/dist/builtin/subagents/src/extension/index.bundle.mjs +422 -140
- package/dist/builtin/web-access/index.bundle.mjs +202 -52
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +70 -0
- package/dist/builtin/workflows/README.md +2 -2
- package/dist/builtin/workflows/builtin/{chunk-h5e65g7g.js → chunk-3y1hmzw6.js} +36 -6
- package/dist/builtin/workflows/builtin/{chunk-nqr34qp3.js → chunk-6rbajjf5.js} +7 -1
- package/dist/builtin/workflows/builtin/{chunk-qe6bfpbd.js → chunk-bz1c9732.js} +15 -3
- package/dist/builtin/workflows/builtin/{chunk-8v8wmb7z.js → chunk-dattsgxg.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-17zk6ffd.js → chunk-gdx0avpx.js} +355 -67
- package/dist/builtin/workflows/builtin/{chunk-rbnj9621.js → chunk-w9c7rkrk.js} +1 -1
- package/dist/builtin/workflows/builtin/goal.js +3 -3
- package/dist/builtin/workflows/builtin/index.js +5 -5
- package/dist/builtin/workflows/builtin/open-claude-design.js +2 -2
- package/dist/builtin/workflows/builtin/ralph.js +3 -3
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +531 -143
- package/dist/builtin/workflows/src/index.js +212 -72
- package/dist/cli/args.js +6 -6
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +2 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/session-picker.d.ts +2 -1
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js +3 -2
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +2 -1
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +1 -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-post-tool-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-post-tool-compaction.js +3 -6
- 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 +3 -1
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +6 -3
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session-state.d.ts.map +1 -1
- package/dist/core/agent-session-state.js +7 -5
- 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 +37 -23
- 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 +9 -2
- package/dist/core/agent-session-tool-registry.js.map +1 -1
- package/dist/core/agent-session.d.ts +2 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +2 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/builtin-packages.d.ts +4 -0
- package/dist/core/builtin-packages.d.ts.map +1 -1
- package/dist/core/builtin-packages.js +22 -1
- package/dist/core/builtin-packages.js.map +1 -1
- package/dist/core/callback-activity.d.ts.map +1 -1
- package/dist/core/callback-activity.js +6 -3
- package/dist/core/callback-activity.js.map +1 -1
- package/dist/core/extensions/loader-core.d.ts +1 -0
- package/dist/core/extensions/loader-core.d.ts.map +1 -1
- package/dist/core/extensions/loader-core.js +11 -1
- package/dist/core/extensions/loader-core.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +1 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner-registries.d.ts.map +1 -1
- package/dist/core/extensions/runner-registries.js +9 -4
- package/dist/core/extensions/runner-registries.js.map +1 -1
- package/dist/core/extensions/runner-shortcuts.d.ts.map +1 -1
- package/dist/core/extensions/runner-shortcuts.js +1 -0
- package/dist/core/extensions/runner-shortcuts.js.map +1 -1
- package/dist/core/keybindings.d.ts +5 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +4 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/mandatory-resource-loader.d.ts +6 -0
- package/dist/core/mandatory-resource-loader.d.ts.map +1 -0
- package/dist/core/mandatory-resource-loader.js +94 -0
- package/dist/core/mandatory-resource-loader.js.map +1 -0
- package/dist/core/mandatory-runtime-tools.d.ts +10 -0
- package/dist/core/mandatory-runtime-tools.d.ts.map +1 -0
- package/dist/core/mandatory-runtime-tools.js +31 -0
- package/dist/core/mandatory-runtime-tools.js.map +1 -0
- package/dist/core/model-resolver-defaults.js +1 -1
- package/dist/core/model-resolver-defaults.js.map +1 -1
- package/dist/core/resource-loader-reload.d.ts.map +1 -1
- package/dist/core/resource-loader-reload.js +24 -13
- package/dist/core/resource-loader-reload.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +2 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager-ui-accessors.d.ts +4 -1
- package/dist/core/settings-manager-ui-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-ui-accessors.js +22 -0
- package/dist/core/settings-manager-ui-accessors.js.map +1 -1
- package/dist/core/settings-types.d.ts +4 -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.js +1 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/main-session.d.ts.map +1 -1
- package/dist/main-session.js +3 -2
- package/dist/main-session.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +6 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/fast-mode-selector.js +2 -2
- package/dist/modes/interactive/components/fast-mode-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-handlers.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector-handlers.js +3 -0
- package/dist/modes/interactive/components/settings-selector-handlers.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-items.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector-items.js +7 -0
- package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-types.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector-types.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector-types.js.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.js +2 -1
- package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
- package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-deferred-startup.js +1 -0
- package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.js +3 -0
- package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.js +15 -1
- package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +6 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-selectors.js +6 -1
- package/dist/modes/interactive/interactive-selectors.js.map +1 -1
- package/dist/modes/interactive/interactive-session-runtime.js +3 -0
- package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-slash-commands.js +7 -12
- package/dist/modes/interactive/interactive-slash-commands.js.map +1 -1
- package/dist/modes/interactive/interactive-tui.d.ts +1 -0
- package/dist/modes/interactive/interactive-tui.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-tui.js +16 -0
- package/dist/modes/interactive/interactive-tui.js.map +1 -1
- package/dist/modes/rpc/rpc-session-binding.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-session-binding.js +2 -0
- package/dist/modes/rpc/rpc-session-binding.js.map +1 -1
- package/docs/compaction.md +1 -1
- package/docs/environment-variables.md +2 -0
- package/docs/extensions.md +1 -1
- package/docs/intercom.md +29 -24
- package/docs/keybindings.md +5 -2
- package/docs/packages.md +1 -1
- package/docs/providers.md +2 -2
- package/docs/sdk.md +9 -7
- package/docs/settings.md +9 -3
- package/docs/subagents.md +2 -2
- package/docs/usage.md +7 -6
- package/docs/workflows.md +11 -7
- package/npm-shrinkwrap.json +59 -77
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,126 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.16] - 2026-08-29
|
|
6
|
+
|
|
7
|
+
Cumulative release of the `0.9.16-alpha.1` – `0.9.16-alpha.11` prereleases. The summary below covers the user-visible outcome of that work; the per-change detail remains in the prerelease sections below.
|
|
8
|
+
|
|
9
|
+
### Breaking Changes
|
|
10
|
+
|
|
11
|
+
- `AgentSession` now invokes a caller-supplied `Agent.shouldStopAfterTurn` callback before `prepareNextTurn` or `prepareNextTurnWithContext`. Preparation runs only after the loop or a non-empty steering/follow-up queue establishes that another assistant turn will start; it no longer runs after final responses, terminating tool batches without queued work, or a stop callback that returns `true`. For a post-tool threshold crossing, Atomic compacts first, passes that compacted context to preparation, and uses the caller's complete returned replacement for the next provider request. Callers that used preparation as an after-every-turn notification must move that work to `shouldStopAfterTurn` or session events ([#6879](https://github.com/earendil-works/pi/issues/6879)).
|
|
12
|
+
- Removed the public `workflow send` action. Use `workflow answer` for pending workflow prompts and ordinary Intercom for workflow-stage communication.
|
|
13
|
+
- Workflow source that typechecks against the legacy bare `@bastani/workflows` specifier must migrate to `@bastani/atomic/workflows`; removing the broken ambient declaration bridge intentionally removes TypeScript resolution for the legacy name. Runtime loading remains backward compatible because Atomic continues to alias `@bastani/workflows` to the in-memory SDK. ([#2716](https://github.com/bastani-inc/atomic/issues/2716))
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Added JSON-only terminal capability overrides for hyperlinks, Kitty/iTerm2 images, and truecolor, plus a live `fullscreenCopyOnSelect` setting. With automatic selection copying disabled, Ctrl+X copies the retained fullscreen selection before falling back to the last assistant message, while `/copy` keeps its last-message behavior and workflow/scoped-selector hierarchy transitions retain precedence.
|
|
18
|
+
- Added `ui_prompt_start` and `ui_prompt_end` extension events around blocking `ctx.ui` prompts so integrations can distinguish active agent work from waiting for user input. Nested and overlapping prompts form one balanced outer span, and prompt failures or UI-context replacement still emit the matching end notification without delaying the prompt UI. ([#5329](https://github.com/earendil-works/pi/issues/5329))
|
|
19
|
+
- Added fast-mode support for eligible GitHub Copilot models advertised by the signed-in account, alongside the existing OpenAI priority service tier. Chat and workflow scopes remain independently configurable with `/fast`.
|
|
20
|
+
- Added `/thinking [level]` plus searchable model and per-model thinking selectors. Selectors show saved defaults, search by model/provider/default state, order the current and default models first, and use `Ctrl+S` to persist a startup default while Enter changes only the current session ([#8399](https://github.com/earendil-works/pi/issues/8399)).
|
|
21
|
+
- Added a Windows PowerShell tool that prefers PowerShell 7 and falls back to Windows PowerShell when `pwsh.exe` or `powershell.exe` is on `PATH`. The tool is omitted when neither executable is available and is exposed through the SDK with typed extension events and result guards. Bash remains the shell for `!`/`!!`, plus Windows/WSL-friendly default keybindings ([#8512](https://github.com/earendil-works/pi/issues/8512)).
|
|
22
|
+
- Added path-aware, deduplicated settings diagnostics and routed startup diagnostics into the fullscreen transcript so alternate-screen startup cannot hide configuration errors.
|
|
23
|
+
- Added transcript billing notices for compaction and branch summaries when cache-miss notices are enabled. Verbatim Compaction aggregates usage from every completed planner response, including retries, into the persisted boundary, session statistics, footer totals, and cost breakdowns.
|
|
24
|
+
- Added export-only `atomic.share` context records containing the system prompt and tool schemas. Session sharing keeps private-Gist transport and Atomic viewer URLs; no persisted session is mutated and no Radius upload is introduced.
|
|
25
|
+
- Added RPC `clear_queue` to retrieve and remove queued steering and follow-up messages ([#8432](https://github.com/earendil-works/pi/issues/8432)).
|
|
26
|
+
- Exported `detectSupportedImageMimeTypeFromFile` from the public coding-agent API ([#8600](https://github.com/earendil-works/pi/pull/8600)).
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- Updated the external Pi runtime dependencies to 0.84.4, inheriting nested autocomplete ordering, surrogate-safe chunked terminal writes above 1 MiB, slash/kebab double-click selection, the 0.84.3 agent/client/protocol updates, and TUI fixes for narrow-width padding and wrapped Markdown-table link colors ([#8252](https://github.com/earendil-works/pi/issues/8252), [#8335](https://github.com/earendil-works/pi/issues/8335)).
|
|
31
|
+
- Ordinary bundled `intercom` is now a mandatory runtime tool in main chat and SDK-created model sessions. Tool and extension allowlists, exclusions, no-tool and deferred-resource modes, supplied loaders, overrides, same-name custom/project collisions, runtime active-tool mutation, and reload preserve its trusted definition without changing restrictions on any other tool. Fresh SDK sessions do not load optional bundled workflow, subagent, MCP, or web-access extensions unless configured.
|
|
32
|
+
- Updated Baseten's default model from `zai-org/GLM-5.2` to the directly selectable `zai-org/GLM-5.3`; GLM-5.2 remains available when fully disabled reasoning is required, while GLM-5.3 Flash provides multimodal input.
|
|
33
|
+
- Installed builtin extensions (`workflows`, `subagents`, `mcp`, `web-access`, `intercom`) now ship as prebundled ESM entry files. Resource trees (`skills/`, `agents/`, workflow builtins) stay on disk; leftover extension TypeScript is pruned from the npm/binary payload. Source maps stay in the published `dist/`, matching upstream pi.
|
|
34
|
+
- Main-chat model fallback is now session-sticky: after failover, later turns keep using the selected fallback model and thinking level until an explicit `/model` selection or model cycle changes it.
|
|
35
|
+
- The default system prompt now teaches repository-intent inference when a shell tool is available: review recent commits, open and merged PRs, issues and their comments, and project/board status to learn maintainer conventions, and identify the requesting user (`git config user.name`/`user.email`, `gh api user`) to interpret ambiguous requests through their own patterns.
|
|
36
|
+
- The ask_user_question fallback guideline now instructs the agent, when no human input channel exists, to choose the interpretation best supported by the repository and stated objective — mining git history, commits, PRs, issues, and the user's own comments to infer how they would decide — state the assumption, and continue fully autonomously instead of stalling.
|
|
37
|
+
- Model and thinking-level changes are session-scoped by default; saved per-model thinking overrides determine startup behavior, and persistence is now explicit through `Ctrl+S` ([#8356](https://github.com/earendil-works/pi/issues/8356)).
|
|
38
|
+
- Skill discovery silently ignores ordinary root Markdown files without skill frontmatter, continues diagnosing malformed declared skills, and loads nested Markdown skills from packages ([#8012](https://github.com/earendil-works/pi/issues/8012), [#8255](https://github.com/earendil-works/pi/issues/8255)).
|
|
39
|
+
- llama.cpp catalogs now expose sleeping models, refresh local-router catalogs even in offline mode, detect autoload support and offer presets, and explain when `/llama` is required after login ([#8235](https://github.com/earendil-works/pi/issues/8235), [#8236](https://github.com/earendil-works/pi/issues/8236), [#8238](https://github.com/earendil-works/pi/issues/8238), [#8558](https://github.com/earendil-works/pi/issues/8558)).
|
|
40
|
+
- Deferred uncommon syntax grammars until after first render to reduce interactive startup work while keeping common languages available immediately.
|
|
41
|
+
- Extension examples whose intent is final settlement now listen for `agent_settled`; JSON mode exposes tool-call ID and tool name at stream start; session-share links use canonical terminal hyperlinks and perform GitHub authentication preflight before export ([#8242](https://github.com/earendil-works/pi/issues/8242), [#7953](https://github.com/earendil-works/pi/issues/7953)).
|
|
42
|
+
- Compaction now reports truthful aggregate planner usage notices, including multi-attempt Verbatim planning, when cache-miss notices are enabled.
|
|
43
|
+
- Documented `/thinking`, the Ctrl+S startup-default shortcut in the model and thinking pickers, and the `modelThinkingLevels` setting.
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- Fixed workflow discovery helpers from Git-installed production-only packages by making the workflow module loader resolve the same supported TypeBox runtime aliases as extension loading, including `typebox/compile`, `typebox/value`, and legacy `@sinclair/typebox` subpaths.
|
|
48
|
+
- Fixed independent workflow launches appearing indefinitely as empty `running` runs when another workflow's DBOS write stalled. Durable write ordering and errors are isolated per root workflow without weakening the global shutdown drain.
|
|
49
|
+
- Fixed `/fast` command and selector copy that still described fast mode as OpenAI/Codex-only after GitHub Copilot fast variants became eligible.
|
|
50
|
+
- Fixed large tool results crossing the auto-compaction threshold being sent to the provider before compaction. Atomic compacts between tool execution and the next assistant response in the same run, and restores interactive progress when that run resumes ([#6879](https://github.com/earendil-works/pi/issues/6879)).
|
|
51
|
+
- Prevented steering or follow-up messages queued while `shouldStopAfterTurn` resolves `true` from automatically starting another provider request. The stopped run now leaves that work pending for a later explicit prompt or continuation.
|
|
52
|
+
- Fixed `/model` and `/thinking` Ctrl+S failing to persist startup defaults in isolated interactive mode. Isolated mode now refreshes the host settings view and remote scoped-model catalog after the engine acknowledges persist, and `set_thinking_level` can include the engine's clamped level plus the provider/model the engine persisted against so a later `model_changed` cannot re-key the saved thinking override ([#2727](https://github.com/bastani-inc/atomic/issues/2727)).
|
|
53
|
+
- Fixed installed packages where the intercom broker failed to start on every launch, leaving both the `intercom` and `subagent` tools entirely non-functional.
|
|
54
|
+
- Fixed Bun-compiled binaries crashing when a transformed extension performed a second `proper-lockfile` operation. Compiled extension imports now reuse the host's lockfile module instead of transforming and proxy-wrapping its mutable internals.
|
|
55
|
+
- Fixed the published workflow SDK so importing `@bastani/atomic` no longer injects the workflows graph into every consumer's TypeScript program, consumers can typecheck against the package again, and workflow authoring types no longer silently collapse to `any`. ([#2716](https://github.com/bastani-inc/atomic/issues/2716))
|
|
56
|
+
- Workflow stages on installed/prebundled builds now resolve credentials from `~/.atomic/agent` again instead of creating an empty `~/.workflows/agent` and reporting `No API key found` for every provider.
|
|
57
|
+
- Coalesced same-turn sibling `subagent` execution calls into one indexed parallel run instead of rejecting every call after the first ([#2588](https://github.com/bastani-inc/atomic/issues/2588)).
|
|
58
|
+
- Fixed `/thinking` being absent from slash-command autocomplete and added completions for the active model's available thinking levels.
|
|
59
|
+
- Fixed `/tree` ranking below `/thinking` in slash-command autocomplete, so typing `/t` again offers branch navigation before the thinking-level command.
|
|
60
|
+
- Fixed the thinking-level selector so a capability-clamped default still receives the default badge when the saved setting is higher than the active model supports.
|
|
61
|
+
- Fixed the per-model thinking-level settings row opening an empty, unexplained picker when no models are available; it now states that a provider login or API key is required.
|
|
62
|
+
- Failed extension loads now roll back provider registrations applied during that load instead of leaving an earlier provider in the runtime.
|
|
63
|
+
- PowerShell cancellation now terminates the Windows process tree and returns without waiting on descendant-held stdout or stderr.
|
|
64
|
+
- Fixed PowerShell tool calls rendering with the Bash `$` transcript prompt. PowerShell calls now render as `PS> <command>`, and truncated PowerShell output is saved under its own temp-file prefix.
|
|
65
|
+
- Fixed Windows compiled binaries crashing with `ERR_INVALID_FILE_URL_PATH` when Return reached native modifier detection, including from the `/model` selector.
|
|
66
|
+
- Fixed `bundle:dev` and `start:fast` omitting the statically registered OAuth adapters. Development bundles now use the Bun entrypoint shared with compiled builds, so OpenAI Codex and xAI OAuth derivation and refresh no longer fail on unresolved runtime imports.
|
|
67
|
+
- Fixed duplicate fullscreen right-click paste in VS Code-based terminals on Windows ([#8186](https://github.com/earendil-works/pi/issues/8186)).
|
|
68
|
+
- Fixed padded text exceeding narrow terminal widths ([#8252](https://github.com/earendil-works/pi/issues/8252)).
|
|
69
|
+
- Fixed wrapped Markdown table links leaking color into borders and neighboring cells, including tables inside blockquotes ([#8335](https://github.com/earendil-works/pi/issues/8335)).
|
|
70
|
+
- Compaction failures and cancellations now emit `session_compact_failed` to extensions and expose public failure details with their trigger, error, abort/retry state, and whether an extension supplied the compacted text ([#8241](https://github.com/earendil-works/pi/issues/8241)).
|
|
71
|
+
- Automatic compaction now estimates message size when providers report all-zero usage instead of silently skipping the threshold check ([#8328](https://github.com/earendil-works/pi/issues/8328)).
|
|
72
|
+
- Branch and session summaries reject tool calls, and their requests explicitly disable tools; planner requests do the same while retaining validated truncated-range recovery.
|
|
73
|
+
- Branch and session summaries reject token-cap-truncated prose instead of persisting incomplete checkpoints ([#7048](https://github.com/earendil-works/pi/issues/7048)).
|
|
74
|
+
- Branch summaries record the source leaf rather than the navigation destination.
|
|
75
|
+
- Fixed package updates comparing versions for inequality and potentially downgrading a newer installed package; upgrades now use semantic-version ordering ([#8239](https://github.com/earendil-works/pi/issues/8239)).
|
|
76
|
+
- Fixed extension flags accepting runtime defaults whose value did not match the declared boolean/string type, and failed extension factories leaking partially registered commands, tools, flags, and inherited resources into later loads ([#8123](https://github.com/earendil-works/pi/issues/8123), [#8424](https://github.com/earendil-works/pi/issues/8424)).
|
|
77
|
+
- Fixed hung authenticated model-catalog attempts consuming the whole request budget without retrying by applying a per-attempt timeout before retrying.
|
|
78
|
+
- Fixed UTF-8 BOMs breaking auth, model, keybinding, frontmatter, package, resource, theme, CLI, and external-editor text inputs while preserving BOM-aware hashline edits.
|
|
79
|
+
- Fixed atomic managed-state rewrites resetting existing file permissions. `auth.json` and `models-store.json` are created owner-only (`0600`) but keep an administrator-managed mode across later rewrites.
|
|
80
|
+
- Fixed explicitly persisted default models disappearing from non-empty model scopes; persisted defaults are now added to both the active and saved scope.
|
|
81
|
+
- Fixed extension messages sent with `triggerTurn: false` while the agent is running being inserted between a tool call and its result; they are now appended after the turn's tool results ([#8537](https://github.com/earendil-works/pi/issues/8537)).
|
|
82
|
+
- Fixed compaction range planning and branch/session summaries forcing `toolChoice: "none"`, which sent `tool_choice` with no tools and could be rejected by gateways ([#8649](https://github.com/earendil-works/pi/issues/8649), [#8638](https://github.com/earendil-works/pi/issues/8638)).
|
|
83
|
+
- Fixed Windows shell aborts crashing Atomic when `taskkill.exe` is not on `PATH`. Both `killProcessTree` and the detached-child guardian worker now spawn the System32 executable and consume the asynchronous spawn error ([#6596](https://github.com/earendil-works/pi/issues/6596)).
|
|
84
|
+
- Fixed Windows `taskkill` spawning without `windowsHide`. Because the spawn is `detached`, Windows allocated and briefly flashed a console window on every process-tree kill.
|
|
85
|
+
- Fixed session files whose final record has no trailing newline not being repaired on load, so a later append no longer concatenates onto that record.
|
|
86
|
+
- Fixed toggling thinking-block visibility discarding partial Bash output. Rendered assistant messages are updated in place instead of rebuilding the chat and its live tool components ([#8611](https://github.com/earendil-works/pi/issues/8611)).
|
|
87
|
+
|
|
88
|
+
### Removed
|
|
89
|
+
|
|
90
|
+
- Removed the bundled writing-rule set from the default system prompt's `Guidelines` section. The unrelated "Be concise in your responses" and "Show file paths clearly when working with files" guidelines remain.
|
|
91
|
+
- Removed the bundled `/subagents-doctor`, `/run`, and `/parallel` entries from the slash-command catalog, and dropped `/parallel-review` and `/parallel-cleanup` suggestions from the `/atomic` guide. Launch children with the `subagent` tool.
|
|
92
|
+
|
|
93
|
+
## [0.9.16-alpha.11] - 2026-08-28
|
|
94
|
+
|
|
95
|
+
### Added
|
|
96
|
+
|
|
97
|
+
- Added JSON-only terminal capability overrides for hyperlinks, Kitty/iTerm2 images, and truecolor, plus a live `fullscreenCopyOnSelect` setting. With automatic selection copying disabled, Ctrl+X copies the retained fullscreen selection before falling back to the last assistant message, while `/copy` keeps its last-message behavior and workflow/scoped-selector hierarchy transitions retain precedence.
|
|
98
|
+
|
|
99
|
+
### Changed
|
|
100
|
+
|
|
101
|
+
- Updated the external Pi runtime dependencies to 0.84.4, inheriting nested autocomplete ordering, surrogate-safe chunked terminal writes above 1 MiB, and slash/kebab double-click selection.
|
|
102
|
+
- Ordinary bundled `intercom` is now a mandatory runtime tool in main chat and SDK-created model sessions. Tool and extension allowlists, exclusions, no-tool and deferred-resource modes, supplied loaders, overrides, same-name custom/project collisions, runtime active-tool mutation, and reload preserve its trusted definition without changing restrictions on any other tool. Fresh SDK sessions do not load optional bundled workflow, subagent, MCP, or web-access extensions unless configured.
|
|
103
|
+
|
|
104
|
+
### Fixed
|
|
105
|
+
|
|
106
|
+
- Fixed workflow discovery helpers from Git-installed production-only packages by making the workflow module loader resolve the same supported TypeBox runtime aliases as extension loading, including `typebox/compile`, `typebox/value`, and legacy `@sinclair/typebox` subpaths.
|
|
107
|
+
- Fixed independent workflow launches appearing indefinitely as empty `running` runs when another workflow's DBOS write stalled. Durable write ordering and errors are isolated per root workflow without weakening the global shutdown drain.
|
|
108
|
+
- Fixed `/fast` command and selector copy that still described fast mode as OpenAI/Codex-only after GitHub Copilot fast variants became eligible.
|
|
109
|
+
|
|
110
|
+
## [0.9.16-alpha.10] - 2026-08-28
|
|
111
|
+
|
|
112
|
+
### Breaking Changes
|
|
113
|
+
|
|
114
|
+
- `AgentSession` now invokes a caller-supplied `Agent.shouldStopAfterTurn` callback before `prepareNextTurn` or `prepareNextTurnWithContext`. Preparation runs only after the loop or a non-empty steering/follow-up queue establishes that another assistant turn will start; it no longer runs after final responses, terminating tool batches without queued work, or a stop callback that returns `true`. For a post-tool threshold crossing, Atomic compacts first, passes that compacted context to preparation, and uses the caller's complete returned replacement for the next provider request. Callers that used preparation as an after-every-turn notification must move that work to `shouldStopAfterTurn` or session events ([#6879](https://github.com/earendil-works/pi/issues/6879)).
|
|
115
|
+
|
|
116
|
+
### Changed
|
|
117
|
+
|
|
118
|
+
- Updated Baseten's default model from `zai-org/GLM-5.2` to the directly selectable `zai-org/GLM-5.3`; GLM-5.2 remains available when fully disabled reasoning is required, while GLM-5.3 Flash provides multimodal input.
|
|
119
|
+
|
|
120
|
+
### Fixed
|
|
121
|
+
|
|
122
|
+
- Fixed large tool results crossing the auto-compaction threshold being sent to the provider before compaction. Atomic compacts between tool execution and the next assistant response in the same run, and restores interactive progress when that run resumes ([#6879](https://github.com/earendil-works/pi/issues/6879)).
|
|
123
|
+
- Prevented steering or follow-up messages queued while `shouldStopAfterTurn` resolves `true` from automatically starting another provider request. The stopped run now leaves that work pending for a later explicit prompt or continuation.
|
|
124
|
+
|
|
5
125
|
## [0.9.16-alpha.9] - 2026-08-27
|
|
6
126
|
|
|
7
127
|
### Added
|
package/README.md
CHANGED
|
@@ -557,10 +557,10 @@ cat README.md | atomic -p "Summarize this text"
|
|
|
557
557
|
|
|
558
558
|
| Option | Description |
|
|
559
559
|
|--------|-------------|
|
|
560
|
-
| `--tools <list>`, `-t <list>` | Allowlist specific tool names across built-in, extension, and custom tools |
|
|
561
|
-
| `--exclude-tools <list>`, `-xt <list>` | Denylist specific built-in, extension, and custom tools |
|
|
560
|
+
| `--tools <list>`, `-t <list>` | Allowlist specific tool names across built-in, extension, and custom tools; mandatory ordinary `intercom` remains available |
|
|
561
|
+
| `--exclude-tools <list>`, `-xt <list>` | Denylist specific built-in, extension, and custom tools; mandatory ordinary `intercom` cannot be excluded |
|
|
562
562
|
| `--no-builtin-tools`, `-nbt` | Disable built-in tools by default but keep extension/custom tools enabled |
|
|
563
|
-
| `--no-tools`, `-nt` | Disable
|
|
563
|
+
| `--no-tools`, `-nt` | Disable every tool except mandatory ordinary `intercom` |
|
|
564
564
|
|
|
565
565
|
Default built-in tools: `read`, `bash`, `edit`, `write`, `find`, `search`, `ask_user_question`, `todo`, plus `powershell` on native Windows when a PowerShell executable is available. `find.paths` accepts directories, files, or glob paths such as `*.ts` and honors `timeout`; `search` accepts `pattern`, `paths`, `i`, `gitignore`, and `skip` for regex content-search pagination. `read`/`search`/`write`/`edit` share session-scoped hashline snapshot tags for stale-safe line edits; copied hashline output is stripped by `write` only when it matches a known current-session snapshot. Archive selectors are Bun-native, and internal-resource selectors use the session router when available. Use `--exclude-tools` to disable one or more tools while leaving the rest available.
|
|
566
566
|
|
|
@@ -578,7 +578,7 @@ Project trust gates `.atomic`/legacy `.pi` project resources, project package se
|
|
|
578
578
|
| Option | Description |
|
|
579
579
|
|--------|-------------|
|
|
580
580
|
| `-e`, `--extension <source>` | Load extension from path, npm, or git (repeatable) |
|
|
581
|
-
| `--no-extensions`, `-ne` | Disable extension discovery |
|
|
581
|
+
| `--no-extensions`, `-ne` | Disable optional extension discovery; mandatory bundled Intercom remains loaded |
|
|
582
582
|
| `--skill <path>` | Load skill (repeatable) |
|
|
583
583
|
| `--no-skills`, `-ns` | Disable skill discovery |
|
|
584
584
|
| `--prompt-template <path>` | Load prompt template (repeatable) |
|
|
@@ -4,6 +4,48 @@ All notable changes to the `pi-intercom` extension will be documented in this fi
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.9.16] - 2026-08-29
|
|
8
|
+
|
|
9
|
+
Cumulative release of the `0.9.16-alpha.1` – `0.9.16-alpha.11` prereleases. The summary below covers the user-visible outcome of that work; the per-change detail remains in the prerelease sections below.
|
|
10
|
+
|
|
11
|
+
### Breaking Changes
|
|
12
|
+
|
|
13
|
+
- Parent-targeted blocking asks no longer pause a child for `subagent` resume. They end the child and return a fresh-subagent `[TASK_CONTEXT]` handoff; migrate supervisors to launch a new child with the answer ([#2604](https://github.com/bastani-inc/atomic/issues/2604)).
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Intercom sessions can now hold multiple group memberships. Runtime `join` is additive, targeted `leave` removes one membership, bare `leave` resets to the startup home group, and the new `groups` action discovers every available group with session counts and membership markers. `list` remains session discovery, `status` reports the complete membership set, legacy single-group clients retain their existing behavior, and `contact_supervisor` keeps its capability-based cross-group route.
|
|
18
|
+
- Extended ordinary `send` delivery to known workflow stages whose sessions have not initialized, with durable FIFO queueing, a distinct `queued` acknowledgment, same-group enforcement, bounded per-stage capacity, structured pre-start `ask` refusal, and delivery through the existing Intercom path before the stage's first model turn. ([#2717](https://github.com/bastani-inc/atomic/issues/2717))
|
|
19
|
+
- Concurrent blocking asks now use a correlation-keyed waiter registry, with configurable `maxPendingAsks` capacity, exact out-of-order reply and selective-disconnect settlement, and a structured refusal when full. Blocking supervisor decisions remain exclusive per child while coexisting with ordinary peer asks ([#2628](https://github.com/bastani-inc/atomic/issues/2628)).
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- Intercom can no longer be disabled with `enabled: false`; Atomic always loads and registers the lightweight ordinary `intercom` tool while keeping broker connection and heavy initialization lazy. `contact_supervisor` remains subagent-only.
|
|
24
|
+
- `contact_supervisor` decisions/interviews and child-to-parent `intercom.ask` now preserve the original question, ordered duplicate attachments, and agent identity in the fresh-start handoff before broker send or reply-waiter admission ([#2604](https://github.com/bastani-inc/atomic/issues/2604)).
|
|
25
|
+
- Session teardown rejects every pending reply waiter while preserving per-waiter reply, timeout, abort, cancel, and peer-disconnect settlement.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- Intercom skill and user docs now tell agents to discover a workflow stage's `workflow:<rootRunId>` invocation group with `groups` and join it before steering the stage.
|
|
30
|
+
- Blocking `ask` and `contact_supervisor` waits now fail promptly with the departed session's name when their target disconnects after delivery, instead of hanging until the 10-minute timeout ([#2627](https://github.com/bastani-inc/atomic/issues/2627)).
|
|
31
|
+
- Replying to an exact pending ask now removes its queued turn context, preventing the same ask from resurfacing and being answered twice ([#2628](https://github.com/bastani-inc/atomic/issues/2628)).
|
|
32
|
+
|
|
33
|
+
## [0.9.16-alpha.11] - 2026-08-28
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- Intercom can no longer be disabled with `enabled: false`; Atomic always loads and registers the lightweight ordinary `intercom` tool while keeping broker connection and heavy initialization lazy. `contact_supervisor` remains subagent-only.
|
|
38
|
+
|
|
39
|
+
## [0.9.16-alpha.10] - 2026-08-28
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
|
|
43
|
+
- Intercom sessions can now hold multiple group memberships. Runtime `join` is additive, targeted `leave` removes one membership, bare `leave` resets to the startup home group, and the new `groups` action discovers every available group with session counts and membership markers. `list` remains session discovery, `status` reports the complete membership set, legacy single-group clients retain their existing behavior, and `contact_supervisor` keeps its capability-based cross-group route.
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- Intercom skill and user docs now tell agents to discover a workflow stage's `workflow:<rootRunId>` invocation group with `groups` and join it before steering the stage.
|
|
48
|
+
|
|
7
49
|
## [0.9.16-alpha.8] - 2026-08-27
|
|
8
50
|
|
|
9
51
|
### Added
|
|
@@ -51,8 +51,7 @@ Coordinate with other local Atomic/pi sessions on related codebases. Use `/skill
|
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
A session becomes intercom-connected when all of these are true:
|
|
54
|
-
- the
|
|
55
|
-
- `enabled` is not set to `false` in `~/.atomic/agent/intercom/config.json` (Atomic) or the legacy `~/.pi/agent/intercom/config.json` fallback
|
|
54
|
+
- the mandatory bundled Intercom extension is loaded in that Atomic model session
|
|
56
55
|
- the model or user has invoked an Intercom tool, `/intercom`, or the `ALT+M` overlay in that session
|
|
57
56
|
- the local broker is running or can be auto-started
|
|
58
57
|
|
|
@@ -82,13 +81,15 @@ intercom({ action: "list" })
|
|
|
82
81
|
// → **Other sessions:**
|
|
83
82
|
// → • research (6332faab-1111-4222-8333-123456789abc) — ~/projects/api (claude-sonnet-4) [same cwd, thinking]
|
|
84
83
|
|
|
85
|
-
//
|
|
84
|
+
// Add a named membership (it is created if no session is there yet)
|
|
86
85
|
intercom({ action: "join", group: "api-review" })
|
|
87
|
-
// → Joined intercom group "api-review".
|
|
86
|
+
// → Joined intercom group "api-review". Memberships: default, api-review.
|
|
88
87
|
|
|
89
|
-
//
|
|
90
|
-
intercom({ action: "
|
|
91
|
-
|
|
88
|
+
// Discover all available groups and see which ones you belong to
|
|
89
|
+
intercom({ action: "groups" })
|
|
90
|
+
|
|
91
|
+
// Leave one membership, or omit group to reset to the startup home group
|
|
92
|
+
intercom({ action: "leave", group: "api-review" })
|
|
92
93
|
|
|
93
94
|
// Send a message
|
|
94
95
|
intercom({ action: "send", to: "research", message: "Check if UserService.validate() handles null" })
|
|
@@ -181,7 +182,7 @@ intercom({
|
|
|
181
182
|
// Worker continues implementing with the answer, same turn, full context.
|
|
182
183
|
```
|
|
183
184
|
|
|
184
|
-
To coordinate two plain chat sessions without changing
|
|
185
|
+
To coordinate two plain chat sessions without changing startup config, have each call `intercom({ action: "join", group: "NAME" })`. Joining adds a membership without changing the session ID or removing existing memberships. Calls to `list`, `send`, and `ask` can then reach any session sharing at least one membership. Use `intercom({ action: "groups" })` to discover every available name, connected-session count, and membership marker. Call `intercom({ action: "leave", group: "NAME" })` to remove one membership while keeping the others, or bare `leave` to reset to the original home group. `contact_supervisor` keeps its dedicated capability-based cross-group behavior.
|
|
185
186
|
|
|
186
187
|
**Worker finds something unexpected — escalates and waits:**
|
|
187
188
|
```typescript
|
|
@@ -333,12 +334,12 @@ The supervisor can reply with plain JSON or a fenced `json` block. If the reply
|
|
|
333
334
|
|
|
334
335
|
| Parameter | Type | Description |
|
|
335
336
|
|-----------|------|-------------|
|
|
336
|
-
| `action` | string | `"list"`, `"join"`, `"leave"`, `"send"`, `"ask"`, `"reply"`, `"pending"`, or `"status"` |
|
|
337
|
+
| `action` | string | `"list"`, `"groups"`, `"join"`, `"leave"`, `"send"`, `"ask"`, `"reply"`, `"pending"`, or `"status"` |
|
|
337
338
|
| `to` | string | Exact session name/full session ID, or `<runId>:<stageKey>` for `send` to a not-yet-started workflow stage (for send/ask, or targeted reply) |
|
|
338
339
|
| `message` | string | Message text (for send/ask/reply) |
|
|
339
340
|
| `attachments` | array | Optional `file`, `snippet`, or `context` attachments |
|
|
340
341
|
| `replyTo` | string | Optional message ID for threading or replying to an `ask` |
|
|
341
|
-
| `group` | string | Group name for `join`; read-only
|
|
342
|
+
| `group` | string | Group name for `join` or optional targeted `leave`; read-only filter for `list`/`status`. `send`/`ask` require a shared membership. |
|
|
342
343
|
|
|
343
344
|
### contact_supervisor
|
|
344
345
|
|
|
@@ -358,11 +359,13 @@ Only registered in sessions where `pi-subagents` supplied the required child bri
|
|
|
358
359
|
|
|
359
360
|
### intercom actions
|
|
360
361
|
|
|
361
|
-
**`join`** —
|
|
362
|
+
**`join`** — Adds a trimmed named membership and creates that group when no peer is there yet. The result reports the complete membership set. `default` is shared; `true` and `auto` remain reserved.
|
|
363
|
+
|
|
364
|
+
**`leave`** — With `group`, removes only that membership. Without `group`, resets the complete set to the startup home group. The result reports the memberships that remain.
|
|
362
365
|
|
|
363
|
-
**`
|
|
366
|
+
**`groups`** — Lists every group represented by a connected session, with session counts and membership markers, so callers can discover names instead of guessing.
|
|
364
367
|
|
|
365
|
-
**`list`** —
|
|
368
|
+
**`list`** — Keeps session-listing semantics: returns the current session and every active session sharing at least one membership. Pass `group` for a read-only view of one group.
|
|
366
369
|
|
|
367
370
|
Live target lookup accepts only an exact full session ID or an exact case-insensitive session name. Ordinary `send` also accepts `<runId>:<stageKey>` for a known workflow stage whose session has not initialized. The run ID is a full UUID and the stage key is exact. Unknown runs and stages retain the ordinary unknown-target failure. All targeting remains **group-scoped** — see [Groups](#groups) below.
|
|
368
371
|
|
|
@@ -376,7 +379,7 @@ Live target lookup accepts only an exact full session ID or an exact case-insens
|
|
|
376
379
|
|
|
377
380
|
`contact_supervisor` decisions and interviews are deliberately exclusive per child: one supervisor wait may coexist with ordinary peer asks, but a second concurrent supervisor wait receives `Already waiting for a supervisor reply`. Claimed foreground parent handoffs remain first-claim-wins and do not allocate a waiter. Multiple children can contact the same parent independently because inbound asks and handoffs are keyed by child/message identity. Mutual peer asks are supported, but each side must process inbound work to reply; the per-waiter timeout remains the deadlock backstop.
|
|
378
381
|
|
|
379
|
-
**`status`** — Shows connection status, session ID, current
|
|
382
|
+
**`status`** — Shows connection status, session ID, every current membership, and the total visible-session count. A `group` filter remains a read-only peek.
|
|
380
383
|
|
|
381
384
|
## Keyboard Shortcuts
|
|
382
385
|
|
|
@@ -396,7 +399,6 @@ Create `~/.atomic/agent/intercom/config.json` for Atomic. Legacy pi-compatible i
|
|
|
396
399
|
"brokerCommand": "npx",
|
|
397
400
|
"brokerArgs": ["--no-install", "tsx"],
|
|
398
401
|
"confirmSend": false,
|
|
399
|
-
"enabled": true,
|
|
400
402
|
"replyHint": true,
|
|
401
403
|
"status": "researching"
|
|
402
404
|
}
|
|
@@ -409,7 +411,6 @@ The default `npx --no-install tsx` pair is a compatibility sentinel: intercom re
|
|
|
409
411
|
| `brokerCommand` | `"npx"` | Command used to start the local broker process; the default sentinel is hardened internally to avoid PATH lookup |
|
|
410
412
|
| `brokerArgs` | `["--no-install", "tsx"]` | Arguments passed to `brokerCommand` before the broker script path |
|
|
411
413
|
| `confirmSend` | false | Show a confirmation dialog before non-reply sends from an interactive session with UI |
|
|
412
|
-
| `enabled` | true | Enable/disable intercom entirely |
|
|
413
414
|
| `replyHint` | true | Include reply instruction in incoming messages |
|
|
414
415
|
| `status` | — | Optional custom status suffix shown after the automatic lifecycle status, for example `thinking · researching` |
|
|
415
416
|
|
|
@@ -450,7 +451,7 @@ graph TB
|
|
|
450
451
|
B2 <-->|Local Socket/Pipe| B3
|
|
451
452
|
```
|
|
452
453
|
|
|
453
|
-
The broker is a standalone TypeScript process that manages session registration and message routing. It auto-spawns when the first
|
|
454
|
+
The broker is a standalone TypeScript process that manages session registration and message routing. It auto-spawns when the first session that invokes Intercom needs it and exits after 5 seconds when the last connected session disconnects. Clients now reconnect automatically if the broker disappears and later comes back.
|
|
454
455
|
|
|
455
456
|
Messages use length-prefixed JSON over a local socket/pipe transport (4-byte length + JSON payload) to handle fragmentation properly. The protocol includes request correlation for session listing, explicit delivery failures, and validation for malformed or out-of-order messages.
|
|
456
457
|
|
|
@@ -17,8 +17,15 @@ import {
|
|
|
17
17
|
type PendingStageRoute,
|
|
18
18
|
} from "./send-handler.js";
|
|
19
19
|
import { SupervisorChannelCache } from "./supervisor-channel.js";
|
|
20
|
-
import { normalizeGroup } from "../group.js";
|
|
20
|
+
import { hasGroup, normalizeGroup, normalizeGroups } from "../group.js";
|
|
21
21
|
import { handleBrokerPresence } from "./presence-handler.js";
|
|
22
|
+
import {
|
|
23
|
+
knownGroupSummaries,
|
|
24
|
+
sessionGroups,
|
|
25
|
+
sessionsInGroup,
|
|
26
|
+
sessionsVisibleTo,
|
|
27
|
+
setSessionGroups,
|
|
28
|
+
} from "./group-membership.js";
|
|
22
29
|
import { PendingQuestionIndex } from "./pending-question-index.js";
|
|
23
30
|
|
|
24
31
|
const INTERCOM_DIR = getIntercomDirPath();
|
|
@@ -95,6 +102,11 @@ function isSessionRegistration(value: unknown): value is Omit<SessionInfo, "id">
|
|
|
95
102
|
return false;
|
|
96
103
|
}
|
|
97
104
|
|
|
105
|
+
|
|
106
|
+
if (session.groups !== undefined &&
|
|
107
|
+
(!Array.isArray(session.groups) || !session.groups.every((group) => typeof group === "string"))) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
98
110
|
return session.status === undefined || typeof session.status === "string";
|
|
99
111
|
}
|
|
100
112
|
function isSupervisorRegistration(value: unknown): value is SupervisorRegistration {
|
|
@@ -247,7 +259,7 @@ class IntercomBroker {
|
|
|
247
259
|
this.pendingStageRoutes.delete(route.runId);
|
|
248
260
|
return false;
|
|
249
261
|
}
|
|
250
|
-
if (route.liveTargetId === undefined &&
|
|
262
|
+
if (route.liveTargetId === undefined && !hasGroup(sessionGroups(route.from.info), ownerRegistration.group)) {
|
|
251
263
|
writeMessage(route.socket, {
|
|
252
264
|
type: "delivery_failed",
|
|
253
265
|
messageId: route.message.id,
|
|
@@ -490,7 +502,7 @@ class IntercomBroker {
|
|
|
490
502
|
target === undefined ||
|
|
491
503
|
target.info.id === currentId ||
|
|
492
504
|
normalizeGroup(target.registrationGroup) !== routeGroup ||
|
|
493
|
-
|
|
505
|
+
!hasGroup(sessionGroups(target.info), routeGroup)
|
|
494
506
|
) {
|
|
495
507
|
this.failPendingStageNotification(socket, message.id, attemptId, "Session not found");
|
|
496
508
|
return;
|
|
@@ -596,15 +608,17 @@ class IntercomBroker {
|
|
|
596
608
|
|
|
597
609
|
const id = randomUUID();
|
|
598
610
|
setId(id);
|
|
611
|
+
const initialGroups = normalizeGroups(clientMessage.session.groups, clientMessage.session.group);
|
|
612
|
+
const legacyGroup = normalizeGroup(clientMessage.session.group ?? initialGroups.values().next().value);
|
|
599
613
|
const info: SessionInfo = {
|
|
600
614
|
...clientMessage.session,
|
|
601
615
|
id,
|
|
602
|
-
group: normalizeGroup(clientMessage.session.group),
|
|
603
616
|
};
|
|
617
|
+
setSessionGroups(info, initialGroups, legacyGroup);
|
|
604
618
|
this.sessions.set(id, {
|
|
605
619
|
socket,
|
|
606
620
|
info,
|
|
607
|
-
registrationGroup:
|
|
621
|
+
registrationGroup: legacyGroup,
|
|
608
622
|
...(typeof info.name === "string" && info.name.trim().length > 0
|
|
609
623
|
? { registrationName: info.name.trim() }
|
|
610
624
|
: {}),
|
|
@@ -625,7 +639,7 @@ class IntercomBroker {
|
|
|
625
639
|
writeMessage(socket, supervisorId
|
|
626
640
|
? { type: "registered", sessionId: id, supervisorSessionId: supervisorId }
|
|
627
641
|
: { type: "registered", sessionId: id });
|
|
628
|
-
this.
|
|
642
|
+
this.broadcastToMemberships({ type: "session_joined", session: info }, sessionGroups(info), id);
|
|
629
643
|
break;
|
|
630
644
|
}
|
|
631
645
|
|
|
@@ -645,16 +659,26 @@ class IntercomBroker {
|
|
|
645
659
|
}
|
|
646
660
|
|
|
647
661
|
const requester = currentId ? this.sessions.get(currentId) : undefined;
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
.map((s) => s.info)
|
|
653
|
-
.filter((info) => normalizeGroup(info.group) === effectiveGroup);
|
|
662
|
+
if (requester === undefined) throw new Error("Session not found");
|
|
663
|
+
const sessions = typeof clientMessage.group === "string"
|
|
664
|
+
? sessionsInGroup(this.sessions, clientMessage.group)
|
|
665
|
+
: sessionsVisibleTo(this.sessions, requester.info);
|
|
654
666
|
writeMessage(socket, { type: "sessions", requestId: clientMessage.requestId, sessions });
|
|
655
667
|
break;
|
|
656
668
|
}
|
|
657
669
|
|
|
670
|
+
case "list_groups": {
|
|
671
|
+
if (typeof clientMessage.requestId !== "string") throw new Error("Invalid list_groups message");
|
|
672
|
+
const requester = currentId ? this.sessions.get(currentId) : undefined;
|
|
673
|
+
if (requester === undefined) throw new Error("Session not found");
|
|
674
|
+
writeMessage(socket, {
|
|
675
|
+
type: "groups",
|
|
676
|
+
requestId: clientMessage.requestId,
|
|
677
|
+
groups: knownGroupSummaries(this.sessions, requester.info),
|
|
678
|
+
});
|
|
679
|
+
break;
|
|
680
|
+
}
|
|
681
|
+
|
|
658
682
|
case "authorize_supervisor": {
|
|
659
683
|
const supervisor = this.sessions.get(currentId);
|
|
660
684
|
if (!supervisor?.supervisorOwnerToken || typeof clientMessage.requestId !== "string"
|
|
@@ -815,7 +839,9 @@ class IntercomBroker {
|
|
|
815
839
|
break;
|
|
816
840
|
}
|
|
817
841
|
|
|
818
|
-
case "presence":
|
|
842
|
+
case "presence":
|
|
843
|
+
case "join_group":
|
|
844
|
+
case "leave_group": {
|
|
819
845
|
handleBrokerPresence(
|
|
820
846
|
socket,
|
|
821
847
|
clientMessage,
|
|
@@ -881,13 +907,12 @@ class IntercomBroker {
|
|
|
881
907
|
if (activation.sessionId === sessionId) this.liveWorkflowStageRouteActivations.delete(requestId);
|
|
882
908
|
}
|
|
883
909
|
this.sessions.delete(sessionId);
|
|
884
|
-
this.
|
|
910
|
+
this.broadcastToMemberships({ type: "session_left", sessionId }, sessionGroups(departed.info), sessionId);
|
|
885
911
|
}
|
|
886
|
-
/** Deliver a broadcast
|
|
887
|
-
private
|
|
888
|
-
const target = normalizeGroup(group);
|
|
912
|
+
/** Deliver a broadcast once to each session represented in any given group. */
|
|
913
|
+
private broadcastToMemberships(msg: BrokerMessage, groups: ReadonlySet<string>, exclude?: string): void {
|
|
889
914
|
for (const [id, session] of this.sessions) {
|
|
890
|
-
if (id !== exclude &&
|
|
915
|
+
if (id !== exclude && [...groups].some((group) => hasGroup(sessionGroups(session.info), group))) {
|
|
891
916
|
writeMessage(session.socket, msg);
|
|
892
917
|
}
|
|
893
918
|
}
|