@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
@@ -7,9 +7,8 @@ import { BUILTIN_MCP_CATALOG } from "@asm-agent/ai/mcp";
7
7
  import { CombinedAutocompleteProvider, Container, Loader, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TUI, truncateToWidth, visibleWidth, } from "@asm-agent/tui";
8
8
  import { spawn, spawnSync } from "child_process";
9
9
  import { buildDaemonUpdateRestartReport, launchDaemonUpdateRestartCoordinator, resolveDaemonUpdateRestartSocketPath, } from "../../cli/daemon-update-restart.js";
10
- import { APP_NAME, APP_TITLE, getAgentDir, getAgentTracesLogPath, getDebugLogPath, getLogsDir, getShareViewerUrl, SELF_UPDATE_INTERACTIVE_CHILD_ENV, SELF_UPDATE_NOT_ATTEMPTED_EXIT_CODE, VERSION, } from "../../config.js";
10
+ import { APP_NAME, APP_TITLE, getAgentDir, getDebugLogPath, getLogsDir, getShareViewerUrl, SELF_UPDATE_INTERACTIVE_CHILD_ENV, SELF_UPDATE_NOT_ATTEMPTED_EXIT_CODE, VERSION, } from "../../config.js";
11
11
  import { AGENT_MESSAGE_RECEIVED_PREVIEW_LABEL, isAgentSessionMessage, startsAgentRun, } from "../../core/agent-messages.js";
12
- import { getAsmAgentTraceCredential, previewAgentTraceFile, uploadAgentTraceFile, uploadAllAgentTraces, } from "../../core/agent-traces.js";
13
12
  import { isNoModelsAvailableMessage } from "../../core/auth-guidance.js";
14
13
  import { DEFAULT_HEARTBEAT_DELIVERY_MODE, parseHeartbeatCommand, } from "../../core/cron-jobs.js";
15
14
  import { FooterDataProvider } from "../../core/footer-data-provider.js";
@@ -19,7 +18,6 @@ import { runMcpManagementCommand } from "../../core/mcp/mcp-command.js";
19
18
  import { bashOutputToText, COMPACTION_OUTCOME_CUSTOM_TYPE, createHeartbeatPromptMessage, HEARTBEAT_PROMPT_PREVIEW_LABEL, isCompactionOutcomeMessage, isRefinementOutcomeMessage, isSessionSlashCommandMessage, isSessionSlashCommandResultMessage, REFINEMENT_OUTCOME_CUSTOM_TYPE, SESSION_SLASH_COMMAND_CUSTOM_TYPE, SESSION_SLASH_COMMAND_RESULT_CUSTOM_TYPE, } from "../../core/messages.js";
20
19
  import { findExactModelReferenceMatch, resolveModelScopeFromModels } from "../../core/model-resolver.js";
21
20
  import { parseNewSessionCommand } from "../../core/new-session-command.js";
22
- import { resolveAsmAgentTracesBaseUrl } from "../../core/prime-inference-auth.js";
23
21
  import { resolvePrimeInferencePostLoginModelAction } from "../../core/prime-inference-model-selection.js";
24
22
  import { parseCommandArgs } from "../../core/prompt-templates.js";
25
23
  import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
@@ -27,7 +25,6 @@ import { SessionImportFileNotFoundError } from "../../core/session-import-errors
27
25
  import { resolveSessionPath, SessionSelectorError, SessionSelectorNotFoundError } from "../../core/session-resolver.js";
28
26
  import { parseSkillBlock } from "../../core/skill-blocks.js";
29
27
  import { BUILTIN_SLASH_COMMANDS, builtinSlashCommandTakesArgument, isBuiltinSlashCommandName, parseSlashCommand, resolveBuiltinSlashCommandName, } from "../../core/slash-commands.js";
30
- import { captureAgentCommandUsed, captureOnboardingCompleted, } from "../../core/telemetry.js";
31
28
  import { truncateTail } from "../../core/tools/truncate.js";
32
29
  import { ASM_LOGO } from "../../themes/asm-logo.js";
33
30
  import { getChangelogPath, parseChangelog } from "../../utils/changelog.js";
@@ -71,6 +68,7 @@ import { FooterComponent } from "./components/footer.js";
71
68
  import { HeartbeatManagerComponent } from "./components/heartbeat-manager.js";
72
69
  import { InjectedPromptMessageComponent, isInjectedPromptMessage } from "./components/injected-prompt-message.js";
73
70
  import { formatKeyText, keyHint, keyText, rawKeyHint } from "./components/keybinding-hints.js";
71
+ import { createMermaidMarkdownTransform } from "./components/mermaid.js";
74
72
  import { OnboardingSplashComponent } from "./components/onboarding-splash.js";
75
73
  import { MalformedRefinementOutcomeMessageComponent, RefinementOutcomeMessageComponent, } from "./components/refinement-outcome-message.js";
76
74
  import { ScopedModelsSelectorComponent } from "./components/scoped-models-selector.js";
@@ -88,7 +86,7 @@ import { UserMessageSelectorComponent } from "./components/user-message-selector
88
86
  import { FeatureHintDeck } from "./feature-hints.js";
89
87
  import { scopeHeartbeatsToSession } from "./heartbeat-scope.js";
90
88
  import { collectMarkedImages, evictImagesToBudget, formatImageMarker, imageMarkerIds, remapImageMarkers, } from "./image-markers.js";
91
- import { isOnboardingModelReady, shouldRunOnboarding, shouldRunPrimeCliOnboardingSplash, } from "./onboarding.js";
89
+ import { shouldRunOnboarding, shouldRunPrimeCliOnboardingSplash } from "./onboarding.js";
92
90
  import { QueueSelection } from "./queue-selection.js";
93
91
  import { formatResumeHint } from "./resume-hint.js";
94
92
  import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, initTheme, onThemeChange, setRegisteredThemes, setTheme, setThemeInstance, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
@@ -611,6 +609,10 @@ export class InteractiveMode {
611
609
  agentMessagesExpanded = false;
612
610
  editDiffsExpanded = false;
613
611
  hideThinkingBlock = false;
612
+ mermaidMarkdownTransform = createMermaidMarkdownTransform({
613
+ getMode: () => this.settingsManager.getMermaidRenderingMode(),
614
+ theme,
615
+ });
614
616
  skillCommands = new Map();
615
617
  connectionCommands = [];
616
618
  connectionModels = [];
@@ -642,7 +644,6 @@ export class InteractiveMode {
642
644
  refineLoader = undefined;
643
645
  retryLoader = undefined;
644
646
  retryCountdown = undefined;
645
- traceUploadAllAbortController = undefined;
646
647
  // Session-owned queued messages mirrored from connection events.
647
648
  connectionQueue = { steering: [], followUp: [] };
648
649
  queueSelection = new QueueSelection();
@@ -1253,34 +1254,11 @@ export class InteractiveMode {
1253
1254
  if (!this.shouldRunOnboarding()) {
1254
1255
  return false;
1255
1256
  }
1256
- const startedAt = Date.now();
1257
1257
  const showPrimeCliSplash = this.shouldRunPrimeCliOnboardingSplash();
1258
- let outcome = "aborted";
1259
- try {
1260
- this.markOnboardingShown();
1261
- await this.settingsManager.flush();
1262
- await this.runOnboardingFlow(showPrimeCliSplash);
1263
- outcome = isOnboardingModelReady(this.getOnboardingState()) ? "success" : "aborted";
1264
- return true;
1265
- }
1266
- catch (error) {
1267
- outcome = "error";
1268
- throw error;
1269
- }
1270
- finally {
1271
- const model = this.getCurrentModel();
1272
- const authStatus = model ? this.modelRegistry.getProviderAuthStatus(model.provider) : undefined;
1273
- const storedCredential = model ? this.modelRegistry.authStorage.get(model.provider) : undefined;
1274
- void captureOnboardingCompleted({
1275
- agentDir: getAgentDir(),
1276
- settingsManager: this.settingsManager,
1277
- durationMs: Date.now() - startedAt,
1278
- outcome,
1279
- provider: model?.provider,
1280
- authSource: authStatus?.source,
1281
- storedCredentialType: storedCredential?.type,
1282
- }).catch(() => { });
1283
- }
1258
+ this.markOnboardingShown();
1259
+ await this.settingsManager.flush();
1260
+ await this.runOnboardingFlow(showPrimeCliSplash);
1261
+ return true;
1284
1262
  }
1285
1263
  async showOnboardingModelSelection(splash) {
1286
1264
  try {
@@ -2067,7 +2045,6 @@ export class InteractiveMode {
2067
2045
  this.isBashRunning() ||
2068
2046
  this.getRetryAttempt() > 0 ||
2069
2047
  this.connectionState?.sessionActions.active !== undefined ||
2070
- this.traceUploadAllAbortController !== undefined ||
2071
2048
  this.sideQuestionEvent?.status === "running");
2072
2049
  }
2073
2050
  getRetryAttempt() {
@@ -3733,13 +3710,6 @@ export class InteractiveMode {
3733
3710
  this.ui.requestRender();
3734
3711
  return;
3735
3712
  }
3736
- if (commandName) {
3737
- void captureAgentCommandUsed({
3738
- agentDir: getAgentDir(),
3739
- settingsManager: this.settingsManager,
3740
- commandName,
3741
- }).catch(() => { });
3742
- }
3743
3713
  if (commandName === "btw") {
3744
3714
  this.editor.setText("");
3745
3715
  await this.handleSideQuestion(commandArgs);
@@ -3818,11 +3788,6 @@ export class InteractiveMode {
3818
3788
  this.editor.setText("");
3819
3789
  return;
3820
3790
  }
3821
- if (commandName === "traces") {
3822
- await this.handleTracesCommand(canonicalCommandText);
3823
- this.editor.setText("");
3824
- return;
3825
- }
3826
3791
  if (commandName === "context" && !commandArgs) {
3827
3792
  this.echoLocalCommand(text);
3828
3793
  await this.handleContextCommand();
@@ -4553,7 +4518,7 @@ export class InteractiveMode {
4553
4518
  case "message_update":
4554
4519
  if (event.message.role === "assistant") {
4555
4520
  this.streamingMessage = event.message;
4556
- this.ensureAssistantStreamingComponent(event.message).updateContent(this.streamingMessage);
4521
+ this.ensureAssistantStreamingComponent(event.message).updateContent(this.streamingMessage, true);
4557
4522
  for (const content of this.streamingMessage.content) {
4558
4523
  if (content.type === "toolCall") {
4559
4524
  await this.getOrCreatePendingToolComponent(content);
@@ -4579,7 +4544,7 @@ export class InteractiveMode {
4579
4544
  : `Operation aborted${elapsedSuffix}`;
4580
4545
  this.streamingMessage.errorMessage = errorMessage;
4581
4546
  }
4582
- this.ensureAssistantStreamingComponent(event.message).updateContent(this.streamingMessage);
4547
+ this.ensureAssistantStreamingComponent(event.message).updateContent(this.streamingMessage, false);
4583
4548
  if (this.streamingMessage.stopReason === "aborted" || this.streamingMessage.stopReason === "error") {
4584
4549
  if (!errorMessage) {
4585
4550
  errorMessage = this.streamingMessage.errorMessage || "Error";
@@ -4660,7 +4625,7 @@ export class InteractiveMode {
4660
4625
  this.syncWorkingLoader();
4661
4626
  if (this.streamingComponent) {
4662
4627
  if (this.streamingMessage) {
4663
- this.streamingComponent.updateContent(this.streamingMessage);
4628
+ this.streamingComponent.updateContent(this.streamingMessage, false);
4664
4629
  }
4665
4630
  else {
4666
4631
  this.chatContainer.removeChild(this.streamingComponent);
@@ -4775,10 +4740,11 @@ export class InteractiveMode {
4775
4740
  expanded: this.toolOutputExpanded,
4776
4741
  precededByToolActivity: this.chatContainer.children.at(-1) instanceof ToolExecutionComponent ||
4777
4742
  this.chatContainer.children.at(-1) instanceof AgentMessageComponent,
4743
+ mermaidTransform: this.mermaidMarkdownTransform,
4778
4744
  });
4779
4745
  this.streamingMessage = message;
4780
4746
  this.chatContainer.addChild(this.streamingComponent);
4781
- this.streamingComponent.updateContent(this.streamingMessage);
4747
+ this.streamingComponent.updateContent(this.streamingMessage, true);
4782
4748
  }
4783
4749
  ensureAssistantStreamingComponent(message) {
4784
4750
  let component = this.streamingComponent;
@@ -5339,6 +5305,7 @@ export class InteractiveMode {
5339
5305
  expanded: this.toolOutputExpanded,
5340
5306
  precededByToolActivity: this.chatContainer.children.at(-1) instanceof ToolExecutionComponent ||
5341
5307
  this.chatContainer.children.at(-1) instanceof AgentMessageComponent,
5308
+ mermaidTransform: this.mermaidMarkdownTransform,
5342
5309
  });
5343
5310
  this.chatContainer.addChild(assistantComponent);
5344
5311
  break;
@@ -5594,7 +5561,6 @@ export class InteractiveMode {
5594
5561
  this.showCtrlCExitHint();
5595
5562
  }
5596
5563
  interruptOrClearInput() {
5597
- this.traceUploadAllAbortController?.abort(new Error("Trace upload cancelled"));
5598
5564
  if (this.sideQuestionEvent?.status === "running") {
5599
5565
  this.abortSideQuestion(this.sideQuestionEvent.id, true);
5600
5566
  }
@@ -6358,6 +6324,7 @@ export class InteractiveMode {
6358
6324
  currentTheme: this.settingsManager.getTheme() || "asm",
6359
6325
  availableThemes: getAvailableThemes(),
6360
6326
  hideThinkingBlock: this.hideThinkingBlock,
6327
+ mermaidRenderingMode: this.settingsManager.getMermaidRenderingMode(),
6361
6328
  treeFilterMode: this.settingsManager.getTreeFilterMode(),
6362
6329
  showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
6363
6330
  editorPaddingX: this.settingsManager.getEditorPaddingX(),
@@ -6456,6 +6423,11 @@ export class InteractiveMode {
6456
6423
  this.showError(error instanceof Error ? error.message : String(error));
6457
6424
  });
6458
6425
  },
6426
+ onMermaidRenderingModeChange: (mode) => {
6427
+ this.settingsManager.setMermaidRenderingMode(mode);
6428
+ this.chatContainer.invalidate();
6429
+ this.ui.requestRender();
6430
+ },
6459
6431
  onQuietStartupChange: (enabled) => {
6460
6432
  this.settingsManager.setQuietStartup(enabled);
6461
6433
  },
@@ -7906,234 +7878,6 @@ export class InteractiveMode {
7906
7878
  this.chatContainer.addChild(new Text(prompt, 1, 0));
7907
7879
  this.ui.requestRender();
7908
7880
  }
7909
- formatTraceUploadResult(result) {
7910
- switch (result.status) {
7911
- case "uploaded":
7912
- return `Trace uploaded (${result.bytesStored.toLocaleString()} bytes).`;
7913
- case "disabled":
7914
- return "Trace sharing is disabled.";
7915
- case "missing_credentials":
7916
- return "Trace sharing needs a Prime API key. Run /traces login.";
7917
- case "no_session_file":
7918
- return "Current session has no persisted trace yet.";
7919
- case "empty_session":
7920
- return "Current session trace is empty.";
7921
- case "invalid_session":
7922
- return `Trace upload skipped: ${result.message}.`;
7923
- case "too_large":
7924
- return `Trace upload skipped: session file is ${result.size.toLocaleString()} bytes; limit is ${result.maxBytes.toLocaleString()} bytes.`;
7925
- case "failed":
7926
- if (result.statusCode === 404) {
7927
- return "Trace upload endpoint was not found. The platform API may not be deployed yet, or ASM_AGENT_TRACES_BASE_URL points at the wrong API.";
7928
- }
7929
- return `Trace upload failed: ${result.statusCode ? `HTTP ${result.statusCode}: ` : ""}${result.message}. See ${getAgentTracesLogPath()} for details.`;
7930
- }
7931
- }
7932
- async uploadCurrentTraceOnce() {
7933
- const state = await this.agentConnection.getState();
7934
- return uploadAgentTraceFile({
7935
- sessionFile: state.sessionFile,
7936
- authStorage: this.modelRegistry.authStorage,
7937
- settingsManager: this.settingsManager,
7938
- requireEnabled: false,
7939
- reloadConfig: false,
7940
- });
7941
- }
7942
- async previewCurrentTrace() {
7943
- const state = await this.agentConnection.getState();
7944
- const result = await previewAgentTraceFile({ sessionFile: state.sessionFile });
7945
- let info;
7946
- switch (result.status) {
7947
- case "no_session_file":
7948
- info = "Trace preview is unavailable until the current session has a persisted assistant response.";
7949
- break;
7950
- case "empty_session":
7951
- info = "The current trace is empty.";
7952
- break;
7953
- case "invalid_session":
7954
- case "failed":
7955
- info = `Trace preview failed: ${result.message}.`;
7956
- break;
7957
- case "ready":
7958
- info = this.formatTracePreview(result);
7959
- break;
7960
- }
7961
- this.chatContainer.addChild(new Spacer(1));
7962
- this.chatContainer.addChild(new Text(info, 1, 0));
7963
- this.ui.requestRender();
7964
- }
7965
- formatTracePreview(result) {
7966
- const lines = [
7967
- theme.bold("Trace Preview"),
7968
- theme.fg("dim", "Nothing has been uploaded by this command."),
7969
- "",
7970
- `${theme.fg("dim", "File:")} ${result.sessionFile}`,
7971
- `${theme.fg("dim", "Size:")} ${result.size.toLocaleString()} bytes`,
7972
- `${theme.fg("dim", "Uploadable:")} ${result.uploadable ? "Yes" : `No (limit ${result.maxBytes.toLocaleString()} bytes)`}`,
7973
- `${theme.fg("dim", "Endpoint:")} ${result.endpoint}`,
7974
- `${theme.fg("dim", "Session ID:")} ${result.sessionId}`,
7975
- `${theme.fg("dim", "Trace ID:")} ${result.traceId}`,
7976
- ];
7977
- if (result.parentSessionId) {
7978
- lines.push(`${theme.fg("dim", "Parent session:")} ${result.parentSessionId}`);
7979
- }
7980
- if (result.gitRepo) {
7981
- lines.push(`${theme.fg("dim", "Git repository:")} ${result.gitRepo}`);
7982
- }
7983
- if (result.gitCommit) {
7984
- lines.push(`${theme.fg("dim", "Git commit:")} ${result.gitCommit}`);
7985
- }
7986
- lines.push("", theme.bold("Raw JSONL payload preview"));
7987
- if (result.contentPreview) {
7988
- lines.push(result.contentPreview);
7989
- if (result.truncated) {
7990
- lines.push("", theme.fg("dim", "Preview truncated; upload sends the complete file."));
7991
- }
7992
- }
7993
- else {
7994
- lines.push(theme.fg("dim", "Payload omitted because the trace exceeds the upload limit."));
7995
- }
7996
- return lines.join("\n");
7997
- }
7998
- async uploadAllTraces(sessionDir, signal) {
7999
- return uploadAllAgentTraces({
8000
- authStorage: this.modelRegistry.authStorage,
8001
- settingsManager: this.settingsManager,
8002
- sessionDir,
8003
- requireEnabled: false,
8004
- reloadConfig: false,
8005
- signal,
8006
- onProgress: ({ completed, total }) => {
8007
- if (total > 0 && (completed === 0 || completed === total || completed % 10 === 0)) {
8008
- this.showStatus(`Uploading traces: ${completed.toLocaleString()}/${total.toLocaleString()} (${keyText("app.clear")} to cancel)`);
8009
- }
8010
- },
8011
- });
8012
- }
8013
- async handleTracesCommand(text) {
8014
- const command = text
8015
- .replace(/^\/traces\b/, "")
8016
- .trim()
8017
- .toLowerCase() || "status";
8018
- if (command === "status") {
8019
- await this.settingsManager.reload().catch(() => undefined);
8020
- const credential = await getAsmAgentTraceCredential(this.modelRegistry.authStorage);
8021
- const state = await this.agentConnection.getState();
8022
- const info = [
8023
- theme.bold("Trace Sharing"),
8024
- "",
8025
- `${theme.fg("dim", "Automatic uploads:")} ${this.settingsManager.getAgentTracesEnabled() ? "Enabled" : "Disabled"}`,
8026
- `${theme.fg("dim", "Credential:")} ${credential?.label ?? "Not configured"}`,
8027
- `${theme.fg("dim", "Endpoint:")} ${resolveAsmAgentTracesBaseUrl()}`,
8028
- `${theme.fg("dim", "Session file:")} ${state.sessionFile ?? "In-memory"}`,
8029
- "",
8030
- theme.fg("dim", "Commands: /traces on, /traces off, /traces preview, /traces upload-current, /traces upload-all, /traces login"),
8031
- ].join("\n");
8032
- this.chatContainer.addChild(new Spacer(1));
8033
- this.chatContainer.addChild(new Text(info, 1, 0));
8034
- this.ui.requestRender();
8035
- return;
8036
- }
8037
- if (command === "off" || command === "disable") {
8038
- this.settingsManager.setAgentTracesEnabled(false);
8039
- await this.settingsManager.flush();
8040
- this.showStatus("Trace sharing disabled.");
8041
- return;
8042
- }
8043
- if (command === "login") {
8044
- await this.createAuthFlows().runAsmAgentTracesLogin();
8045
- return;
8046
- }
8047
- if (command === "preview") {
8048
- await this.previewCurrentTrace();
8049
- return;
8050
- }
8051
- if (command === "on" || command === "enable") {
8052
- let credential = await getAsmAgentTraceCredential(this.modelRegistry.authStorage);
8053
- if (!credential) {
8054
- const authResult = await this.createAuthFlows().runAsmAgentTracesLogin();
8055
- if (authResult.status !== "success") {
8056
- return;
8057
- }
8058
- credential = await getAsmAgentTraceCredential(this.modelRegistry.authStorage);
8059
- }
8060
- if (!credential) {
8061
- this.showError("Trace sharing needs a Prime API key.");
8062
- return;
8063
- }
8064
- this.settingsManager.setAgentTracesEnabled(true);
8065
- await this.settingsManager.flush();
8066
- const uploadResult = await this.uploadCurrentTraceOnce();
8067
- const uploadMessage = uploadResult.status === "no_session_file" || uploadResult.status === "empty_session"
8068
- ? "Current session will upload after the first assistant response."
8069
- : this.formatTraceUploadResult(uploadResult);
8070
- this.showStatus(`Trace sharing enabled. ${uploadMessage}`);
8071
- return;
8072
- }
8073
- if (command === "upload" || command === "upload-current") {
8074
- const credential = await getAsmAgentTraceCredential(this.modelRegistry.authStorage);
8075
- if (!credential) {
8076
- this.showError("Trace sharing needs a Prime API key. Run /traces login.");
8077
- return;
8078
- }
8079
- const uploadResult = await this.uploadCurrentTraceOnce();
8080
- const message = this.formatTraceUploadResult(uploadResult);
8081
- if (uploadResult.status === "failed") {
8082
- this.showError(message);
8083
- }
8084
- else {
8085
- this.showStatus(message);
8086
- }
8087
- return;
8088
- }
8089
- if (command === "upload-all") {
8090
- const credential = await getAsmAgentTraceCredential(this.modelRegistry.authStorage);
8091
- if (!credential) {
8092
- this.showError("Trace sharing needs a Prime API key. Run /traces login.");
8093
- return;
8094
- }
8095
- if (this.traceUploadAllAbortController) {
8096
- this.showWarning("A trace upload is already running. Cancel it before starting another.");
8097
- return;
8098
- }
8099
- const state = await this.agentConnection.getState();
8100
- const abortController = new AbortController();
8101
- this.traceUploadAllAbortController = abortController;
8102
- let result;
8103
- try {
8104
- result = await this.uploadAllTraces(state.sessionDir, abortController.signal);
8105
- }
8106
- finally {
8107
- if (this.traceUploadAllAbortController === abortController) {
8108
- this.traceUploadAllAbortController = undefined;
8109
- }
8110
- }
8111
- if (abortController.signal.aborted) {
8112
- this.showStatus("Trace upload cancelled.");
8113
- return;
8114
- }
8115
- if (result.total === 0) {
8116
- this.showStatus("No persisted traces were found.");
8117
- return;
8118
- }
8119
- const summary = [
8120
- `Uploaded ${result.uploaded.toLocaleString()} of ${result.total.toLocaleString()} traces`,
8121
- result.skipped > 0 ? `${result.skipped.toLocaleString()} skipped` : undefined,
8122
- result.failed > 0 ? `${result.failed.toLocaleString()} failed` : undefined,
8123
- `${result.bytesStored.toLocaleString()} bytes stored`,
8124
- ]
8125
- .filter((part) => part !== undefined)
8126
- .join("; ");
8127
- if (result.failed > 0) {
8128
- this.showWarning(`${summary}. See ${getAgentTracesLogPath()} for details.`);
8129
- }
8130
- else {
8131
- this.showStatus(`${summary}.`);
8132
- }
8133
- return;
8134
- }
8135
- this.showWarning("Usage: /traces [status|on|off|preview|upload|upload-current|upload-all|login]");
8136
- }
8137
7881
  async handleContextCommand() {
8138
7882
  let info;
8139
7883
  try {