@asm-agent/coding-agent 0.8.8 → 0.9.0

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 (178) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +2 -7
  3. package/dist/asm-agent-runtime/src/__pycache__/asm_cm_driver.cpython-313.pyc +0 -0
  4. package/dist/asm-agent-runtime/src/__pycache__/phase76_address_head.cpython-313.pyc +0 -0
  5. package/dist/asm-agent-runtime/src/rlm/__init__.py +1 -1
  6. package/dist/asm-agent-runtime/src/rlm/__pycache__/__init__.cpython-312.pyc +0 -0
  7. package/dist/asm-agent-runtime/src/rlm/__pycache__/__init__.cpython-313.pyc +0 -0
  8. package/dist/asm-agent-runtime/src/rlm/__pycache__/bash.cpython-312.pyc +0 -0
  9. package/dist/asm-agent-runtime/src/rlm/__pycache__/bash.cpython-313.pyc +0 -0
  10. package/dist/asm-agent-runtime/src/rlm/__pycache__/mcp.cpython-312.pyc +0 -0
  11. package/dist/asm-agent-runtime/src/rlm/__pycache__/mcp_base.cpython-312.pyc +0 -0
  12. package/dist/asm-agent-runtime/src/rlm/__pycache__/repl.cpython-312.pyc +0 -0
  13. package/dist/asm-agent-runtime/src/rlm/__pycache__/repl.cpython-313.pyc +0 -0
  14. package/dist/asm-agent-runtime/src/rlm/__pycache__/skill.cpython-313.pyc +0 -0
  15. package/dist/asm-agent-runtime/src/rlm/bash.py +94 -31
  16. package/dist/asm-agent-runtime/src/rlm/repl.md +3 -3
  17. package/dist/asm-agent-runtime/src/rlm/repl.py +46 -45
  18. package/dist/asm-agent-runtime/test/__pycache__/test_bash.cpython-313.pyc +0 -0
  19. package/dist/asm-agent-runtime/test/__pycache__/test_repl.cpython-313.pyc +0 -0
  20. package/dist/asm-agent-runtime/test/test_bash.py +74 -19
  21. package/dist/asm-agent-runtime/test/test_repl.py +67 -3
  22. package/dist/asm-agent-runtime/uv.lock +446 -155
  23. package/dist/bundle/{anthropic-OFECORE7.js → anthropic-ZOZNPFXS.js} +2 -2
  24. package/dist/bundle/{azure-openai-responses-AOVTLR6N.js → azure-openai-responses-TDHCU647.js} +2 -2
  25. package/dist/bundle/{bundled-modules-JQCJDEIY.js → bundled-modules-Q2YODC4B.js} +3 -3
  26. package/dist/bundle/{chunk-M67RGWDQ.js → chunk-AMKLNEAK.js} +25 -44
  27. package/dist/bundle/{chunk-7TB7CGPV.js → chunk-FPY7FFJS.js} +978 -1821
  28. package/dist/bundle/{chunk-JC2TT4MZ.js → chunk-G6SC4YYW.js} +4942 -1916
  29. package/dist/bundle/{chunk-A65OM3TZ.js → chunk-QLHAP3FT.js} +1 -1
  30. package/dist/bundle/{cli-main-FNHDQGQD.js → cli-main-277AG2BR.js} +3 -3
  31. package/dist/bundle/cli.js +1 -1
  32. package/dist/bundle/{google-RVJL6RIQ.js → google-Q3AJWUOY.js} +1 -1
  33. package/dist/bundle/{google-vertex-EZTRRRH6.js → google-vertex-2CSNOUBS.js} +1 -1
  34. package/dist/bundle/{main-IYXIIAJN.js → main-TNXWJXIU.js} +3 -3
  35. package/dist/bundle/{mistral-FSGKSMA7.js → mistral-XRYJGLLG.js} +1 -1
  36. package/dist/bundle/{openai-codex-responses-VM5Y564D.js → openai-codex-responses-C6BRO2BN.js} +2 -2
  37. package/dist/bundle/{openai-completions-X46FOQDN.js → openai-completions-DNXCK2JW.js} +3 -3
  38. package/dist/bundle/{openai-responses-SOQNEPBE.js → openai-responses-BEMWVIXE.js} +2 -2
  39. package/dist/config.d.ts +0 -1
  40. package/dist/config.d.ts.map +1 -1
  41. package/dist/config.js +0 -3
  42. package/dist/config.js.map +1 -1
  43. package/dist/core/agent-session-config.d.ts +1 -2
  44. package/dist/core/agent-session-config.d.ts.map +1 -1
  45. package/dist/core/agent-session-config.js +0 -3
  46. package/dist/core/agent-session-config.js.map +1 -1
  47. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  48. package/dist/core/agent-session-runtime.js +0 -8
  49. package/dist/core/agent-session-runtime.js.map +1 -1
  50. package/dist/core/agent-session-services.d.ts +0 -2
  51. package/dist/core/agent-session-services.d.ts.map +1 -1
  52. package/dist/core/agent-session-services.js +0 -22
  53. package/dist/core/agent-session-services.js.map +1 -1
  54. package/dist/core/agent-session.d.ts +8 -1
  55. package/dist/core/agent-session.d.ts.map +1 -1
  56. package/dist/core/agent-session.js +100 -22
  57. package/dist/core/agent-session.js.map +1 -1
  58. package/dist/core/kernel/bootstrap.d.ts.map +1 -1
  59. package/dist/core/kernel/bootstrap.js +1 -1
  60. package/dist/core/kernel/bootstrap.js.map +1 -1
  61. package/dist/core/kernel/repl-manager.d.ts +32 -8
  62. package/dist/core/kernel/repl-manager.d.ts.map +1 -1
  63. package/dist/core/kernel/repl-manager.js +401 -102
  64. package/dist/core/kernel/repl-manager.js.map +1 -1
  65. package/dist/core/kernel/shared.d.ts +11 -7
  66. package/dist/core/kernel/shared.d.ts.map +1 -1
  67. package/dist/core/kernel/shared.js +2 -5
  68. package/dist/core/kernel/shared.js.map +1 -1
  69. package/dist/core/mcp/mcp-manager.d.ts +4 -2
  70. package/dist/core/mcp/mcp-manager.d.ts.map +1 -1
  71. package/dist/core/mcp/mcp-manager.js +9 -7
  72. package/dist/core/mcp/mcp-manager.js.map +1 -1
  73. package/dist/core/prime-inference-auth.d.ts +0 -9
  74. package/dist/core/prime-inference-auth.d.ts.map +1 -1
  75. package/dist/core/prime-inference-auth.js +0 -50
  76. package/dist/core/prime-inference-auth.js.map +1 -1
  77. package/dist/core/provider-display-names.d.ts.map +1 -1
  78. package/dist/core/provider-display-names.js +0 -1
  79. package/dist/core/provider-display-names.js.map +1 -1
  80. package/dist/core/session-manager.d.ts +0 -4
  81. package/dist/core/session-manager.d.ts.map +1 -1
  82. package/dist/core/session-manager.js +0 -22
  83. package/dist/core/session-manager.js.map +1 -1
  84. package/dist/core/settings-manager.d.ts +4 -16
  85. package/dist/core/settings-manager.d.ts.map +1 -1
  86. package/dist/core/settings-manager.js +13 -43
  87. package/dist/core/settings-manager.js.map +1 -1
  88. package/dist/core/slash-commands.d.ts.map +1 -1
  89. package/dist/core/slash-commands.js +0 -5
  90. package/dist/core/slash-commands.js.map +1 -1
  91. package/dist/core/tools/acp-mcp.d.ts +6 -0
  92. package/dist/core/tools/acp-mcp.d.ts.map +1 -0
  93. package/dist/core/tools/acp-mcp.js +86 -0
  94. package/dist/core/tools/acp-mcp.js.map +1 -0
  95. package/dist/core/tools/index.d.ts +1 -0
  96. package/dist/core/tools/index.d.ts.map +1 -1
  97. package/dist/core/tools/index.js +1 -0
  98. package/dist/core/tools/index.js.map +1 -1
  99. package/dist/core/tools/ipython.d.ts.map +1 -1
  100. package/dist/core/tools/ipython.js +9 -4
  101. package/dist/core/tools/ipython.js.map +1 -1
  102. package/dist/main.d.ts.map +1 -1
  103. package/dist/main.js +2 -11
  104. package/dist/main.js.map +1 -1
  105. package/dist/modes/acp/acp-mode.d.ts.map +1 -1
  106. package/dist/modes/acp/acp-mode.js +1 -1
  107. package/dist/modes/acp/acp-mode.js.map +1 -1
  108. package/dist/modes/agent-connection/daemon-agent-connection.d.ts +0 -2
  109. package/dist/modes/agent-connection/daemon-agent-connection.d.ts.map +1 -1
  110. package/dist/modes/agent-connection/daemon-agent-connection.js +0 -2
  111. package/dist/modes/agent-connection/daemon-agent-connection.js.map +1 -1
  112. package/dist/modes/agents-view/agents-view-mode.d.ts.map +1 -1
  113. package/dist/modes/agents-view/agents-view-mode.js +0 -19
  114. package/dist/modes/agents-view/agents-view-mode.js.map +1 -1
  115. package/dist/modes/daemon/daemon-mode.d.ts +1 -10
  116. package/dist/modes/daemon/daemon-mode.d.ts.map +1 -1
  117. package/dist/modes/daemon/daemon-mode.js +134 -274
  118. package/dist/modes/daemon/daemon-mode.js.map +1 -1
  119. package/dist/modes/daemon/daemon-protocol.d.ts +11 -5
  120. package/dist/modes/daemon/daemon-protocol.d.ts.map +1 -1
  121. package/dist/modes/daemon/daemon-protocol.js +6 -8
  122. package/dist/modes/daemon/daemon-protocol.js.map +1 -1
  123. package/dist/modes/daemon/daemon-supervisor.d.ts +0 -3
  124. package/dist/modes/daemon/daemon-supervisor.d.ts.map +1 -1
  125. package/dist/modes/daemon/daemon-supervisor.js +18 -52
  126. package/dist/modes/daemon/daemon-supervisor.js.map +1 -1
  127. package/dist/modes/daemon/daemon-worker-protocol.d.ts +1 -6
  128. package/dist/modes/daemon/daemon-worker-protocol.d.ts.map +1 -1
  129. package/dist/modes/daemon/daemon-worker-protocol.js +0 -2
  130. package/dist/modes/daemon/daemon-worker-protocol.js.map +1 -1
  131. package/dist/modes/interactive/auth-flows.d.ts +0 -2
  132. package/dist/modes/interactive/auth-flows.d.ts.map +1 -1
  133. package/dist/modes/interactive/auth-flows.js +1 -101
  134. package/dist/modes/interactive/auth-flows.js.map +1 -1
  135. package/dist/modes/interactive/components/assistant-message.d.ts +6 -1
  136. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  137. package/dist/modes/interactive/components/assistant-message.js +13 -3
  138. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  139. package/dist/modes/interactive/components/footer.d.ts +1 -1
  140. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  141. package/dist/modes/interactive/components/footer.js +2 -2
  142. package/dist/modes/interactive/components/footer.js.map +1 -1
  143. package/dist/modes/interactive/components/mermaid.d.ts +12 -0
  144. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
  145. package/dist/modes/interactive/components/mermaid.js +63 -0
  146. package/dist/modes/interactive/components/mermaid.js.map +1 -0
  147. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  148. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  149. package/dist/modes/interactive/components/settings-selector.js +10 -0
  150. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  151. package/dist/modes/interactive/feature-hints.d.ts.map +1 -1
  152. package/dist/modes/interactive/feature-hints.js +0 -4
  153. package/dist/modes/interactive/feature-hints.js.map +1 -1
  154. package/dist/modes/interactive/interactive-mode.d.ts +1 -7
  155. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  156. package/dist/modes/interactive/interactive-mode.js +23 -279
  157. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  158. package/dist/utils/version-check.d.ts.map +1 -1
  159. package/dist/utils/version-check.js +1 -1
  160. package/dist/utils/version-check.js.map +1 -1
  161. package/docs/settings.md +1 -31
  162. package/docs/usage.md +1 -4
  163. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  164. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  165. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  166. package/examples/extensions/sandbox/package-lock.json +2 -2
  167. package/examples/extensions/sandbox/package.json +1 -1
  168. package/examples/extensions/with-deps/package-lock.json +2 -2
  169. package/examples/extensions/with-deps/package.json +1 -1
  170. package/package.json +6 -5
  171. package/dist/core/agent-traces.d.ts +0 -130
  172. package/dist/core/agent-traces.d.ts.map +0 -1
  173. package/dist/core/agent-traces.js +0 -746
  174. package/dist/core/agent-traces.js.map +0 -1
  175. package/dist/core/telemetry.d.ts +0 -92
  176. package/dist/core/telemetry.d.ts.map +0 -1
  177. package/dist/core/telemetry.js +0 -633
  178. package/dist/core/telemetry.js.map +0 -1
@@ -8,9 +8,8 @@ import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels
8
8
  import { theme } from "../modes/interactive/theme/theme.js";
9
9
  import { stripFrontmatter } from "../utils/frontmatter.js";
10
10
  import { sleep } from "../utils/sleep.js";
11
- import { AGENT_MESSAGE_CUSTOM_TYPE, AGENT_MESSAGE_RECEIVED_PREVIEW_LABEL, AGENT_MESSAGE_SKILL_NAME, assertAgentSessionNameAvailable, assertDirectAgentMessageTarget, createAgentMessageHostHandlers, formatAgentSessionNameUnavailable, isAgentSessionMessage, normalizeAgentSessionMessage, parseAgentSessionMessagePromptId, startsAgentRun, } from "./agent-messages.js";
11
+ import { AGENT_MESSAGE_CUSTOM_TYPE, AGENT_MESSAGE_RECEIVED_PREVIEW_LABEL, AGENT_MESSAGE_SKILL_NAME, assertAgentMessageQueueCapacity, assertAgentSessionNameAvailable, assertDirectAgentMessageTarget, createAgentMessageHostHandlers, DEFAULT_AGENT_MESSAGE_MAX_PENDING_PER_SESSION, formatAgentSessionNameUnavailable, isAgentSessionMessage, isAgentSessionMessagePrompt, normalizeAgentSessionMessage, parseAgentSessionMessagePromptId, startsAgentRun, } from "./agent-messages.js";
12
12
  import { AGENT_OBSERVE_SKILL_NAME, createAgentObserveHostHandlers, normalizeObserveLimit, normalizeObserveMaxChars, ORCHESTRATION_HEARTBEAT_SKILL_NAME, } from "./agent-observe.js";
13
- import { flushAgentTraceUpload } from "./agent-traces.js";
14
13
  import { addLoginGuidanceToAuthError, formatAuthenticationFailedMessage, formatNoApiKeyFoundMessage, formatNoModelSelectedMessage, isLikelyAuthenticationError, } from "./auth-guidance.js";
15
14
  import { addAutonomousContinuation, addAutonomousUsage, autonomousStatus, createAutonomousRuntimeState, nextAutonomousContinuation, refreshAutonomousQualityGates, setAutonomousEnabled, } from "./autonomous.js";
16
15
  import { executeBashWithOperations } from "./bash-executor.js";
@@ -37,6 +36,7 @@ import { parseRefineCommandOptions, parseSessionSlashCommand, parseSlashCommand,
37
36
  import { createSyntheticSourceInfo } from "./source-info.js";
38
37
  import { buildSystemPrompt } from "./system-prompt.js";
39
38
  import { THINKING_LEVELS } from "./thinking-levels.js";
39
+ import { acpMcpToolNames, createAcpMcpToolDefinitions } from "./tools/acp-mcp.js";
40
40
  import { createLocalBashOperations } from "./tools/bash.js";
41
41
  import { createAllToolDefinitions } from "./tools/index.js";
42
42
  import { IpythonKernelProvisioner } from "./tools/ipython.js";
@@ -341,11 +341,12 @@ export class AgentSession {
341
341
  _retryPromise = undefined;
342
342
  _retryResolve = undefined;
343
343
  _retryAuthFailureSources = [];
344
+ _agentMessageClearEpoch = 0;
344
345
  _agentMessageOutcomes = new Map();
345
346
  _lateIpythonSentAgentMessages = new Map();
346
347
  /** Outcome disclosures whose session-file append failed; retained for context rebuilds. */
347
348
  _unpersistedOutcomes = [];
348
- _bashAbortController = undefined;
349
+ _bashAbortControllers = new Set();
349
350
  _userBashRunning = false;
350
351
  _userBashAbortRequested = false;
351
352
  _pendingBashMessages = [];
@@ -357,6 +358,7 @@ export class AgentSession {
357
358
  _modelSelectEmitContext = new AsyncLocalStorage();
358
359
  _resourceLoader;
359
360
  _customTools;
361
+ _acpMcpTools = [];
360
362
  _baseToolDefinitions = new Map();
361
363
  _cwd;
362
364
  _agentDir;
@@ -554,6 +556,10 @@ export class AgentSession {
554
556
  throw new Error("MCP is unavailable in this session");
555
557
  return;
556
558
  }
559
+ if (servers.length > 0 && !this._ipythonKernelProvisioner) {
560
+ throw new Error("ACP MCP servers require the built-in cpython tool");
561
+ }
562
+ this._assertAcpMcpToolNamesAvailable(acpMcpToolNames(servers));
557
563
  if (!this._mcpManager.replaceAcpServers(servers, ownerId))
558
564
  return;
559
565
  this._rebuildRuntimeForAcpMcpServers();
@@ -562,8 +568,12 @@ export class AgentSession {
562
568
  if (!this._mcpManager?.canReleaseAcpServers(ownerId))
563
569
  return;
564
570
  if (this._mcpManager.replaceAcpServers([], ownerId)) {
565
- // Host MCP handlers read this manager dynamically, so credentials disappear
566
- // before the kernel-side transport is closed.
571
+ const removedToolNames = new Set(this._acpMcpTools.map((tool) => tool.name));
572
+ const activeToolNames = this.getActiveToolNames().filter((name) => !removedToolNames.has(name));
573
+ for (const name of removedToolNames)
574
+ this._allowedToolNames?.delete(name);
575
+ this._acpMcpTools = [];
576
+ this._refreshToolRegistry({ activeToolNames, includeAllExtensionTools: true });
567
577
  this._baseSystemPrompt = this._rebuildSystemPrompt(this.getActiveToolNames());
568
578
  this.agent.state.systemPrompt = this._baseSystemPrompt;
569
579
  }
@@ -602,9 +612,26 @@ export class AgentSession {
602
612
  inputPause.release();
603
613
  }
604
614
  }
615
+ _assertAcpMcpToolNamesAvailable(names) {
616
+ const occupiedNames = new Set([
617
+ ...this._baseToolDefinitions.keys(),
618
+ ...this._customTools.map((tool) => tool.name),
619
+ ...this._extensionRunner.getAllRegisteredTools().map((tool) => tool.definition.name),
620
+ ]);
621
+ for (const name of names) {
622
+ if (occupiedNames.has(name)) {
623
+ throw new Error(`ACP MCP tool name conflicts with an existing tool: ${name}`);
624
+ }
625
+ }
626
+ }
605
627
  _rebuildRuntimeForAcpMcpServers() {
628
+ const previousToolNames = new Set(this._acpMcpTools.map((tool) => tool.name));
629
+ const nextToolNames = acpMcpToolNames(this._mcpManager?.getAcpServers() ?? []);
630
+ this._assertAcpMcpToolNamesAvailable(nextToolNames);
631
+ const activeToolNames = this.getActiveToolNames().filter((name) => !previousToolNames.has(name));
632
+ activeToolNames.push(...nextToolNames);
606
633
  this._buildRuntime({
607
- activeToolNames: this.getActiveToolNames(),
634
+ activeToolNames,
608
635
  includeAllExtensionTools: true,
609
636
  });
610
637
  this._baseSystemPrompt = this._rebuildSystemPrompt(this.getActiveToolNames());
@@ -2027,7 +2054,6 @@ export class AgentSession {
2027
2054
  if (instructions !== undefined && typeof instructions !== "string") {
2028
2055
  throw new Error("compact.run instructions must be a string when provided");
2029
2056
  }
2030
- // "status" is reserved by the host-request reply protocol; don't use it as a key.
2031
2057
  if (!this.isStreaming) {
2032
2058
  return {
2033
2059
  scheduled: false,
@@ -2981,7 +3007,7 @@ export class AgentSession {
2981
3007
  }
2982
3008
  }
2983
3009
  async _disposeAsyncOnce() {
2984
- // Flush kernels/traces for both still-running and retained children; the sync
3010
+ // Flush kernels for both still-running and retained children; the sync
2985
3011
  // dispose() below only tears them down synchronously.
2986
3012
  for (const run of [...this._activeRlmChildRuns.values()]) {
2987
3013
  const childSession = run.session;
@@ -3305,7 +3331,7 @@ export class AgentSession {
3305
3331
  rlmDepth: this._rlmDepth,
3306
3332
  rlmParentAgent: this._rlmParentAgent,
3307
3333
  harnessState: this._loadMergedHarnessState(),
3308
- genericMcpServers: this._mcpManager?.getEnabledGenericServers(),
3334
+ genericMcpServers: this._mcpManager?.getEnabledPersistentGenericServers(),
3309
3335
  };
3310
3336
  return buildSystemPrompt(this._baseSystemPromptOptions);
3311
3337
  }
@@ -3466,6 +3492,22 @@ export class AgentSession {
3466
3492
  }
3467
3493
  async acceptAgentMessagePrompt(text, options) {
3468
3494
  const customMessage = options?.customMessage && isAgentSessionMessage(options.customMessage) ? options.customMessage : undefined;
3495
+ const clearEpoch = this._agentMessageClearEpoch;
3496
+ const admissionCommitted = () => {
3497
+ options?.admissionCommitted?.();
3498
+ if (clearEpoch !== this._agentMessageClearEpoch) {
3499
+ throw new Error("Agent message was cleared before admission");
3500
+ }
3501
+ };
3502
+ if (this._sessionInputPumpSuspended &&
3503
+ this._isBusyForSessionInput("preflight") &&
3504
+ options?.queueIfBusy === true &&
3505
+ options.streamingBehavior) {
3506
+ admissionCommitted();
3507
+ const queued = await this.queueAgentMessagePrompt(text, options.streamingBehavior, customMessage);
3508
+ options.preflightResult?.(queued, queued);
3509
+ return;
3510
+ }
3469
3511
  await this._prompt(text, {
3470
3512
  ...options,
3471
3513
  resumeIfIdle: false,
@@ -3475,6 +3517,7 @@ export class AgentSession {
3475
3517
  returnAfterAccepted: true,
3476
3518
  agentMessageId: options?.agentMessageId ?? customMessage?.details.id ?? parseAgentSessionMessagePromptId(text),
3477
3519
  customMessage,
3520
+ admissionCommitted,
3478
3521
  });
3479
3522
  if (customMessage?.details.fromRelationship === "parent")
3480
3523
  this._repliedToParentSinceTask = false;
@@ -3737,6 +3780,11 @@ export class AgentSession {
3737
3780
  expandPromptTemplates,
3738
3781
  });
3739
3782
  const normalized = normalizationResult instanceof Promise ? await normalizationResult : normalizationResult;
3783
+ // Async input handlers ran between the admission check above and
3784
+ // admission itself; re-check so content invalidated during that
3785
+ // await (e.g. a cron job cancelled or updated) is not admitted.
3786
+ if (normalizationResult instanceof Promise)
3787
+ options?.admissionCommitted?.();
3740
3788
  if (normalized.kind === "extensionCommand") {
3741
3789
  commitFence?.release();
3742
3790
  reportPreflight(true);
@@ -4300,6 +4348,11 @@ export class AgentSession {
4300
4348
  if (this._sessionInputAdmissionPauses.size > 0) {
4301
4349
  throw new Error("Cannot admit a session action while session input admission is paused.");
4302
4350
  }
4351
+ if (options.restore !== true &&
4352
+ action.payload.kind === "turn" &&
4353
+ isAgentSessionMessage(primaryDeliveryRecord(action).message)) {
4354
+ assertAgentMessageQueueCapacity(this._actionStore.unfinishedActions().length, DEFAULT_AGENT_MESSAGE_MAX_PENDING_PER_SESSION);
4355
+ }
4303
4356
  const coalescedOwner = options.restore ? undefined : this._coalescedFollowUpOwner(action);
4304
4357
  if (coalescedOwner) {
4305
4358
  if (action.agentMessageId !== coalescedOwner.agentMessageId) {
@@ -4998,6 +5051,10 @@ export class AgentSession {
4998
5051
  action.payload.prepared = undefined;
4999
5052
  }
5000
5053
  }
5054
+ clearQueuedAgentMessages() {
5055
+ this._agentMessageClearEpoch++;
5056
+ return this.clearQueuedUserMessagesMatching(isAgentSessionMessagePrompt);
5057
+ }
5001
5058
  clearQueuedUserMessagesMatching(predicate) {
5002
5059
  const ownedActions = this._actionStore.ownedActions();
5003
5060
  const dispatchedTurnCount = ownedActions.filter((action) => action.payload.kind === "turn" &&
@@ -7201,14 +7258,16 @@ export class AgentSession {
7201
7258
  const previousActiveToolNames = this.getActiveToolNames();
7202
7259
  const allowedToolNames = this._allowedToolNames;
7203
7260
  const registeredTools = this._extensionRunner.getAllRegisteredTools();
7261
+ const sdkToolEntry = (definition) => ({
7262
+ definition,
7263
+ sourceInfo: createSyntheticSourceInfo(`<sdk:${definition.name}>`, {
7264
+ source: "sdk",
7265
+ }),
7266
+ });
7204
7267
  const allCustomTools = [
7205
7268
  ...registeredTools,
7206
- ...this._customTools.map((definition) => ({
7207
- definition,
7208
- sourceInfo: createSyntheticSourceInfo(`<sdk:${definition.name}>`, {
7209
- source: "sdk",
7210
- }),
7211
- })),
7269
+ ...this._customTools.map(sdkToolEntry),
7270
+ ...this._acpMcpTools.map(sdkToolEntry),
7212
7271
  ];
7213
7272
  const isAllowedTool = (name) => !allowedToolNames || allowedToolNames.has(name);
7214
7273
  const allowedCustomTools = allCustomTools.filter((tool) => isAllowedTool(tool.definition.name));
@@ -7338,6 +7397,20 @@ export class AgentSession {
7338
7397
  }
7339
7398
  this._bindExtensionCore(this._extensionRunner);
7340
7399
  this._applyExtensionBindings(this._extensionRunner);
7400
+ const previousAcpMcpToolNames = new Set(this._acpMcpTools.map((tool) => tool.name));
7401
+ const acpServers = this._mcpManager?.getAcpServers() ?? [];
7402
+ if (acpServers.length > 0 && !this._ipythonKernelProvisioner) {
7403
+ throw new Error("ACP MCP servers require the built-in cpython tool");
7404
+ }
7405
+ const acpMcpTools = this._ipythonKernelProvisioner
7406
+ ? createAcpMcpToolDefinitions(acpServers, this._ipythonKernelProvisioner)
7407
+ : [];
7408
+ this._assertAcpMcpToolNamesAvailable(acpMcpTools.map((tool) => tool.name));
7409
+ for (const name of previousAcpMcpToolNames)
7410
+ this._allowedToolNames?.delete(name);
7411
+ for (const tool of acpMcpTools)
7412
+ this._allowedToolNames?.add(tool.name);
7413
+ this._acpMcpTools = acpMcpTools;
7341
7414
  const defaultActiveToolNames = this._baseToolsOverride ? Object.keys(this._baseToolsOverride) : ["ipython"];
7342
7415
  const baseActiveToolNames = [...(options.activeToolNames ?? defaultActiveToolNames)];
7343
7416
  if (this._goalState.status === "active" && this._includeGoals) {
@@ -8651,7 +8724,6 @@ export class AgentSession {
8651
8724
  const text = compactRlmText(readAssistantText(assistant));
8652
8725
  if (text)
8653
8726
  answerPreview = text;
8654
- void flushAgentTraceUpload(child.sessionManager).catch(() => undefined);
8655
8727
  emitChildUpdate();
8656
8728
  }
8657
8729
  else if (event.type === "message_start" || event.type === "message_update") {
@@ -9088,14 +9160,16 @@ export class AgentSession {
9088
9160
  * @param options.operations Custom BashOperations for remote execution
9089
9161
  */
9090
9162
  async executeBash(command, onChunk, options) {
9091
- this._bashAbortController = new AbortController();
9163
+ // Each invocation owns its controller so abortBash reaches every in-flight command.
9164
+ const abortController = new AbortController();
9165
+ this._bashAbortControllers.add(abortController);
9092
9166
  const prefix = this.settingsManager.getShellCommandPrefix();
9093
9167
  const shellPath = this.settingsManager.getShellPath();
9094
9168
  const resolvedCommand = prefix ? `${prefix}\n${command}` : command;
9095
9169
  try {
9096
9170
  const result = await executeBashWithOperations(resolvedCommand, this.sessionManager.getCwd(), options?.operations ?? createLocalBashOperations({ shellPath }), {
9097
9171
  onChunk,
9098
- signal: this._bashAbortController.signal,
9172
+ signal: abortController.signal,
9099
9173
  });
9100
9174
  if (!options?.transient) {
9101
9175
  this.recordBashResult(command, result, options);
@@ -9103,7 +9177,8 @@ export class AgentSession {
9103
9177
  return result;
9104
9178
  }
9105
9179
  finally {
9106
- this._bashAbortController = undefined;
9180
+ this._bashAbortControllers.delete(abortController);
9181
+ this._notifySessionInputCheckpointChange();
9107
9182
  }
9108
9183
  }
9109
9184
  /**
@@ -9247,13 +9322,16 @@ export class AgentSession {
9247
9322
  abortBash() {
9248
9323
  // A user bash command may not have spawned yet (extension dispatch in
9249
9324
  // progress); flag the request so runUserBash cancels before executing.
9250
- if (this._userBashRunning && this._bashAbortController === undefined) {
9325
+ // runUserBash clears the flag at each start, so a stale flag is harmless.
9326
+ if (this._userBashRunning) {
9251
9327
  this._userBashAbortRequested = true;
9252
9328
  }
9253
- this._bashAbortController?.abort();
9329
+ for (const controller of this._bashAbortControllers) {
9330
+ controller.abort();
9331
+ }
9254
9332
  }
9255
9333
  get isBashRunning() {
9256
- return this._bashAbortController !== undefined || this._userBashRunning;
9334
+ return this._bashAbortControllers.size > 0 || this._userBashRunning;
9257
9335
  }
9258
9336
  /** Whether there are pending bash messages waiting to be flushed */
9259
9337
  get hasPendingBashMessages() {