@bastani/atomic 0.9.16-alpha.8 → 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.
Files changed (212) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/README.md +4 -4
  3. package/dist/builtin/intercom/CHANGELOG.md +42 -0
  4. package/dist/builtin/intercom/README.md +18 -17
  5. package/dist/builtin/intercom/broker/broker.ts +43 -18
  6. package/dist/builtin/intercom/broker/client.ts +138 -7
  7. package/dist/builtin/intercom/broker/group-isolation.ts +3 -3
  8. package/dist/builtin/intercom/broker/group-membership.ts +55 -0
  9. package/dist/builtin/intercom/broker/presence-handler.ts +62 -50
  10. package/dist/builtin/intercom/broker/send-handler.ts +2 -3
  11. package/dist/builtin/intercom/group.ts +40 -0
  12. package/dist/builtin/intercom/index.bundle.mjs +556 -185
  13. package/dist/builtin/intercom/package.json +2 -2
  14. package/dist/builtin/intercom/skills/intercom/SKILL.md +16 -10
  15. package/dist/builtin/intercom/types.ts +24 -2
  16. package/dist/builtin/mcp/index.bundle.mjs +268 -54
  17. package/dist/builtin/mcp/package.json +2 -2
  18. package/dist/builtin/subagents/CHANGELOG.md +51 -0
  19. package/dist/builtin/subagents/README.md +3 -3
  20. package/dist/builtin/subagents/agents/code-simplifier.md +1 -1
  21. package/dist/builtin/subagents/agents/codebase-analyzer.md +1 -1
  22. package/dist/builtin/subagents/agents/codebase-locator.md +1 -1
  23. package/dist/builtin/subagents/agents/codebase-online-researcher.md +1 -1
  24. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +1 -1
  25. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +1 -1
  26. package/dist/builtin/subagents/agents/codebase-research-locator.md +1 -1
  27. package/dist/builtin/subagents/agents/debugger.md +1 -1
  28. package/dist/builtin/subagents/agents/worker.md +1 -1
  29. package/dist/builtin/subagents/package.json +3 -3
  30. package/dist/builtin/subagents/src/extension/index.bundle.mjs +488 -142
  31. package/dist/builtin/web-access/index.bundle.mjs +268 -54
  32. package/dist/builtin/web-access/package.json +2 -2
  33. package/dist/builtin/workflows/CHANGELOG.md +70 -0
  34. package/dist/builtin/workflows/README.md +2 -2
  35. package/dist/builtin/workflows/builtin/{chunk-zf28603f.js → chunk-3y1hmzw6.js} +36 -6
  36. package/dist/builtin/workflows/builtin/{chunk-nqr34qp3.js → chunk-6rbajjf5.js} +7 -1
  37. package/dist/builtin/workflows/builtin/{chunk-v04c5qmd.js → chunk-bz1c9732.js} +15 -3
  38. package/dist/builtin/workflows/builtin/{chunk-cdtd3m3w.js → chunk-dattsgxg.js} +1 -1
  39. package/dist/builtin/workflows/builtin/{chunk-5n10x7j2.js → chunk-gdx0avpx.js} +421 -69
  40. package/dist/builtin/workflows/builtin/{chunk-hdpj1dkw.js → chunk-w9c7rkrk.js} +1 -1
  41. package/dist/builtin/workflows/builtin/goal.js +3 -3
  42. package/dist/builtin/workflows/builtin/index.js +5 -5
  43. package/dist/builtin/workflows/builtin/open-claude-design.js +2 -2
  44. package/dist/builtin/workflows/builtin/ralph.js +3 -3
  45. package/dist/builtin/workflows/package.json +2 -2
  46. package/dist/builtin/workflows/src/extension/index.bundle.mjs +597 -145
  47. package/dist/builtin/workflows/src/index.js +278 -74
  48. package/dist/cli/args.js +6 -6
  49. package/dist/cli/args.js.map +1 -1
  50. package/dist/cli/config-selector.d.ts.map +1 -1
  51. package/dist/cli/config-selector.js +2 -1
  52. package/dist/cli/config-selector.js.map +1 -1
  53. package/dist/cli/session-picker.d.ts +2 -1
  54. package/dist/cli/session-picker.d.ts.map +1 -1
  55. package/dist/cli/session-picker.js +3 -2
  56. package/dist/cli/session-picker.js.map +1 -1
  57. package/dist/cli/startup-ui.d.ts.map +1 -1
  58. package/dist/cli/startup-ui.js +2 -1
  59. package/dist/cli/startup-ui.js.map +1 -1
  60. package/dist/core/agent-session-methods.d.ts +1 -0
  61. package/dist/core/agent-session-methods.d.ts.map +1 -1
  62. package/dist/core/agent-session-methods.js.map +1 -1
  63. package/dist/core/agent-session-post-tool-compaction.d.ts.map +1 -1
  64. package/dist/core/agent-session-post-tool-compaction.js +3 -6
  65. package/dist/core/agent-session-post-tool-compaction.js.map +1 -1
  66. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  67. package/dist/core/agent-session-prompt.js +3 -1
  68. package/dist/core/agent-session-prompt.js.map +1 -1
  69. package/dist/core/agent-session-services.d.ts.map +1 -1
  70. package/dist/core/agent-session-services.js +6 -3
  71. package/dist/core/agent-session-services.js.map +1 -1
  72. package/dist/core/agent-session-state.d.ts.map +1 -1
  73. package/dist/core/agent-session-state.js +7 -5
  74. package/dist/core/agent-session-state.js.map +1 -1
  75. package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
  76. package/dist/core/agent-session-tool-hooks.js +37 -23
  77. package/dist/core/agent-session-tool-hooks.js.map +1 -1
  78. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  79. package/dist/core/agent-session-tool-registry.js +9 -2
  80. package/dist/core/agent-session-tool-registry.js.map +1 -1
  81. package/dist/core/agent-session.d.ts +2 -0
  82. package/dist/core/agent-session.d.ts.map +1 -1
  83. package/dist/core/agent-session.js +2 -0
  84. package/dist/core/agent-session.js.map +1 -1
  85. package/dist/core/builtin-packages.d.ts +4 -0
  86. package/dist/core/builtin-packages.d.ts.map +1 -1
  87. package/dist/core/builtin-packages.js +22 -1
  88. package/dist/core/builtin-packages.js.map +1 -1
  89. package/dist/core/callback-activity.d.ts.map +1 -1
  90. package/dist/core/callback-activity.js +6 -3
  91. package/dist/core/callback-activity.js.map +1 -1
  92. package/dist/core/extensions/agent-events.d.ts +15 -0
  93. package/dist/core/extensions/agent-events.d.ts.map +1 -1
  94. package/dist/core/extensions/agent-events.js.map +1 -1
  95. package/dist/core/extensions/api-types.d.ts +3 -1
  96. package/dist/core/extensions/api-types.d.ts.map +1 -1
  97. package/dist/core/extensions/api-types.js.map +1 -1
  98. package/dist/core/extensions/event-types.d.ts +2 -2
  99. package/dist/core/extensions/event-types.d.ts.map +1 -1
  100. package/dist/core/extensions/event-types.js.map +1 -1
  101. package/dist/core/extensions/index.d.ts +1 -1
  102. package/dist/core/extensions/index.d.ts.map +1 -1
  103. package/dist/core/extensions/index.js.map +1 -1
  104. package/dist/core/extensions/loader-core.d.ts +1 -0
  105. package/dist/core/extensions/loader-core.d.ts.map +1 -1
  106. package/dist/core/extensions/loader-core.js +11 -1
  107. package/dist/core/extensions/loader-core.js.map +1 -1
  108. package/dist/core/extensions/loader.d.ts +1 -1
  109. package/dist/core/extensions/loader.d.ts.map +1 -1
  110. package/dist/core/extensions/loader.js +1 -1
  111. package/dist/core/extensions/loader.js.map +1 -1
  112. package/dist/core/extensions/runner-registries.d.ts.map +1 -1
  113. package/dist/core/extensions/runner-registries.js +9 -4
  114. package/dist/core/extensions/runner-registries.js.map +1 -1
  115. package/dist/core/extensions/runner-shortcuts.d.ts.map +1 -1
  116. package/dist/core/extensions/runner-shortcuts.js +1 -0
  117. package/dist/core/extensions/runner-shortcuts.js.map +1 -1
  118. package/dist/core/extensions/runner.d.ts +6 -0
  119. package/dist/core/extensions/runner.d.ts.map +1 -1
  120. package/dist/core/extensions/runner.js +65 -1
  121. package/dist/core/extensions/runner.js.map +1 -1
  122. package/dist/core/keybindings.d.ts +5 -0
  123. package/dist/core/keybindings.d.ts.map +1 -1
  124. package/dist/core/keybindings.js +4 -0
  125. package/dist/core/keybindings.js.map +1 -1
  126. package/dist/core/mandatory-resource-loader.d.ts +6 -0
  127. package/dist/core/mandatory-resource-loader.d.ts.map +1 -0
  128. package/dist/core/mandatory-resource-loader.js +94 -0
  129. package/dist/core/mandatory-resource-loader.js.map +1 -0
  130. package/dist/core/mandatory-runtime-tools.d.ts +10 -0
  131. package/dist/core/mandatory-runtime-tools.d.ts.map +1 -0
  132. package/dist/core/mandatory-runtime-tools.js +31 -0
  133. package/dist/core/mandatory-runtime-tools.js.map +1 -0
  134. package/dist/core/model-resolver-defaults.js +1 -1
  135. package/dist/core/model-resolver-defaults.js.map +1 -1
  136. package/dist/core/resource-loader-reload.d.ts.map +1 -1
  137. package/dist/core/resource-loader-reload.js +24 -13
  138. package/dist/core/resource-loader-reload.js.map +1 -1
  139. package/dist/core/sdk.d.ts.map +1 -1
  140. package/dist/core/sdk.js +2 -0
  141. package/dist/core/sdk.js.map +1 -1
  142. package/dist/core/settings-manager-ui-accessors.d.ts +4 -1
  143. package/dist/core/settings-manager-ui-accessors.d.ts.map +1 -1
  144. package/dist/core/settings-manager-ui-accessors.js +22 -0
  145. package/dist/core/settings-manager-ui-accessors.js.map +1 -1
  146. package/dist/core/settings-types.d.ts +4 -0
  147. package/dist/core/settings-types.d.ts.map +1 -1
  148. package/dist/core/settings-types.js.map +1 -1
  149. package/dist/core/slash-commands.js +1 -1
  150. package/dist/core/slash-commands.js.map +1 -1
  151. package/dist/index-extensions.d.ts +1 -1
  152. package/dist/index-extensions.d.ts.map +1 -1
  153. package/dist/index-extensions.js.map +1 -1
  154. package/dist/main-session.d.ts.map +1 -1
  155. package/dist/main-session.js +3 -2
  156. package/dist/main-session.js.map +1 -1
  157. package/dist/main.d.ts.map +1 -1
  158. package/dist/main.js +6 -0
  159. package/dist/main.js.map +1 -1
  160. package/dist/modes/interactive/components/fast-mode-selector.js +2 -2
  161. package/dist/modes/interactive/components/fast-mode-selector.js.map +1 -1
  162. package/dist/modes/interactive/components/settings-selector-handlers.d.ts.map +1 -1
  163. package/dist/modes/interactive/components/settings-selector-handlers.js +3 -0
  164. package/dist/modes/interactive/components/settings-selector-handlers.js.map +1 -1
  165. package/dist/modes/interactive/components/settings-selector-items.d.ts.map +1 -1
  166. package/dist/modes/interactive/components/settings-selector-items.js +7 -0
  167. package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
  168. package/dist/modes/interactive/components/settings-selector-types.d.ts +2 -0
  169. package/dist/modes/interactive/components/settings-selector-types.d.ts.map +1 -1
  170. package/dist/modes/interactive/components/settings-selector-types.js.map +1 -1
  171. package/dist/modes/interactive/interactive-agent-events.js +2 -1
  172. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  173. package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -1
  174. package/dist/modes/interactive/interactive-deferred-startup.js +1 -0
  175. package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
  176. package/dist/modes/interactive/interactive-extension-runtime.js +1 -1
  177. package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
  178. package/dist/modes/interactive/interactive-input-handling.js +3 -0
  179. package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
  180. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  181. package/dist/modes/interactive/interactive-mode-base.js +15 -1
  182. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  183. package/dist/modes/interactive/interactive-mode-surface.d.ts +6 -1
  184. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  185. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  186. package/dist/modes/interactive/interactive-selectors.js +6 -1
  187. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  188. package/dist/modes/interactive/interactive-session-runtime.js +3 -0
  189. package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
  190. package/dist/modes/interactive/interactive-slash-commands.js +7 -12
  191. package/dist/modes/interactive/interactive-slash-commands.js.map +1 -1
  192. package/dist/modes/interactive/interactive-tui.d.ts +1 -0
  193. package/dist/modes/interactive/interactive-tui.d.ts.map +1 -1
  194. package/dist/modes/interactive/interactive-tui.js +16 -0
  195. package/dist/modes/interactive/interactive-tui.js.map +1 -1
  196. package/dist/modes/rpc/rpc-session-binding.d.ts.map +1 -1
  197. package/dist/modes/rpc/rpc-session-binding.js +2 -0
  198. package/dist/modes/rpc/rpc-session-binding.js.map +1 -1
  199. package/docs/compaction.md +1 -1
  200. package/docs/environment-variables.md +2 -0
  201. package/docs/extensions.md +20 -1
  202. package/docs/intercom.md +29 -24
  203. package/docs/keybindings.md +5 -2
  204. package/docs/packages.md +1 -1
  205. package/docs/providers.md +2 -2
  206. package/docs/sdk.md +9 -7
  207. package/docs/settings.md +9 -3
  208. package/docs/subagents.md +2 -2
  209. package/docs/usage.md +7 -6
  210. package/docs/workflows.md +11 -7
  211. package/npm-shrinkwrap.json +59 -77
  212. package/package.json +7 -7
@@ -9224,11 +9224,13 @@ function runSynchronousCallback(descriptor, callback) {
9224
9224
  }
9225
9225
  }
9226
9226
  async function runCallback(descriptor, callback) {
9227
+ if (!reporter)
9228
+ return callback();
9229
+ await yieldToEventLoop();
9227
9230
  const active = beginActivity(descriptor);
9228
9231
  if (!active)
9229
9232
  return callback();
9230
9233
  try {
9231
- await yieldToEventLoop();
9232
9234
  return await callback();
9233
9235
  } finally {
9234
9236
  active.reporter.finished(active.activity.id);
@@ -11960,12 +11962,34 @@ var init_runner_events = __esm(() => {
11960
11962
  init_callback_activity();
11961
11963
  });
11962
11964
 
11965
+ // src/core/mandatory-runtime-tools.ts
11966
+ function isTrustedMandatoryRuntimeTool(registration) {
11967
+ return MANDATORY_TOOL_NAMES.has(registration.definition.name) && TRUSTED_MANDATORY_DEFINITIONS.has(registration.definition);
11968
+ }
11969
+ function isMandatoryRuntimeTool(name) {
11970
+ return MANDATORY_TOOL_NAMES.has(name);
11971
+ }
11972
+ function appendRegisteredMandatoryTools(tools, registry) {
11973
+ for (const name of MANDATORY_TOOL_NAMES) {
11974
+ const tool = registry.get(name);
11975
+ if (tool && !tools.some((candidate) => candidate.name === name))
11976
+ tools.push(tool);
11977
+ }
11978
+ return tools;
11979
+ }
11980
+ var MANDATORY_TOOL_NAMES, TRUSTED_MANDATORY_DEFINITIONS;
11981
+ var init_mandatory_runtime_tools = __esm(() => {
11982
+ MANDATORY_TOOL_NAMES = new Set(["intercom"]);
11983
+ TRUSTED_MANDATORY_DEFINITIONS = new WeakSet;
11984
+ });
11985
+
11963
11986
  // src/core/extensions/runner-registries.ts
11964
11987
  function collectRegisteredTools(extensions) {
11965
11988
  const toolsByName = new Map;
11966
11989
  for (const ext of extensions) {
11967
11990
  for (const tool of ext.tools.values()) {
11968
- if (!toolsByName.has(tool.definition.name)) {
11991
+ const existing = toolsByName.get(tool.definition.name);
11992
+ if (!existing || isMandatoryRuntimeTool(tool.definition.name) && isTrustedMandatoryRuntimeTool(tool)) {
11969
11993
  toolsByName.set(tool.definition.name, tool);
11970
11994
  }
11971
11995
  }
@@ -11973,13 +11997,16 @@ function collectRegisteredTools(extensions) {
11973
11997
  return Array.from(toolsByName.values());
11974
11998
  }
11975
11999
  function findToolDefinition(extensions, toolName) {
12000
+ let first;
11976
12001
  for (const ext of extensions) {
11977
12002
  const tool = ext.tools.get(toolName);
11978
- if (tool) {
12003
+ if (!tool)
12004
+ continue;
12005
+ first ??= tool;
12006
+ if (isMandatoryRuntimeTool(toolName) && isTrustedMandatoryRuntimeTool(tool))
11979
12007
  return tool.definition;
11980
- }
11981
12008
  }
11982
- return;
12009
+ return first?.definition;
11983
12010
  }
11984
12011
  function collectFlags(extensions) {
11985
12012
  const allFlags = new Map;
@@ -12047,6 +12074,9 @@ function resolveRegisteredCommands(extensions) {
12047
12074
  return { ...command, invocationName };
12048
12075
  });
12049
12076
  }
12077
+ var init_runner_registries = __esm(() => {
12078
+ init_mandatory_runtime_tools();
12079
+ });
12050
12080
 
12051
12081
  // src/core/extensions/runner-shortcuts.ts
12052
12082
  function resolveExtensionShortcuts(extensions, resolvedKeybindings, hasUI) {
@@ -12110,6 +12140,7 @@ var init_runner_shortcuts = __esm(() => {
12110
12140
  "app.thinking.toggle",
12111
12141
  "app.editor.external",
12112
12142
  "app.message.followUp",
12143
+ "app.message.copy",
12113
12144
  "tui.input.submit",
12114
12145
  "tui.select.confirm",
12115
12146
  "tui.select.cancel",
@@ -12236,6 +12267,8 @@ class ExtensionRunner {
12236
12267
  shortcutDiagnostics = [];
12237
12268
  commandDiagnostics = [];
12238
12269
  staleMessage;
12270
+ uiPromptBinding = 0;
12271
+ activeUIPrompt;
12239
12272
  constructor(extensions, runtime, cwd, sessionManager, modelRegistry, orchestrationContext, subagentPolicy) {
12240
12273
  this.extensions = extensions;
12241
12274
  this.runtime = runtime;
@@ -12330,9 +12363,71 @@ class ExtensionRunner {
12330
12363
  this.reloadHandler = async () => {};
12331
12364
  }
12332
12365
  setUIContext(uiContext, mode = "print") {
12333
- this.uiContext = uiContext ?? noOpUIContext;
12366
+ this.endActiveUIPrompt();
12367
+ const binding = ++this.uiPromptBinding;
12368
+ this.uiContext = uiContext ? this.wrapUIPromptContext(uiContext, binding) : noOpUIContext;
12334
12369
  this.mode = mode;
12335
12370
  }
12371
+ wrapUIPromptContext(ui, binding) {
12372
+ return {
12373
+ ...ui,
12374
+ select: (title, options, opts) => this.withUIPrompt(binding, "select", title, () => ui.select(title, options, opts)),
12375
+ confirm: (title, message, opts) => this.withUIPrompt(binding, "confirm", title, () => ui.confirm(title, message, opts)),
12376
+ input: (title, placeholder, opts) => this.withUIPrompt(binding, "input", title, () => ui.input(title, placeholder, opts)),
12377
+ editor: (title, prefill, opts) => this.withUIPrompt(binding, "editor", title, () => ui.editor(title, prefill, opts)),
12378
+ custom: (factory, options) => this.withUIPrompt(binding, "custom", undefined, () => ui.custom(factory, options))
12379
+ };
12380
+ }
12381
+ withUIPrompt(binding, kind, title, run) {
12382
+ if (binding !== this.uiPromptBinding)
12383
+ return run();
12384
+ let prompt = this.activeUIPrompt;
12385
+ if (!prompt) {
12386
+ prompt = { depth: 0, kind, title };
12387
+ this.activeUIPrompt = prompt;
12388
+ this.emitUIPromptEvent({
12389
+ type: "ui_prompt_start",
12390
+ reason: "ui_prompt",
12391
+ kind,
12392
+ ...title === undefined ? {} : { title }
12393
+ });
12394
+ }
12395
+ prompt.depth += 1;
12396
+ let finished = false;
12397
+ const finish = () => {
12398
+ if (finished)
12399
+ return;
12400
+ finished = true;
12401
+ if (this.activeUIPrompt !== prompt)
12402
+ return;
12403
+ prompt.depth -= 1;
12404
+ if (prompt.depth === 0)
12405
+ this.endActiveUIPrompt(prompt);
12406
+ };
12407
+ try {
12408
+ return run().finally(finish);
12409
+ } catch (error) {
12410
+ finish();
12411
+ throw error;
12412
+ }
12413
+ }
12414
+ endActiveUIPrompt(prompt = this.activeUIPrompt) {
12415
+ if (!prompt || this.activeUIPrompt !== prompt)
12416
+ return;
12417
+ this.activeUIPrompt = undefined;
12418
+ prompt.depth = 0;
12419
+ this.emitUIPromptEvent({
12420
+ type: "ui_prompt_end",
12421
+ reason: "ui_prompt",
12422
+ kind: prompt.kind,
12423
+ ...prompt.title === undefined ? {} : { title: prompt.title }
12424
+ });
12425
+ }
12426
+ emitUIPromptEvent(event) {
12427
+ queueMicrotask(() => {
12428
+ this.emit(event);
12429
+ });
12430
+ }
12336
12431
  getUIContext() {
12337
12432
  return this.uiContext;
12338
12433
  }
@@ -12509,6 +12604,7 @@ var init_runner = __esm(() => {
12509
12604
  init_loader_runtime();
12510
12605
  init_runner_context();
12511
12606
  init_runner_events();
12607
+ init_runner_registries();
12512
12608
  init_runner_shortcuts();
12513
12609
  init_runner_ui();
12514
12610
  init_stale_context();
@@ -14712,11 +14808,13 @@ async function _runAgentContinue() {
14712
14808
  }
14713
14809
  async function _continueQueuedAgentMessages() {
14714
14810
  await this._agentEventQueue;
14715
- while (!this._queuedMessagesPaused && this.agent.hasQueuedMessages()) {
14811
+ while (!this._stopAfterTurnBlockedContinuation && !this._queuedMessagesPaused && this.agent.hasQueuedMessages()) {
14716
14812
  await this.agent.continue();
14717
14813
  await this.waitForRetry();
14718
14814
  await this._agentEventQueue;
14719
14815
  }
14816
+ if (this._stopAfterTurnBlockedContinuation)
14817
+ return;
14720
14818
  await answerAdmittedQueuedMessage(this);
14721
14819
  }
14722
14820
  async function answerAdmittedQueuedMessage(session) {
@@ -16107,14 +16205,13 @@ function getToolDefinition(name) {
16107
16205
  }
16108
16206
  function setActiveToolsByName(toolNames) {
16109
16207
  const tools = [];
16110
- const validToolNames = [];
16111
16208
  for (const name of toolNames) {
16112
16209
  const tool = this._toolRegistry.get(name);
16113
- if (tool) {
16210
+ if (tool)
16114
16211
  tools.push(tool);
16115
- validToolNames.push(name);
16116
- }
16117
16212
  }
16213
+ appendRegisteredMandatoryTools(tools, this._toolRegistry);
16214
+ const validToolNames = tools.map((tool) => tool.name);
16118
16215
  this.agent.state.tools = tools;
16119
16216
  this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames);
16120
16217
  this.agent.state.systemPrompt = this._systemPromptOverride ?? this._baseSystemPrompt;
@@ -16171,7 +16268,7 @@ function _rebuildSystemPrompt(toolNames) {
16171
16268
  customPrompt: loaderSystemPrompt,
16172
16269
  appendSystemPrompt,
16173
16270
  selectedTools: validToolNames,
16174
- excludedTools: this._excludedToolNames ? Array.from(this._excludedToolNames) : undefined,
16271
+ excludedTools: this._excludedToolNames ? Array.from(this._excludedToolNames).filter((name) => !isMandatoryRuntimeTool(name)) : undefined,
16175
16272
  toolSnippets,
16176
16273
  promptGuidelines
16177
16274
  };
@@ -16184,6 +16281,7 @@ function _refreshBaseSystemPromptFromActiveTools() {
16184
16281
  }
16185
16282
  var agentSessionStateMethods;
16186
16283
  var init_agent_session_state = __esm(() => {
16284
+ init_mandatory_runtime_tools();
16187
16285
  init_skill_catalog();
16188
16286
  init_system_prompt();
16189
16287
  agentSessionStateMethods = {
@@ -17211,6 +17309,17 @@ function _installAgentToolHooks() {
17211
17309
  }
17212
17310
  function _installAgentNextTurnRefresh() {
17213
17311
  const previousPrepareNextTurnWithContext = this.agent.prepareNextTurnWithContext ?? (this.agent.prepareNextTurn ? async (_turn, signal) => await this.agent.prepareNextTurn?.(signal) : undefined);
17312
+ const previousShouldStopAfterTurn = this.agent.shouldStopAfterTurn;
17313
+ this.agent.shouldStopAfterTurn = async (turn, signal) => {
17314
+ const toolCallIds = turn.message.content.filter((part) => part.type === "toolCall").map((part) => part.id);
17315
+ const terminatingBatch = toolCallIds.length > 0 && toolCallIds.every((id) => this._terminatingToolCallIds.has(id));
17316
+ for (const id of toolCallIds)
17317
+ this._terminatingToolCallIds.delete(id);
17318
+ const shouldStop = await previousShouldStopAfterTurn?.(turn, signal) ?? false;
17319
+ this._stopAfterTurnBlockedContinuation = shouldStop;
17320
+ await settleFallbackAfterTurn(this, turn, terminatingBatch);
17321
+ return shouldStop;
17322
+ };
17214
17323
  const previousTransformContext = this.agent.transformContext;
17215
17324
  this.agent.transformContext = async (messages, signal) => {
17216
17325
  const transformed = previousTransformContext ? await previousTransformContext(messages, signal) : messages;
@@ -17218,24 +17327,17 @@ function _installAgentNextTurnRefresh() {
17218
17327
  assertToolPairingInvariant(guarded);
17219
17328
  return guarded;
17220
17329
  };
17221
- this.agent.prepareNextTurnWithContext = async (turn, signal) => {
17222
- const previousSnapshot = await previousPrepareNextTurnWithContext?.(turn, signal);
17223
- const previousContext = previousSnapshot?.context ?? turn.context;
17224
- const toolCallIds = turn.message.content.filter((part) => part.type === "toolCall").map((part) => part.id);
17225
- const terminatingBatch = toolCallIds.length > 0 && toolCallIds.every((id) => this._terminatingToolCallIds.has(id));
17226
- for (const id of toolCallIds)
17227
- this._terminatingToolCallIds.delete(id);
17228
- const messages = turn.toolResults.length > 0 && !terminatingBatch ? await this._preflightPostToolContext(previousContext.messages, signal) : previousContext.messages;
17229
- const preserveFallbackForFailure = turn.message.role === "assistant" && !this.agent.hasQueuedMessages() && (turn.message.stopReason === "length" || this._isEmptyCompletion?.(turn.message) === true || this._isSafetyRefusal?.(turn.message) === true);
17230
- if (!preserveFallbackForFailure && (turn.toolResults.length === 0 || terminatingBatch)) {
17231
- await this._agentEventQueue;
17232
- await this._settleFallbackModelScope();
17233
- }
17330
+ const prepareTurn = async (turn, signal) => {
17331
+ const compactedMessages = turn.toolResults.length > 0 ? await this._preflightPostToolContext(turn.context.messages, signal) : turn.context.messages;
17332
+ const compactedContext = compactedMessages === turn.context.messages ? turn.context : { ...turn.context, messages: compactedMessages };
17333
+ const preparedTurn = compactedContext === turn.context ? turn : { ...turn, context: compactedContext };
17334
+ const previousSnapshot = await previousPrepareNextTurnWithContext?.(preparedTurn, signal);
17335
+ const previousContext = previousSnapshot?.context ?? compactedContext;
17234
17336
  return {
17235
17337
  ...previousSnapshot,
17236
17338
  context: {
17237
17339
  ...previousContext,
17238
- messages,
17340
+ messages: previousContext.messages,
17239
17341
  systemPrompt: this._systemPromptOverride ?? this._baseSystemPrompt,
17240
17342
  tools: this.agent.state.tools.slice()
17241
17343
  },
@@ -17243,6 +17345,14 @@ function _installAgentNextTurnRefresh() {
17243
17345
  thinkingLevel: this.agent.state.thinkingLevel
17244
17346
  };
17245
17347
  };
17348
+ this.agent.prepareNextTurnWithContext = prepareTurn;
17349
+ }
17350
+ async function settleFallbackAfterTurn(session, turn, terminatingBatch) {
17351
+ const preserveFallbackForFailure = turn.message.role === "assistant" && !session.agent.hasQueuedMessages() && (turn.message.stopReason === "length" || session._isEmptyCompletion?.(turn.message) === true || session._isSafetyRefusal?.(turn.message) === true);
17352
+ if (!preserveFallbackForFailure && (turn.toolResults.length === 0 || terminatingBatch)) {
17353
+ await session._agentEventQueue;
17354
+ await session._settleFallbackModelScope();
17355
+ }
17246
17356
  }
17247
17357
  var agentSessionToolHooksMethods;
17248
17358
  var init_agent_session_tool_hooks = __esm(() => {
@@ -17325,6 +17435,7 @@ var init_loader_virtual_modules = __esm(() => {
17325
17435
  });
17326
17436
 
17327
17437
  // src/core/extensions/loader-core.ts
17438
+ var runtimeEventBuses;
17328
17439
  var init_loader_core = __esm(() => {
17329
17440
  init_event_loop();
17330
17441
  init_paths();
@@ -17334,6 +17445,7 @@ var init_loader_core = __esm(() => {
17334
17445
  init_loader_resources();
17335
17446
  init_loader_runtime();
17336
17447
  init_loader_virtual_modules();
17448
+ runtimeEventBuses = new WeakMap;
17337
17449
  });
17338
17450
 
17339
17451
  // src/core/package-manager-manifest.ts
@@ -22427,7 +22539,7 @@ class FastModeSelectorComponent {
22427
22539
  }
22428
22540
  invalidate() {}
22429
22541
  render(width) {
22430
- const lines = [truncateToWidth10(theme.bold(theme.fg("accent", "Codex fast mode")), width)];
22542
+ const lines = [truncateToWidth10(theme.bold(theme.fg("accent", "Fast mode")), width)];
22431
22543
  for (const line of wrapTextWithAnsi3(DESCRIPTION, Math.max(20, width))) {
22432
22544
  lines.push(theme.fg("muted", line));
22433
22545
  }
@@ -22510,7 +22622,7 @@ class FastModeSelectorComponent {
22510
22622
  return this.getFocusedRow() === row ? theme.fg("muted", text) : theme.fg("dim", text);
22511
22623
  }
22512
22624
  }
22513
- var ROWS, LABEL_WIDTH = 16, DESCRIPTION = "Priority tier for supported OpenAI and shared ChatGPT Codex transports.", ROW_DETAILS;
22625
+ var ROWS, LABEL_WIDTH = 16, DESCRIPTION = "Use faster routing for the selected model when supported by its provider.", ROW_DETAILS;
22514
22626
  var init_fast_mode_selector = __esm(() => {
22515
22627
  init_theme();
22516
22628
  ROWS = ["chat", "workflow"];
@@ -23737,6 +23849,10 @@ var init_keybindings = __esm(() => {
23737
23849
  defaultKeys: windowsKeybindings ? "alt+q" : "alt+up",
23738
23850
  description: "Restore queued messages"
23739
23851
  },
23852
+ "app.message.copy": {
23853
+ defaultKeys: "ctrl+x",
23854
+ description: "Copy fullscreen selection or last agent message"
23855
+ },
23740
23856
  "app.clipboard.pasteImage": {
23741
23857
  defaultKeys: windowsKeybindings ? "alt+v" : "ctrl+v",
23742
23858
  description: "Paste image from clipboard (text fallback)"
@@ -25122,6 +25238,9 @@ function createSettingsChangeHandler(callbacks) {
25122
25238
  case "fullscreen-exit-output":
25123
25239
  callbacks.onFullscreenExitOutputChange(newValue);
25124
25240
  break;
25241
+ case "fullscreen-copy-on-select":
25242
+ callbacks.onFullscreenCopyOnSelectChange(newValue === "true");
25243
+ break;
25125
25244
  case "editor-padding":
25126
25245
  callbacks.onEditorPaddingXChange(parseInt(newValue, 10));
25127
25246
  break;
@@ -25509,6 +25628,13 @@ function insertUiToggles(items, config) {
25509
25628
  values: ["transcript", "resume-hint"]
25510
25629
  });
25511
25630
  insertAfter(items, "fullscreen-exit-output", {
25631
+ id: "fullscreen-copy-on-select",
25632
+ label: "Fullscreen copy on select",
25633
+ description: "Copy selected transcript text automatically on mouse release",
25634
+ currentValue: config.fullscreenCopyOnSelect ? "true" : "false",
25635
+ values: ["true", "false"]
25636
+ });
25637
+ insertAfter(items, "fullscreen-copy-on-select", {
25512
25638
  id: "editor-padding",
25513
25639
  label: "Editor padding",
25514
25640
  description: "Horizontal padding for input editor (0-3)",
@@ -38583,6 +38709,8 @@ function _refreshToolRegistry(options) {
38583
38709
  const allowedToolNames = this._allowedToolNames;
38584
38710
  const excludedToolNames = this._excludedToolNames;
38585
38711
  const isExposedTool = (name) => {
38712
+ if (isMandatoryRuntimeTool(name))
38713
+ return true;
38586
38714
  if (allowedToolNames && !allowedToolNames.has(name)) {
38587
38715
  return false;
38588
38716
  }
@@ -38591,10 +38719,10 @@ function _refreshToolRegistry(options) {
38591
38719
  }
38592
38720
  return true;
38593
38721
  };
38594
- const registeredTools = this._extensionRunner.getAllRegisteredTools();
38722
+ const registeredTools = this._extensionRunner.getAllRegisteredTools().filter((tool) => !isMandatoryRuntimeTool(tool.definition.name) || isTrustedMandatoryRuntimeTool(tool));
38595
38723
  const allCustomTools = [
38596
38724
  ...registeredTools,
38597
- ...this._customTools.map((definition) => ({
38725
+ ...this._customTools.filter((definition) => !isMandatoryRuntimeTool(definition.name)).map((definition) => ({
38598
38726
  definition,
38599
38727
  sourceInfo: createSyntheticSourceInfo(`<sdk:${definition.name}>`, { source: "sdk" })
38600
38728
  }))
@@ -38715,6 +38843,7 @@ function _buildRuntime(options) {
38715
38843
  var agentSessionToolRegistryMethods;
38716
38844
  var init_agent_session_tool_registry = __esm(() => {
38717
38845
  init_extensions();
38846
+ init_mandatory_runtime_tools();
38718
38847
  init_model_registry();
38719
38848
  init_tools();
38720
38849
  init_session_temp_dir();
@@ -39557,6 +39686,7 @@ class AgentSessionBase {
39557
39686
  _postToolCompactionPreflightError = undefined;
39558
39687
  _pendingPostToolCompactionGuard = undefined;
39559
39688
  _terminatingToolCallIds = new Set;
39689
+ _stopAfterTurnBlockedContinuation = false;
39560
39690
  _disposed = false;
39561
39691
  _branchSummaryAbortController = undefined;
39562
39692
  _sessionSummaryAbortController = undefined;
@@ -39705,11 +39835,12 @@ var init_builtin_packages = __esm(() => {
39705
39835
  { packageName: "@bastani/subagents", workspaceDirName: "subagents", distDirName: "subagents" },
39706
39836
  { packageName: "@bastani/mcp", workspaceDirName: "mcp", distDirName: "mcp" },
39707
39837
  { packageName: "@bastani/web-access", workspaceDirName: "web-access", distDirName: "web-access" },
39708
- { packageName: "@bastani/intercom", workspaceDirName: "intercom", distDirName: "intercom" }
39838
+ { packageName: "@bastani/intercom", workspaceDirName: "intercom", distDirName: "intercom", mandatory: true }
39709
39839
  ];
39710
39840
  BUILTIN_PACKAGES = WORKSPACE_BUILTINS.map((spec) => ({
39711
39841
  packageName: spec.packageName,
39712
39842
  distDirName: spec.distDirName,
39843
+ mandatory: spec.mandatory === true,
39713
39844
  requiredEntries: requiredEntriesForBuiltin(spec.distDirName),
39714
39845
  sourceCandidates: ({ here, packageDir, isSourceCheckout }) => isSourceCheckout ? [join37(packageDir, "..", spec.workspaceDirName), join37(here, "..", "..", "..", spec.workspaceDirName)] : []
39715
39846
  }));
@@ -43035,7 +43166,9 @@ var init_resource_loader_extensions = __esm(() => {
43035
43166
  var init_resource_loader_reload = __esm(() => {
43036
43167
  init_event_loop();
43037
43168
  init_paths();
43169
+ init_builtin_packages();
43038
43170
  init_loader();
43171
+ init_mandatory_runtime_tools();
43039
43172
  init_resource_loader_assets();
43040
43173
  init_resource_loader_context_files();
43041
43174
  init_resource_loader_discovery();
@@ -44192,6 +44325,28 @@ var init_settings_manager_ui_accessors = __esm(() => {
44192
44325
  state.markModified("fullscreenExitOutput");
44193
44326
  state.save();
44194
44327
  },
44328
+ getFullscreenCopyOnSelect() {
44329
+ return settingsInternals(this).settings.fullscreenCopyOnSelect !== false;
44330
+ },
44331
+ setFullscreenCopyOnSelect(enabled) {
44332
+ const state = settingsInternals(this);
44333
+ state.globalSettings.fullscreenCopyOnSelect = enabled;
44334
+ state.markModified("fullscreenCopyOnSelect");
44335
+ state.save();
44336
+ },
44337
+ getTerminalCapabilityOverrides() {
44338
+ const terminal = settingsInternals(this).settings.terminal;
44339
+ const overrides = {};
44340
+ if (typeof terminal?.hyperlinks === "boolean")
44341
+ overrides.hyperlinks = terminal.hyperlinks;
44342
+ if (terminal?.images === "kitty" || terminal?.images === "iterm2")
44343
+ overrides.images = terminal.images;
44344
+ else if (terminal?.images === false)
44345
+ overrides.images = null;
44346
+ if (typeof terminal?.trueColor === "boolean")
44347
+ overrides.trueColor = terminal.trueColor;
44348
+ return overrides;
44349
+ },
44195
44350
  getEditorPaddingX() {
44196
44351
  return settingsInternals(this).settings.editorPaddingX ?? 0;
44197
44352
  },
@@ -44337,6 +44492,14 @@ var init_resource_loader = __esm(() => {
44337
44492
  init_resource_loader_core();
44338
44493
  init_skill_catalog();
44339
44494
  });
44495
+ // src/core/mandatory-resource-loader.ts
44496
+ var init_mandatory_resource_loader = __esm(() => {
44497
+ init_builtin_packages();
44498
+ init_loader();
44499
+ init_mandatory_runtime_tools();
44500
+ init_skill_catalog();
44501
+ });
44502
+
44340
44503
  // src/core/model-resolver-defaults.ts
44341
44504
  function findPreferredAvailableModel(availableModels) {
44342
44505
  for (const [provider, defaultId] of Object.entries(defaultModelPerProvider)) {
@@ -44377,7 +44540,7 @@ var init_model_resolver_defaults = __esm(() => {
44377
44540
  huggingface: "moonshotai/Kimi-K2.6",
44378
44541
  fireworks: "accounts/fireworks/models/kimi-k2p6",
44379
44542
  together: "moonshotai/Kimi-K2.6",
44380
- baseten: "zai-org/GLM-5.2",
44543
+ baseten: "zai-org/GLM-5.3",
44381
44544
  opencode: "kimi-k2.6",
44382
44545
  "opencode-go": "kimi-k2.6",
44383
44546
  "kimi-coding": "kimi-for-coding",
@@ -45035,6 +45198,7 @@ var init_session_cwd = __esm(() => {
45035
45198
  var init_agent_session_services = __esm(() => {
45036
45199
  init_config();
45037
45200
  init_paths();
45201
+ init_mandatory_resource_loader();
45038
45202
  init_model_runtime();
45039
45203
  init_resource_loader();
45040
45204
  init_sdk();
@@ -45371,6 +45535,7 @@ var init_sdk = __esm(() => {
45371
45535
  init_agent_session();
45372
45536
  init_auth_guidance();
45373
45537
  init_codex_fast_mode();
45538
+ init_mandatory_resource_loader();
45374
45539
  init_messages();
45375
45540
  init_model_resolver();
45376
45541
  init_model_runtime();
@@ -45474,7 +45639,12 @@ var init_list_models = __esm(() => {
45474
45639
  });
45475
45640
 
45476
45641
  // src/cli/startup-ui.ts
45477
- import { ProcessTerminal, setKeybindings, TuiMainScreen } from "@earendil-works/pi-tui";
45642
+ import {
45643
+ ProcessTerminal,
45644
+ setCapabilityOverrides,
45645
+ setKeybindings,
45646
+ TuiMainScreen
45647
+ } from "@earendil-works/pi-tui";
45478
45648
  var init_startup_ui = __esm(() => {
45479
45649
  init_config();
45480
45650
  init_keybindings();
@@ -45562,7 +45732,7 @@ var init_main_first_time_setup = __esm(() => {
45562
45732
  init_startup_ui();
45563
45733
  });
45564
45734
  // src/cli/session-picker.ts
45565
- import { ProcessTerminal as ProcessTerminal2, setKeybindings as setKeybindings2, TuiMainScreen as TuiMainScreen2 } from "@earendil-works/pi-tui";
45735
+ import { ProcessTerminal as ProcessTerminal2, setCapabilityOverrides as setCapabilityOverrides2, setKeybindings as setKeybindings2, TuiMainScreen as TuiMainScreen2 } from "@earendil-works/pi-tui";
45566
45736
  var init_session_picker = __esm(() => {
45567
45737
  init_config();
45568
45738
  init_keybindings();
@@ -45570,7 +45740,7 @@ var init_session_picker = __esm(() => {
45570
45740
  });
45571
45741
 
45572
45742
  // src/main-session.ts
45573
- import { ProcessTerminal as ProcessTerminal3, setKeybindings as setKeybindings3, TuiMainScreen as TuiMainScreen3 } from "@earendil-works/pi-tui";
45743
+ import { ProcessTerminal as ProcessTerminal3, setCapabilityOverrides as setCapabilityOverrides3, setKeybindings as setKeybindings3, TuiMainScreen as TuiMainScreen3 } from "@earendil-works/pi-tui";
45574
45744
  import chalk10 from "chalk";
45575
45745
  var init_main_session = __esm(() => {
45576
45746
  init_session_picker();
@@ -48388,7 +48558,7 @@ var init_slash_commands = __esm(() => {
48388
48558
  { name: "tree", description: "Navigate session tree (switch branches)" },
48389
48559
  { name: "thinking", description: "Set thinking level", argumentHint: "<level>" },
48390
48560
  { name: "scoped-models", description: "Enable/disable models for ctrl+p cycling" },
48391
- { name: "fast", description: "Configure OpenAI fast mode for chat and workflows in supported models" },
48561
+ { name: "fast", description: "Configure fast mode for chat and workflows on supported models" },
48392
48562
  { name: "export", description: "Export session (HTML default, or specify path: .html/.jsonl)" },
48393
48563
  { name: "import", description: "Import and resume a session from a JSONL file" },
48394
48564
  { name: "share", description: "Share session as a secret GitHub gist" },
@@ -49014,6 +49184,7 @@ function createFullscreenTui(options) {
49014
49184
  openUrl: openBrowser
49015
49185
  }),
49016
49186
  onRightClickPaste: options.onRightClickPaste,
49187
+ copyOnSelect: options.copyOnSelect,
49017
49188
  copySelection: options.copySelection ?? copySelectionToHostClipboard
49018
49189
  }, options.shouldHandleViewportInput, options.onOverlayUnhandledInput);
49019
49190
  }
@@ -49055,7 +49226,7 @@ function createInteractiveTuiReference(getTui) {
49055
49226
  getPrototypeOf: () => Reflect.getPrototypeOf(getTui())
49056
49227
  });
49057
49228
  }
49058
- var viewportInputListeners, viewportInputGates, overlayUnhandledInputHandlers, viewportInputReplays, viewportInputSubscriptions, SGR_MOUSE_SEQUENCE, LEFT_MOUSE_MODIFIER_MASK, AtomicTuiAltScreen, AtomicTuiMainScreen;
49229
+ var viewportInputListeners, viewportInputGates, overlayUnhandledInputHandlers, viewportInputReplays, overlayOwnedSelections, viewportInputSubscriptions, SGR_MOUSE_SEQUENCE, LEFT_MOUSE_MODIFIER_MASK, AtomicTuiAltScreen, AtomicTuiMainScreen;
49059
49230
  var init_interactive_tui = __esm(() => {
49060
49231
  init_clipboard();
49061
49232
  init_open_browser();
@@ -49064,6 +49235,7 @@ var init_interactive_tui = __esm(() => {
49064
49235
  viewportInputGates = new WeakMap;
49065
49236
  overlayUnhandledInputHandlers = new WeakMap;
49066
49237
  viewportInputReplays = new WeakSet;
49238
+ overlayOwnedSelections = new WeakSet;
49067
49239
  viewportInputSubscriptions = new WeakMap;
49068
49240
  SGR_MOUSE_SEQUENCE = /^\x1b\[<(\d+);\d+;\d+([Mm])/;
49069
49241
  LEFT_MOUSE_MODIFIER_MASK = 4 | 8 | 16;
@@ -49079,8 +49251,20 @@ var init_interactive_tui = __esm(() => {
49079
49251
  deferral.shouldDeferViewportInputToOverlay = () => !viewportInputReplays.has(this) && deferToOverlay?.() === true;
49080
49252
  }
49081
49253
  applyLineResets(lines) {
49254
+ if (overlayOwnedSelections.has(this) && !this.isFocusedOverlay())
49255
+ this.clearOverlayOwnedSelection();
49082
49256
  return stripOverlayActiveRowMarker(super.applyLineResets(lines));
49083
49257
  }
49258
+ clearOverlayOwnedSelection() {
49259
+ const selection = this;
49260
+ selection.selectionAnchor = undefined;
49261
+ selection.selectionFocus = undefined;
49262
+ selection.selectionInitialRange = undefined;
49263
+ selection.selectionPressActive = false;
49264
+ selection.selectionDragged = false;
49265
+ selection.lastClick = undefined;
49266
+ overlayOwnedSelections.delete(this);
49267
+ }
49084
49268
  isPiTuiMouseSequence(data) {
49085
49269
  if (parseMouseSequences(data))
49086
49270
  return true;
@@ -49157,6 +49341,7 @@ var init_interactive_tui = __esm(() => {
49157
49341
  if (isLeftMouseButton(sequence))
49158
49342
  viewportListener(sequence.data);
49159
49343
  }
49344
+ overlayOwnedSelections.add(this);
49160
49345
  }
49161
49346
  replayViewportInput(viewportListener, data) {
49162
49347
  viewportInputReplays.add(this);
@@ -49224,7 +49409,11 @@ var init_interactive_tui = __esm(() => {
49224
49409
  });
49225
49410
 
49226
49411
  // src/modes/interactive/interactive-mode-base.ts
49227
- import { isKeyRelease as isKeyRelease3, isViewportTUI } from "@earendil-works/pi-tui";
49412
+ import {
49413
+ isKeyRelease as isKeyRelease3,
49414
+ isViewportTUI,
49415
+ setCapabilityOverrides as setCapabilityOverrides4
49416
+ } from "@earendil-works/pi-tui";
49228
49417
  function isFullscreenViewportAction(data, keybindings) {
49229
49418
  return FULLSCREEN_VIEWPORT_ACTIONS.some((action) => keybindings.matches(data, action));
49230
49419
  }
@@ -49285,6 +49474,18 @@ class InteractiveModeBase {
49285
49474
  return false;
49286
49475
  return this.defaultEditor.handleInput(data);
49287
49476
  }
49477
+ setFullscreenCopyOnSelect(enabled) {
49478
+ if (this.renderer.mode === "fullscreen")
49479
+ this.renderer.setCopyOnSelect(enabled);
49480
+ }
49481
+ getFullscreenCopyOnSelect() {
49482
+ return this.renderer.mode === "fullscreen" ? this.renderer.getCopyOnSelect() : undefined;
49483
+ }
49484
+ async copyActiveFullscreenSelection() {
49485
+ if (this.renderer.mode !== "fullscreen" || !this.renderer.hasActiveSelection())
49486
+ return;
49487
+ return this.renderer.copyActiveSelectionToClipboard();
49488
+ }
49288
49489
  onRightClickPaste = () => {
49289
49490
  this.handleRightClickPaste();
49290
49491
  };
@@ -49484,11 +49685,13 @@ class InteractiveModeBase {
49484
49685
  await this.rebindCurrentSession();
49485
49686
  await this.themeController.applyFromSettings();
49486
49687
  });
49688
+ setCapabilityOverrides4(this.settingsManager.getTerminalCapabilityOverrides());
49487
49689
  this.version = VERSION;
49488
49690
  this.renderer = createInteractiveTui({
49489
49691
  showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
49490
49692
  logDirectory: runtimeHost.services.agentDir,
49491
49693
  terminal: options.terminal,
49694
+ copyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
49492
49695
  onRightClickPaste: this.onRightClickPaste,
49493
49696
  shouldHandleViewportInput: this.shouldHandleViewportInput,
49494
49697
  onOverlayUnhandledInput: this.onOverlayUnhandledInput,
@@ -50611,6 +50814,7 @@ var init_interactive_deferred_startup = __esm(() => {
50611
50814
  try {
50612
50815
  await this.bindCurrentSessionExtensions();
50613
50816
  await this.session.reload({ reason: "startup" });
50817
+ this.applyRuntimeSettings();
50614
50818
  this.rebuildChatFromMessages();
50615
50819
  if (!this.promptTurnWorkingLoaderActive) {
50616
50820
  this.stopWorkingLoader();
@@ -51299,6 +51503,7 @@ ${warningLines}`, 0, 0));
51299
51503
  });
51300
51504
 
51301
51505
  // src/modes/interactive/interactive-session-runtime.ts
51506
+ import { setCapabilityOverrides as setCapabilityOverrides5 } from "@earendil-works/pi-tui";
51302
51507
  var init_interactive_session_runtime = __esm(() => {
51303
51508
  init_interactive_mode_base();
51304
51509
  init_interactive_mode_deps();
@@ -51385,6 +51590,8 @@ var init_interactive_session_runtime = __esm(() => {
51385
51590
  }
51386
51591
  };
51387
51592
  InteractiveModeBase.prototype.applyRuntimeSettings = function() {
51593
+ setCapabilityOverrides5(this.settingsManager.getTerminalCapabilityOverrides());
51594
+ this.setFullscreenCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect());
51388
51595
  this.transcriptScrollView?.setScrollbar(this.settingsManager.getFullscreenScrollbar());
51389
51596
  this.footer.setSession(this.session);
51390
51597
  this.usageMeter.setSession(this.session);
@@ -51454,7 +51661,7 @@ var init_interactive_extension_runtime = __esm(() => {
51454
51661
  if (shortcuts.size === 0)
51455
51662
  return;
51456
51663
  const createContext = () => ({
51457
- ui: this.createExtensionUIContext(),
51664
+ ui: extensionRunner.getUIContext(),
51458
51665
  mode: "tui",
51459
51666
  hasUI: true,
51460
51667
  cwd: this.sessionManager.getCwd(),
@@ -52901,6 +53108,9 @@ var init_interactive_input_handling = __esm(() => {
52901
53108
  });
52902
53109
  this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
52903
53110
  this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
53111
+ this.defaultEditor.onAction("app.message.copy", () => {
53112
+ this.handleCopyCommand({ preferSelection: true });
53113
+ });
52904
53114
  this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
52905
53115
  this.defaultEditor.onAction("app.session.tree", () => this.showTreeSelector());
52906
53116
  this.defaultEditor.onAction("app.session.fork", () => this.showUserMessageSelector());
@@ -53808,7 +54018,8 @@ var init_interactive_agent_events = __esm(() => {
53808
54018
  } else if (event.reason === "manual") {
53809
54019
  this.manualCompactionTakeoverPending = false;
53810
54020
  }
53811
- if (!manualTakeoverPending && this.settingsManager.getShowTerminalProgress()) {
54021
+ const resumesActiveRun = event.midTurn && !event.aborted && !event.errorMessage && !manualTakeoverPending;
54022
+ if (!manualTakeoverPending && !resumesActiveRun && this.settingsManager.getShowTerminalProgress()) {
53812
54023
  this.ui.terminal.setProgress(false);
53813
54024
  }
53814
54025
  if (!manualTakeoverPending && this.autoCompactionEscapeHandlerSaved) {
@@ -54824,7 +55035,7 @@ var init_interactive_selectors = __esm(() => {
54824
55035
  };
54825
55036
  InteractiveModeBase.prototype.showFastModeSelector = function() {
54826
55037
  if (!this.hasCodexFastModeSupportedModels()) {
54827
- this.showWarning("Codex fast mode requires a supported OpenAI or shared ChatGPT Codex transport model.");
55038
+ this.showWarning("Fast mode isn't available for any configured model.");
54828
55039
  return;
54829
55040
  }
54830
55041
  this.showSelector((done) => {
@@ -54883,6 +55094,7 @@ var init_interactive_selectors = __esm(() => {
54883
55094
  showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
54884
55095
  fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
54885
55096
  fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
55097
+ fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
54886
55098
  editorPaddingX: this.settingsManager.getEditorPaddingX(),
54887
55099
  outputPad: this.settingsManager.getOutputPad(),
54888
55100
  showCacheMissNotices: this.settingsManager.getShowCacheMissNotices(),
@@ -55000,6 +55212,10 @@ var init_interactive_selectors = __esm(() => {
55000
55212
  onFullscreenExitOutputChange: (output) => {
55001
55213
  this.settingsManager.setFullscreenExitOutput(output);
55002
55214
  },
55215
+ onFullscreenCopyOnSelectChange: (enabled) => {
55216
+ this.settingsManager.setFullscreenCopyOnSelect(enabled);
55217
+ this.setFullscreenCopyOnSelect(enabled);
55218
+ },
55003
55219
  onEditorPaddingXChange: (padding) => {
55004
55220
  this.settingsManager.setEditorPaddingX(padding);
55005
55221
  this.defaultEditor.setPaddingX(padding);
@@ -55986,18 +56202,8 @@ var init_interactive_slash_commands = __esm(() => {
55986
56202
  activeHeader.setExpanded(this.toolOutputExpanded);
55987
56203
  }
55988
56204
  setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
55989
- this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
56205
+ this.applyRuntimeSettings();
55990
56206
  await this.themeController.applyFromSettings();
55991
- const editorPaddingX = this.settingsManager.getEditorPaddingX();
55992
- const autocompleteMaxVisible = this.settingsManager.getAutocompleteMaxVisible();
55993
- this.defaultEditor.setPaddingX(editorPaddingX);
55994
- this.defaultEditor.setAutocompleteMaxVisible(autocompleteMaxVisible);
55995
- if (this.editor !== this.defaultEditor) {
55996
- this.editor.setPaddingX?.(editorPaddingX);
55997
- this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible);
55998
- }
55999
- this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());
56000
- this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
56001
56207
  this.setupAutocompleteProvider();
56002
56208
  const runner = this.session.extensionRunner;
56003
56209
  this.setupExtensionShortcuts(runner);
@@ -56190,7 +56396,12 @@ Gist: ${hyperlink3(gistUrl, gistUrl)}`);
56190
56396
  }
56191
56397
  }
56192
56398
  };
56193
- InteractiveModeBase.prototype.handleCopyCommand = async function() {
56399
+ InteractiveModeBase.prototype.handleCopyCommand = async function(options = {}) {
56400
+ if (options.preferSelection && this.getFullscreenCopyOnSelect() === false) {
56401
+ const selectionCopied = await this.copyActiveFullscreenSelection();
56402
+ if (selectionCopied !== undefined)
56403
+ return;
56404
+ }
56194
56405
  const text = this.session.getLastAssistantText();
56195
56406
  if (!text) {
56196
56407
  this.showError("No agent messages to copy yet.");
@@ -56737,6 +56948,7 @@ var init_rpc_extension_ui = __esm(() => {
56737
56948
  });
56738
56949
 
56739
56950
  // src/modes/rpc/rpc-session-binding.ts
56951
+ import { setCapabilityOverrides as setCapabilityOverrides6 } from "@earendil-works/pi-tui";
56740
56952
  var init_rpc_session_binding = __esm(() => {
56741
56953
  init_footer_data_provider();
56742
56954
  init_output_guard();
@@ -56813,7 +57025,7 @@ var init_config_selector = __esm(() => {
56813
57025
  });
56814
57026
 
56815
57027
  // src/cli/config-selector.ts
56816
- import { ProcessTerminal as ProcessTerminal6, TuiMainScreen as TuiMainScreen8 } from "@earendil-works/pi-tui";
57028
+ import { ProcessTerminal as ProcessTerminal6, setCapabilityOverrides as setCapabilityOverrides7, TuiMainScreen as TuiMainScreen8 } from "@earendil-works/pi-tui";
56817
57029
  var init_config_selector2 = __esm(() => {
56818
57030
  init_config_selector();
56819
57031
  init_theme();
@@ -56860,6 +57072,7 @@ var init_package_manager_cli = __esm(() => {
56860
57072
  });
56861
57073
 
56862
57074
  // src/main.ts
57075
+ import { setCapabilityOverrides as setCapabilityOverrides8 } from "@earendil-works/pi-tui";
56863
57076
  import chalk15 from "chalk";
56864
57077
  var init_main = __esm(() => {
56865
57078
  init_args();
@@ -56874,6 +57087,7 @@ var init_main = __esm(() => {
56874
57087
  init_auth_storage();
56875
57088
  init_builtin_packages();
56876
57089
  init_http_dispatcher();
57090
+ init_mandatory_resource_loader();
56877
57091
  init_model_resolver();
56878
57092
  init_model_runtime();
56879
57093
  init_output_guard();
@@ -57309,6 +57523,59 @@ function isSessionInfo(value) {
57309
57523
  return session.status === undefined || typeof session.status === "string";
57310
57524
  }
57311
57525
 
57526
+ // dist/builtin/intercom/group.ts
57527
+ function intercomGroupFromEnv() {
57528
+ return process.env.ATOMIC_INTERCOM_GROUP ?? process.env.PI_INTERCOM_GROUP;
57529
+ }
57530
+ function normalizeGroup(value) {
57531
+ if (typeof value !== "string")
57532
+ return DEFAULT_GROUP;
57533
+ const trimmed = value.trim();
57534
+ return trimmed.length > 0 ? trimmed : DEFAULT_GROUP;
57535
+ }
57536
+ function normalizeGroups(values, legacyGroup) {
57537
+ const groups = new Set;
57538
+ for (const value of values ?? [])
57539
+ groups.add(normalizeGroup(value));
57540
+ if (legacyGroup !== undefined)
57541
+ groups.add(normalizeGroup(legacyGroup));
57542
+ if (groups.size === 0)
57543
+ groups.add(DEFAULT_GROUP);
57544
+ return groups;
57545
+ }
57546
+ function validateRuntimeGroup(value) {
57547
+ if (typeof value !== "string" || value.trim().length === 0) {
57548
+ throw new Error("A non-empty intercom group name is required");
57549
+ }
57550
+ const group = normalizeGroup(value);
57551
+ if (RESERVED_RUNTIME_GROUPS.has(group.toLowerCase())) {
57552
+ throw new Error(`Intercom group name "${group}" is reserved; choose another name`);
57553
+ }
57554
+ return group;
57555
+ }
57556
+ function resolveHomeGroup(config, ctx) {
57557
+ const fromPolicy = ctx?.subagentPolicy?.intercomGroup;
57558
+ if (typeof fromPolicy === "string" && fromPolicy.trim().length > 0) {
57559
+ return normalizeGroup(fromPolicy);
57560
+ }
57561
+ const fromContext = ctx?.orchestrationContext?.intercomGroup;
57562
+ if (typeof fromContext === "string" && fromContext.trim().length > 0) {
57563
+ return normalizeGroup(fromContext);
57564
+ }
57565
+ const fromEnv = intercomGroupFromEnv();
57566
+ if (typeof fromEnv === "string" && fromEnv.trim().length > 0) {
57567
+ return normalizeGroup(fromEnv);
57568
+ }
57569
+ if (config && typeof config.group === "string" && config.group.trim().length > 0) {
57570
+ return normalizeGroup(config.group);
57571
+ }
57572
+ return DEFAULT_GROUP;
57573
+ }
57574
+ var DEFAULT_GROUP = "default", RESERVED_RUNTIME_GROUPS;
57575
+ var init_group = __esm(() => {
57576
+ RESERVED_RUNTIME_GROUPS = new Set(["true", "auto"]);
57577
+ });
57578
+
57312
57579
  // dist/builtin/intercom/broker/client.ts
57313
57580
  import { EventEmitter as EventEmitter2 } from "events";
57314
57581
  import net from "net";
@@ -57316,10 +57583,11 @@ import { randomUUID as randomUUID8 } from "crypto";
57316
57583
  function toError(error) {
57317
57584
  return error instanceof Error ? error : new Error(String(error));
57318
57585
  }
57319
- var BROKER_SOCKET, PRESENCE_ACK_TIMEOUT_MS = 5000, IntercomClient;
57586
+ var BROKER_SOCKET, GROUP_REQUEST_TIMEOUT_MS = 5000, PRESENCE_ACK_TIMEOUT_MS = 5000, IntercomClient;
57320
57587
  var init_client = __esm(() => {
57321
57588
  init_paths2();
57322
57589
  init_pending_send_registry();
57590
+ init_group();
57323
57591
  BROKER_SOCKET = getBrokerSocketPath();
57324
57592
  IntercomClient = class IntercomClient extends EventEmitter2 {
57325
57593
  returnAddress;
@@ -57328,8 +57596,11 @@ var init_client = __esm(() => {
57328
57596
  _supervisorSessionId = null;
57329
57597
  _messageSource;
57330
57598
  pendingSends = new PendingSendRegistry;
57599
+ pendingGroupLists = new Map;
57331
57600
  pendingLists = new Map;
57332
57601
  pendingPresence = new Map;
57602
+ pendingMemberships = new Map;
57603
+ _groups = normalizeGroups();
57333
57604
  pendingLiveWorkflowStageRoutes = new Map;
57334
57605
  pendingSupervisorAuthorizations = new Map;
57335
57606
  disconnecting = false;
@@ -57342,17 +57613,23 @@ var init_client = __esm(() => {
57342
57613
  }
57343
57614
  failPending(error) {
57344
57615
  this.pendingSends.rejectAll(error);
57616
+ for (const pending of this.pendingGroupLists.values())
57617
+ pending.reject(error);
57345
57618
  for (const pending of this.pendingLists.values())
57346
57619
  pending.reject(error);
57347
57620
  for (const pending of this.pendingSupervisorAuthorizations.values())
57348
57621
  pending.reject(error);
57349
57622
  for (const pending of this.pendingPresence.values())
57350
57623
  pending.reject(error);
57624
+ for (const pending of this.pendingMemberships.values())
57625
+ pending.reject(error);
57351
57626
  for (const pending of this.pendingLiveWorkflowStageRoutes.values())
57352
57627
  pending.reject(error);
57353
57628
  this.pendingLists.clear();
57629
+ this.pendingGroupLists.clear();
57354
57630
  this.pendingSupervisorAuthorizations.clear();
57355
57631
  this.pendingPresence.clear();
57632
+ this.pendingMemberships.clear();
57356
57633
  this.pendingLiveWorkflowStageRoutes.clear();
57357
57634
  }
57358
57635
  get sessionId() {
@@ -57361,6 +57638,9 @@ var init_client = __esm(() => {
57361
57638
  get supervisorSessionId() {
57362
57639
  return this._supervisorSessionId;
57363
57640
  }
57641
+ get groups() {
57642
+ return [...this._groups];
57643
+ }
57364
57644
  isConnected() {
57365
57645
  const socket = this.socket;
57366
57646
  return Boolean(socket && this._sessionId && !this.disconnecting && !socket.destroyed && !socket.writableEnded && socket.writable);
@@ -57383,6 +57663,7 @@ var init_client = __esm(() => {
57383
57663
  return Promise.reject(new Error("Already connected"));
57384
57664
  }
57385
57665
  this._messageSource = messageSource ?? readSubagentMessageSource();
57666
+ this._groups = normalizeGroups(session.groups, session.group);
57386
57667
  return new Promise((resolve15, reject) => {
57387
57668
  const socket = net.connect(BROKER_SOCKET);
57388
57669
  this.socket = socket;
@@ -57534,6 +57815,18 @@ var init_client = __esm(() => {
57534
57815
  pending.resolve(sessions);
57535
57816
  break;
57536
57817
  }
57818
+ case "groups": {
57819
+ const { requestId, groups } = brokerMessage;
57820
+ if (typeof requestId !== "string" || !Array.isArray(groups) || !groups.every((summary) => typeof summary === "object" && summary !== null && typeof summary.group === "string" && typeof summary.sessionCount === "number" && typeof summary.member === "boolean")) {
57821
+ throw new Error("Invalid groups message");
57822
+ }
57823
+ const pending = this.pendingGroupLists.get(requestId);
57824
+ if (!pending)
57825
+ return;
57826
+ this.pendingGroupLists.delete(requestId);
57827
+ pending.resolve(groups);
57828
+ break;
57829
+ }
57537
57830
  case "supervisor_authorized": {
57538
57831
  const { requestId, capability, supervisorSessionId, childName } = brokerMessage;
57539
57832
  if (typeof requestId !== "string" || typeof capability !== "string" || typeof supervisorSessionId !== "string" || typeof childName !== "string") {
@@ -57664,18 +57957,39 @@ var init_client = __esm(() => {
57664
57957
  if (!pending)
57665
57958
  return;
57666
57959
  this.pendingPresence.delete(brokerMessage.requestId);
57960
+ this._groups = pending.groups === undefined ? normalizeGroups(undefined, brokerMessage.group) : normalizeGroups(pending.groups);
57667
57961
  pending.resolve(brokerMessage.group);
57668
57962
  break;
57669
57963
  }
57964
+ case "membership_ack": {
57965
+ const { requestId, groups } = brokerMessage;
57966
+ if (typeof requestId !== "string" || !Array.isArray(groups) || !groups.every((group) => typeof group === "string")) {
57967
+ throw new Error("Invalid membership_ack message");
57968
+ }
57969
+ const pending = this.pendingMemberships.get(requestId);
57970
+ if (!pending)
57971
+ return;
57972
+ this.pendingMemberships.delete(requestId);
57973
+ const normalizedGroups = [...normalizeGroups(groups)];
57974
+ this._groups = new Set(normalizedGroups);
57975
+ pending.resolve(normalizedGroups);
57976
+ break;
57977
+ }
57670
57978
  case "presence_failed": {
57671
57979
  if (typeof brokerMessage.requestId !== "string" || typeof brokerMessage.reason !== "string") {
57672
57980
  throw new Error("Invalid presence_failed message");
57673
57981
  }
57674
- const pending = this.pendingPresence.get(brokerMessage.requestId);
57675
- if (!pending)
57982
+ const presence = this.pendingPresence.get(brokerMessage.requestId);
57983
+ if (presence) {
57984
+ this.pendingPresence.delete(brokerMessage.requestId);
57985
+ presence.reject(new Error(brokerMessage.reason));
57986
+ break;
57987
+ }
57988
+ const membership = this.pendingMemberships.get(brokerMessage.requestId);
57989
+ if (!membership)
57676
57990
  return;
57677
- this.pendingPresence.delete(brokerMessage.requestId);
57678
- pending.reject(new Error(brokerMessage.reason));
57991
+ this.pendingMemberships.delete(brokerMessage.requestId);
57992
+ membership.reject(new Error(brokerMessage.reason));
57679
57993
  break;
57680
57994
  }
57681
57995
  case "peer_disconnected": {
@@ -57771,6 +58085,78 @@ var init_client = __esm(() => {
57771
58085
  }
57772
58086
  });
57773
58087
  }
58088
+ listGroups() {
58089
+ let socket;
58090
+ try {
58091
+ socket = this.requireActiveSocket();
58092
+ } catch (error) {
58093
+ return Promise.reject(toError(error));
58094
+ }
58095
+ const requestId = randomUUID8();
58096
+ return new Promise((resolve15, reject) => {
58097
+ const timeout = setTimeout(() => {
58098
+ if (!this.pendingGroupLists.delete(requestId))
58099
+ return;
58100
+ reject(new Error("List groups timeout"));
58101
+ }, GROUP_REQUEST_TIMEOUT_MS);
58102
+ this.pendingGroupLists.set(requestId, {
58103
+ resolve: (groups) => {
58104
+ clearTimeout(timeout);
58105
+ resolve15(groups);
58106
+ },
58107
+ reject: (error) => {
58108
+ clearTimeout(timeout);
58109
+ reject(error);
58110
+ }
58111
+ });
58112
+ try {
58113
+ writeMessage(socket, { type: "list_groups", requestId });
58114
+ } catch (error) {
58115
+ clearTimeout(timeout);
58116
+ this.pendingGroupLists.delete(requestId);
58117
+ reject(toError(error));
58118
+ }
58119
+ });
58120
+ }
58121
+ joinGroup(group) {
58122
+ return this.updateMembership("join_group", group);
58123
+ }
58124
+ leaveGroup(group) {
58125
+ return this.updateMembership("leave_group", group);
58126
+ }
58127
+ updateMembership(type, group) {
58128
+ let socket;
58129
+ try {
58130
+ socket = this.requireActiveSocket();
58131
+ } catch (error) {
58132
+ return Promise.reject(toError(error));
58133
+ }
58134
+ const requestId = randomUUID8();
58135
+ return new Promise((resolve15, reject) => {
58136
+ const timeout = setTimeout(() => {
58137
+ if (!this.pendingMemberships.delete(requestId))
58138
+ return;
58139
+ reject(new Error("Membership update timeout"));
58140
+ }, GROUP_REQUEST_TIMEOUT_MS);
58141
+ this.pendingMemberships.set(requestId, {
58142
+ resolve: (groups) => {
58143
+ clearTimeout(timeout);
58144
+ resolve15(groups);
58145
+ },
58146
+ reject: (error) => {
58147
+ clearTimeout(timeout);
58148
+ reject(error);
58149
+ }
58150
+ });
58151
+ try {
58152
+ writeMessage(socket, group === undefined ? { type, requestId } : { type, requestId, group });
58153
+ } catch (error) {
58154
+ clearTimeout(timeout);
58155
+ this.pendingMemberships.delete(requestId);
58156
+ reject(toError(error));
58157
+ }
58158
+ });
58159
+ }
57774
58160
  authorizeSupervisorChild(childName, capability) {
57775
58161
  let socket;
57776
58162
  try {
@@ -57902,6 +58288,10 @@ var init_client = __esm(() => {
57902
58288
  return false;
57903
58289
  }
57904
58290
  writeMessage(socket, { type: "presence", ...updates });
58291
+ if (updates.groups !== undefined)
58292
+ this._groups = normalizeGroups(updates.groups, updates.group);
58293
+ else if (updates.group !== undefined)
58294
+ this._groups = normalizeGroups(undefined, updates.group);
57905
58295
  return true;
57906
58296
  }
57907
58297
  updatePresenceAcked(updates) {
@@ -57926,7 +58316,11 @@ var init_client = __esm(() => {
57926
58316
  return;
57927
58317
  reject(new Error("Presence update timeout"));
57928
58318
  }, PRESENCE_ACK_TIMEOUT_MS);
57929
- this.pendingPresence.set(requestId, { resolve: wrappedResolve, reject: wrappedReject });
58319
+ this.pendingPresence.set(requestId, {
58320
+ resolve: wrappedResolve,
58321
+ reject: wrappedReject,
58322
+ ...updates.groups === undefined ? {} : { groups: [...updates.groups] }
58323
+ });
57930
58324
  try {
57931
58325
  writeMessage(socket, { type: "presence", ...updates, requestId });
57932
58326
  } catch (error) {
@@ -58477,12 +58871,6 @@ function loadConfig2() {
58477
58871
  }
58478
58872
  config.maxPendingAsks = Number(parsedConfig.maxPendingAsks);
58479
58873
  }
58480
- if (Object.hasOwn(parsedConfig, "enabled")) {
58481
- if (typeof parsedConfig.enabled !== "boolean") {
58482
- throw new Error(`"enabled" must be a boolean`);
58483
- }
58484
- config.enabled = parsedConfig.enabled;
58485
- }
58486
58874
  if (Object.hasOwn(parsedConfig, "replyHint")) {
58487
58875
  if (typeof parsedConfig.replyHint !== "boolean") {
58488
58876
  throw new Error(`"replyHint" must be a boolean`);
@@ -58519,7 +58907,6 @@ var init_config3 = __esm(() => {
58519
58907
  brokerArgs: [...DEFAULT_BROKER_ARGS],
58520
58908
  confirmSend: false,
58521
58909
  maxPendingAsks: DEFAULT_MAX_PENDING_REPLY_WAITS,
58522
- enabled: true,
58523
58910
  replyHint: true
58524
58911
  };
58525
58912
  });
@@ -58705,49 +59092,6 @@ var init_parent_ask_handoff = __esm(() => {
58705
59092
  PROCESS_PARENT_ASK_CLAIMS = Symbol.for("atomic/subagents/parent-ask-claims@1");
58706
59093
  });
58707
59094
 
58708
- // dist/builtin/intercom/group.ts
58709
- function intercomGroupFromEnv() {
58710
- return process.env.ATOMIC_INTERCOM_GROUP ?? process.env.PI_INTERCOM_GROUP;
58711
- }
58712
- function normalizeGroup(value) {
58713
- if (typeof value !== "string")
58714
- return DEFAULT_GROUP;
58715
- const trimmed = value.trim();
58716
- return trimmed.length > 0 ? trimmed : DEFAULT_GROUP;
58717
- }
58718
- function validateRuntimeGroup(value) {
58719
- if (typeof value !== "string" || value.trim().length === 0) {
58720
- throw new Error("A non-empty intercom group name is required");
58721
- }
58722
- const group = normalizeGroup(value);
58723
- if (RESERVED_RUNTIME_GROUPS.has(group.toLowerCase())) {
58724
- throw new Error(`Intercom group name "${group}" is reserved; choose another name`);
58725
- }
58726
- return group;
58727
- }
58728
- function resolveHomeGroup(config, ctx) {
58729
- const fromPolicy = ctx?.subagentPolicy?.intercomGroup;
58730
- if (typeof fromPolicy === "string" && fromPolicy.trim().length > 0) {
58731
- return normalizeGroup(fromPolicy);
58732
- }
58733
- const fromContext = ctx?.orchestrationContext?.intercomGroup;
58734
- if (typeof fromContext === "string" && fromContext.trim().length > 0) {
58735
- return normalizeGroup(fromContext);
58736
- }
58737
- const fromEnv = intercomGroupFromEnv();
58738
- if (typeof fromEnv === "string" && fromEnv.trim().length > 0) {
58739
- return normalizeGroup(fromEnv);
58740
- }
58741
- if (config && typeof config.group === "string" && config.group.trim().length > 0) {
58742
- return normalizeGroup(config.group);
58743
- }
58744
- return DEFAULT_GROUP;
58745
- }
58746
- var DEFAULT_GROUP = "default", RESERVED_RUNTIME_GROUPS;
58747
- var init_group = __esm(() => {
58748
- RESERVED_RUNTIME_GROUPS = new Set(["true", "auto"]);
58749
- });
58750
-
58751
59095
  // dist/builtin/intercom/intercom-utils.ts
58752
59096
  function getErrorMessage(error) {
58753
59097
  return error instanceof Error ? error.message : String(error);
@@ -59420,23 +59764,25 @@ workflow stage, use the exact \`<runId>:<stageKey>\` target; send messages to pe
59420
59764
  queue automatically.
59421
59765
 
59422
59766
  Usage:
59423
- intercom({ action: "list" }) → List sessions in your group
59424
- intercom({ action: "list", group: "name" }) → Read-only peek at another group's sessions
59425
- intercom({ action: "join", group: "name" }) Join or create a named group
59767
+ intercom({ action: "list" }) → List sessions visible through your groups
59768
+ intercom({ action: "list", group: "name" }) → Read-only peek at one group's sessions
59769
+ intercom({ action: "groups" }) Discover every available group and your memberships
59770
+ intercom({ action: "join", group: "name" }) → Add a named group membership
59771
+ intercom({ action: "leave", group: "name" }) → Leave one named group
59426
59772
  intercom({ action: "leave" }) → Return to your resolved home group
59427
- intercom({ action: "send", to: "session-name", message: "..." }) → Send message (own group only)
59773
+ intercom({ action: "send", to: "session-name", message: "..." }) → Send message (shared group only)
59428
59774
  intercom({ action: "ask", to: "session-name", message: "..." }) → Ask and wait for reply
59429
59775
  intercom({ action: "reply", message: "..." }) → Reply to the active or exact pending ask
59430
59776
  intercom({ action: "pending" }) → List unresolved inbound asks
59431
- intercom({ action: "status" }) → Show connection status and your group
59777
+ intercom({ action: "status" }) → Show connection status and all your groups
59432
59778
 
59433
- The "join" action changes this session's group in place. "default" is the shared
59434
- default group; "true" and "auto" are reserved for subagent auto-groups. Joining
59435
- does not grant cross-group access: contact_supervisor is the only cross-group path.`,
59436
- promptSnippet: "Use to coordinate with other local agent sessions in your intercom group: list peers, send updates, ask for help, or check intercom connectivity. Groups are isolated; you can only message sessions in your own group.",
59779
+ The "join" action is additive. "default" is the shared default group; "true" and
59780
+ "auto" are reserved for subagent auto-groups. Ordinary delivery requires at least
59781
+ one shared membership; contact_supervisor remains the only cross-group path.`,
59782
+ promptSnippet: "Use to coordinate with other local agent sessions that share an intercom group: discover groups or peers, send updates, ask for help, or check connectivity. Ordinary messages require a shared membership.",
59437
59783
  parameters: Type14.Object({
59438
59784
  action: Type14.String({
59439
- description: "Action: 'list', 'join', 'leave', 'send', 'ask', 'reply', 'pending', or 'status'"
59785
+ description: "Action: 'list', 'groups', 'join', 'leave', 'send', 'ask', 'reply', 'pending', or 'status'"
59440
59786
  }),
59441
59787
  to: Type14.Optional(Type14.String({
59442
59788
  description: "Live session name, exact full session ID, or exact `<runId>:<stageKey>` for a known workflow stage; send messages to pending stages queue automatically (for 'send', 'ask', or targeted 'reply')"
@@ -59454,7 +59800,7 @@ does not grant cross-group access: contact_supervisor is the only cross-group pa
59454
59800
  description: "Exact pending-ask message ID; disambiguates concurrent asks, including asks from one sender"
59455
59801
  })),
59456
59802
  group: Type14.Optional(Type14.String({
59457
- description: "Group name for 'join'; read-only group filter for 'list'/'status'. 'send'/'ask' are locked to your own group."
59803
+ description: "Group name for 'join' or optional targeted 'leave'; read-only group filter for 'list'/'status'. 'send'/'ask' use shared memberships."
59458
59804
  }))
59459
59805
  }),
59460
59806
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
@@ -59470,17 +59816,20 @@ does not grant cross-group access: contact_supervisor is the only cross-group pa
59470
59816
  }
59471
59817
  syncPresenceIdentity(ctx.sessionManager.getSessionId());
59472
59818
  const { action, to, message, attachments, replyTo, group } = params;
59473
- const requestedGroup = typeof group === "string" && group.trim() ? normalizeGroup(group) : undefined;
59474
- const resolveOwnGroup = async () => {
59475
- const sessions = await connectedClient.listSessions();
59476
- const self = sessions.find((s) => s.id === connectedClient.sessionId);
59477
- return normalizeGroup(self?.group);
59819
+ const resolveOwnGroups = (sessions) => {
59820
+ if (Array.isArray(connectedClient.groups)) {
59821
+ return connectedClient.groups.map((membership) => normalizeGroup(membership));
59822
+ }
59823
+ const self = sessions?.find((session) => session.id === connectedClient.sessionId);
59824
+ return [...normalizeGroups(self?.groups, self?.group)];
59478
59825
  };
59826
+ const isOnlyOwnGroup = (candidate, ownGroups) => candidate !== undefined && ownGroups.length === 1 && ownGroups[0] === candidate;
59827
+ const requestedGroup = typeof group === "string" && group.trim() ? normalizeGroup(group) : undefined;
59479
59828
  if ((action === "send" || action === "ask") && requestedGroup) {
59480
- const ownGroup = await resolveOwnGroup();
59481
- if (requestedGroup !== ownGroup) {
59829
+ const ownGroups = resolveOwnGroups();
59830
+ if (!ownGroups.includes(requestedGroup)) {
59482
59831
  return {
59483
- content: [{ type: "text", text: `The 'group' parameter is read-only for 'list'/'status'. '${action}' is always locked to your own group ("${ownGroup}"); it cannot target group "${requestedGroup}".` }],
59832
+ content: [{ type: "text", text: `The 'group' parameter is read-only for 'list'/'status'. '${action}' is always locked to your groups (${ownGroups.join(", ")}); it cannot target group "${requestedGroup}".` }],
59484
59833
  isError: true,
59485
59834
  details: { error: true }
59486
59835
  };
@@ -59499,15 +59848,12 @@ does not grant cross-group access: contact_supervisor is the only cross-group pa
59499
59848
  };
59500
59849
  }
59501
59850
  try {
59502
- const acknowledgedGroup = await connectedClient.updatePresenceAcked({ group: targetGroup });
59503
- if (acknowledgedGroup !== targetGroup) {
59504
- throw new Error(`Broker acknowledged group "${acknowledgedGroup}" instead of "${targetGroup}"`);
59505
- }
59506
- deps.setJoinedGroup(targetGroup);
59851
+ const groups = await connectedClient.joinGroup(targetGroup);
59852
+ deps.setJoinedGroups(groups);
59507
59853
  return {
59508
- content: [{ type: "text", text: `Joined intercom group "${targetGroup}".` }],
59854
+ content: [{ type: "text", text: `Joined intercom group "${targetGroup}". Memberships: ${groups.join(", ")}.` }],
59509
59855
  isError: false,
59510
- details: { group: targetGroup }
59856
+ details: { group: targetGroup, groups }
59511
59857
  };
59512
59858
  } catch (error) {
59513
59859
  return {
@@ -59518,37 +59864,59 @@ does not grant cross-group access: contact_supervisor is the only cross-group pa
59518
59864
  }
59519
59865
  }
59520
59866
  case "leave": {
59521
- if (typeof group === "string" && group.trim().length > 0) {
59867
+ let targetGroup;
59868
+ let homeGroup;
59869
+ try {
59870
+ targetGroup = typeof group === "string" && group.trim().length > 0 ? validateRuntimeGroup(group) : undefined;
59871
+ if (targetGroup === undefined)
59872
+ homeGroup = validateRuntimeGroup(deps.homeGroup());
59873
+ } catch (error) {
59522
59874
  return {
59523
- content: [{ type: "text", text: "The 'leave' action does not accept a group; it returns to the resolved home group." }],
59875
+ content: [{ type: "text", text: `Cannot leave intercom group: ${getErrorMessage(error)}` }],
59524
59876
  isError: true,
59525
59877
  details: { error: true }
59526
59878
  };
59527
59879
  }
59528
- let targetGroup;
59529
59880
  try {
59530
- targetGroup = validateRuntimeGroup(deps.homeGroup());
59881
+ let groups;
59882
+ if (targetGroup === undefined) {
59883
+ if (homeGroup === undefined)
59884
+ throw new Error("Intercom home group is unavailable");
59885
+ await connectedClient.updatePresenceAcked({ groups: [homeGroup] });
59886
+ groups = connectedClient.groups;
59887
+ deps.clearJoinedGroups();
59888
+ } else {
59889
+ groups = await connectedClient.leaveGroup(targetGroup);
59890
+ deps.setJoinedGroups(groups);
59891
+ }
59892
+ const text = targetGroup === undefined ? `Returned to home intercom membership. Memberships: ${groups.join(", ")}.` : `Left intercom group "${targetGroup}". Memberships: ${groups.join(", ")}.`;
59893
+ return {
59894
+ content: [{ type: "text", text }],
59895
+ isError: false,
59896
+ details: targetGroup === undefined ? { group: homeGroup, groups } : { groups }
59897
+ };
59531
59898
  } catch (error) {
59532
59899
  return {
59533
- content: [{ type: "text", text: `Cannot leave intercom group: ${getErrorMessage(error)}` }],
59900
+ content: [{ type: "text", text: `Failed to leave group: ${getErrorMessage(error)}` }],
59534
59901
  isError: true,
59535
59902
  details: { error: true }
59536
59903
  };
59537
59904
  }
59905
+ }
59906
+ case "groups": {
59538
59907
  try {
59539
- const acknowledgedGroup = await connectedClient.updatePresenceAcked({ group: targetGroup });
59540
- if (acknowledgedGroup !== targetGroup) {
59541
- throw new Error(`Broker acknowledged group "${acknowledgedGroup}" instead of "${targetGroup}"`);
59542
- }
59543
- deps.clearJoinedGroup();
59908
+ const groups = await connectedClient.listGroups();
59909
+ const lines = groups.map(({ group: groupName, sessionCount, member }) => `- ${groupName} — ${sessionCount} session${sessionCount === 1 ? "" : "s"}${member ? " [member]" : ""}`);
59544
59910
  return {
59545
- content: [{ type: "text", text: `Returned to home intercom group "${targetGroup}".` }],
59911
+ content: [{ type: "text", text: `**Intercom groups:**
59912
+ ${lines.join(`
59913
+ `)}` }],
59546
59914
  isError: false,
59547
- details: { group: targetGroup }
59915
+ details: { groups }
59548
59916
  };
59549
59917
  } catch (error) {
59550
59918
  return {
59551
- content: [{ type: "text", text: `Failed to leave group: ${getErrorMessage(error)}` }],
59919
+ content: [{ type: "text", text: `Failed to list groups: ${getErrorMessage(error)}` }],
59552
59920
  isError: true,
59553
59921
  details: { error: true }
59554
59922
  };
@@ -59558,7 +59926,7 @@ does not grant cross-group access: contact_supervisor is the only cross-group pa
59558
59926
  try {
59559
59927
  const mySessionId = connectedClient.sessionId;
59560
59928
  const ownSessions = await connectedClient.listSessions();
59561
- const currentSession = ownSessions.find((s) => s.id === mySessionId);
59929
+ const currentSession = ownSessions.find((session) => session.id === mySessionId);
59562
59930
  if (!currentSession) {
59563
59931
  return {
59564
59932
  content: [{ type: "text", text: "Current session is missing from intercom session list." }],
@@ -59566,34 +59934,34 @@ does not grant cross-group access: contact_supervisor is the only cross-group pa
59566
59934
  details: { error: true }
59567
59935
  };
59568
59936
  }
59569
- const ownGroup = normalizeGroup(currentSession.group);
59570
- if (requestedGroup && requestedGroup !== ownGroup) {
59937
+ const ownGroups = resolveOwnGroups(ownSessions);
59938
+ if (requestedGroup && !isOnlyOwnGroup(requestedGroup, ownGroups)) {
59571
59939
  const peeked = await connectedClient.listSessions(requestedGroup);
59572
59940
  const section = peeked.length === 0 ? `**Group [${requestedGroup}] (read-only peek):**
59573
59941
  No sessions in this group.` : `**Group [${requestedGroup}] (read-only peek):**
59574
- ${peeked.map((s) => formatSessionListRow(s, currentSession.cwd, s.id === mySessionId)).join(`
59942
+ ${peeked.map((session) => formatSessionListRow(session, currentSession.cwd, session.id === mySessionId)).join(`
59575
59943
  `)}`;
59576
59944
  return {
59577
- content: [{ type: "text", text: `Your group: ${ownGroup}
59945
+ content: [{ type: "text", text: `Your groups: ${ownGroups.join(", ")}
59578
59946
 
59579
59947
  ${section}` }],
59580
59948
  isError: false,
59581
- details: { group: ownGroup, peekGroup: requestedGroup }
59949
+ details: { group: ownGroups.at(-1), groups: ownGroups, peekGroup: requestedGroup }
59582
59950
  };
59583
59951
  }
59584
- const otherSessions = ownSessions.filter((s) => s.id !== mySessionId);
59585
- const currentSection = `**Current session** (group: ${ownGroup}):
59952
+ const otherSessions = ownSessions.filter((session) => session.id !== mySessionId);
59953
+ const currentSection = `**Current session** (groups: ${ownGroups.join(", ")}):
59586
59954
  ${formatSessionListRow(currentSession, currentSession.cwd, true)}`;
59587
59955
  const otherSection = otherSessions.length === 0 ? `**Other sessions:**
59588
- No other sessions in your group (${ownGroup}).` : `**Other sessions** (group: ${ownGroup}):
59589
- ${otherSessions.map((s) => formatSessionListRow(s, currentSession.cwd, false)).join(`
59956
+ No other sessions share any of your groups.` : `**Other visible sessions:**
59957
+ ${otherSessions.map((session) => formatSessionListRow(session, currentSession.cwd, false)).join(`
59590
59958
  `)}`;
59591
59959
  return {
59592
59960
  content: [{ type: "text", text: `${currentSection}
59593
59961
 
59594
59962
  ${otherSection}` }],
59595
59963
  isError: false,
59596
- details: { group: ownGroup }
59964
+ details: { group: ownGroups.at(-1), groups: ownGroups }
59597
59965
  };
59598
59966
  } catch (error) {
59599
59967
  return {
@@ -59901,21 +60269,26 @@ ${lines.join(`
59901
60269
  try {
59902
60270
  const mySessionId = connectedClient.sessionId;
59903
60271
  const sessions = await connectedClient.listSessions();
59904
- const self = sessions.find((s) => s.id === mySessionId);
59905
- const ownGroup = normalizeGroup(self?.group);
59906
- const peekSection = requestedGroup && requestedGroup !== ownGroup ? `
59907
- Peeked group [${requestedGroup}]: ${(await connectedClient.listSessions(requestedGroup)).length} session(s)` : "";
60272
+ const ownGroups = resolveOwnGroups(sessions);
60273
+ const selectedGroup = isOnlyOwnGroup(requestedGroup, ownGroups) ? undefined : requestedGroup;
60274
+ const selectedGroupSessions = selectedGroup === undefined ? undefined : await connectedClient.listSessions(selectedGroup);
60275
+ const selectedSection = selectedGroupSessions === undefined ? "" : `
60276
+ Selected group [${selectedGroup}]: ${selectedGroupSessions.length} session(s)`;
59908
60277
  return {
59909
60278
  content: [{
59910
60279
  type: "text",
59911
60280
  text: `**Intercom Status:**
59912
60281
  Connected: Yes
59913
60282
  Session ID: ${mySessionId}
59914
- Group: ${ownGroup}
59915
- Active sessions in group: ${sessions.length}${peekSection}`
60283
+ Groups: ${ownGroups.join(", ")}
60284
+ Active visible sessions: ${sessions.length}${selectedSection}`
59916
60285
  }],
59917
60286
  isError: false,
59918
- details: { group: ownGroup }
60287
+ details: {
60288
+ group: ownGroups.at(-1),
60289
+ groups: ownGroups,
60290
+ ...selectedGroup === undefined ? {} : { selectedGroup, selectedGroupSessionCount: selectedGroupSessions?.length ?? 0 }
60291
+ }
59919
60292
  };
59920
60293
  } catch (error) {
59921
60294
  return {
@@ -60369,8 +60742,6 @@ function registerIntercomLifecycle(pi, deps) {
60369
60742
  deps.setSessionStartedAt(null);
60370
60743
  }
60371
60744
  pi.on("session_start", async (_event, ctx) => {
60372
- if (!deps.config.enabled)
60373
- return;
60374
60745
  if (hasActiveSession)
60375
60746
  await cleanupRuntime("Session replaced");
60376
60747
  hasActiveSession = true;
@@ -61705,7 +62076,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
61705
62076
  let runtimeGeneration = 0;
61706
62077
  let agentRunning = false;
61707
62078
  let sessionHomeGroup = null;
61708
- let joinedGroup = null;
62079
+ let joinedGroups = null;
61709
62080
  const activeTools = new Map;
61710
62081
  let replyTracker = new ReplyTracker;
61711
62082
  const replyWaiters = new ReplyWaiterRegistry(DEFAULT_REPLY_TIMEOUT_MS, config.maxPendingAsks);
@@ -61760,19 +62131,21 @@ function piIntercomExtension(pi, testOverrides = {}) {
61760
62131
  function resolveSessionHomeGroup() {
61761
62132
  return sessionHomeGroup ?? resolveHomeGroup(config, getLiveContext());
61762
62133
  }
62134
+ function currentIntercomGroups() {
62135
+ return joinedGroups === null ? normalizeGroups(undefined, resolveSessionHomeGroup()) : new Set(joinedGroups);
62136
+ }
61763
62137
  function currentIntercomGroup() {
61764
- return joinedGroup ?? resolveSessionHomeGroup();
62138
+ return [...currentIntercomGroups()].at(-1) ?? resolveSessionHomeGroup();
61765
62139
  }
61766
- function setJoinedGroup(group) {
62140
+ function setJoinedGroups(groups) {
62141
+ joinedGroups = normalizeGroups(groups);
61767
62142
  const sessionId = currentSessionId;
61768
- if (!sessionId)
61769
- return;
61770
- setRuntimeIntercomGroup(sessionId, group);
61771
- joinedGroup = group;
62143
+ if (sessionId)
62144
+ setRuntimeIntercomGroup(sessionId, currentIntercomGroup());
61772
62145
  }
61773
- function clearJoinedGroup() {
62146
+ function clearJoinedGroups() {
62147
+ joinedGroups = null;
61774
62148
  const sessionId = currentSessionId;
61775
- joinedGroup = null;
61776
62149
  if (sessionId)
61777
62150
  clearRuntimeIntercomGroup(sessionId);
61778
62151
  }
@@ -61790,6 +62163,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
61790
62163
  startedAt: sessionStartedAt,
61791
62164
  lastActivity: Date.now(),
61792
62165
  status: currentStatus(),
62166
+ groups: [...currentIntercomGroups()],
61793
62167
  group: currentIntercomGroup()
61794
62168
  };
61795
62169
  }
@@ -62209,7 +62583,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
62209
62583
  const nextClient = new IntercomClient(`${currentSessionId}:pending-stage-route:${runId}`);
62210
62584
  state.client = nextClient;
62211
62585
  attachPendingStageRouteClientHandlers(runId, state, nextClient);
62212
- await nextClient.connect({ ...buildRegistration(), name: undefined, group: normalizeGroup(route.group) }, undefined, undefined, readSubagentMessageSource(runtimeContext?.subagentPolicy));
62586
+ await nextClient.connect({ ...buildRegistration(), name: undefined, groups: [normalizeGroup(route.group)], group: normalizeGroup(route.group) }, undefined, undefined, readSubagentMessageSource(runtimeContext?.subagentPolicy));
62213
62587
  if (!pendingStageRouteClientIsCurrent(runId, state, contextAtStart, generationAtStart)) {
62214
62588
  await nextClient.disconnect();
62215
62589
  throw new Error("Intercom runtime no longer active");
@@ -62268,9 +62642,6 @@ function piIntercomExtension(pi, testOverrides = {}) {
62268
62642
  await ensurePendingStageRouteClient(runId, { ...route, group: routeGroup });
62269
62643
  }
62270
62644
  async function ensureConnected(reason) {
62271
- if (!config.enabled) {
62272
- throw new Error("Intercom disabled");
62273
- }
62274
62645
  if (disposed || shuttingDown) {
62275
62646
  throw new Error("Intercom shutting down");
62276
62647
  }
@@ -62412,7 +62783,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
62412
62783
  clearReconnectTimer,
62413
62784
  setRuntimeContext: (value) => {
62414
62785
  if (value === null) {
62415
- clearJoinedGroup();
62786
+ clearJoinedGroups();
62416
62787
  sessionHomeGroup = null;
62417
62788
  } else {
62418
62789
  sessionHomeGroup = resolveHomeGroup(config, value);
@@ -62475,8 +62846,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
62475
62846
  beginReplyWait: (from, replyTo, signal) => replyWaiters.begin(from, replyTo, signal),
62476
62847
  confirmSend: config.confirmSend,
62477
62848
  homeGroup: resolveSessionHomeGroup,
62478
- setJoinedGroup,
62479
- clearJoinedGroup,
62849
+ setJoinedGroups,
62850
+ clearJoinedGroups,
62480
62851
  replyTracker: () => replyTracker
62481
62852
  });
62482
62853
  registerIntercomOverlay(pi, {