@getpaseo/server 0.1.75 → 0.1.76

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/dist/server/client/daemon-client.d.ts +13 -2
  2. package/dist/server/client/daemon-client.d.ts.map +1 -1
  3. package/dist/server/client/daemon-client.js +36 -0
  4. package/dist/server/client/daemon-client.js.map +1 -1
  5. package/dist/server/server/agent/agent-manager.d.ts +1 -0
  6. package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
  7. package/dist/server/server/agent/agent-manager.js +13 -8
  8. package/dist/server/server/agent/agent-manager.js.map +1 -1
  9. package/dist/server/server/agent/agent-sdk-types.d.ts +3 -0
  10. package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -1
  11. package/dist/server/server/agent/agent-sdk-types.js +7 -0
  12. package/dist/server/server/agent/agent-sdk-types.js.map +1 -1
  13. package/dist/server/server/agent/mcp-server.d.ts.map +1 -1
  14. package/dist/server/server/agent/mcp-server.js +74 -3
  15. package/dist/server/server/agent/mcp-server.js.map +1 -1
  16. package/dist/server/server/agent/provider-history-timestamps.d.ts +2 -0
  17. package/dist/server/server/agent/provider-history-timestamps.d.ts.map +1 -0
  18. package/dist/server/server/agent/provider-history-timestamps.js +16 -0
  19. package/dist/server/server/agent/provider-history-timestamps.js.map +1 -0
  20. package/dist/server/server/agent/provider-manifest.d.ts +1 -1
  21. package/dist/server/server/agent/provider-manifest.d.ts.map +1 -1
  22. package/dist/server/server/agent/provider-manifest.js +14 -0
  23. package/dist/server/server/agent/provider-manifest.js.map +1 -1
  24. package/dist/server/server/agent/provider-registry.d.ts.map +1 -1
  25. package/dist/server/server/agent/provider-registry.js +53 -27
  26. package/dist/server/server/agent/provider-registry.js.map +1 -1
  27. package/dist/server/server/agent/provider-snapshot-manager.d.ts +2 -6
  28. package/dist/server/server/agent/provider-snapshot-manager.d.ts.map +1 -1
  29. package/dist/server/server/agent/provider-snapshot-manager.js +43 -32
  30. package/dist/server/server/agent/provider-snapshot-manager.js.map +1 -1
  31. package/dist/server/server/agent/providers/acp-agent.d.ts +3 -1
  32. package/dist/server/server/agent/providers/acp-agent.d.ts.map +1 -1
  33. package/dist/server/server/agent/providers/acp-agent.js +61 -14
  34. package/dist/server/server/agent/providers/acp-agent.js.map +1 -1
  35. package/dist/server/server/agent/providers/claude/agent.d.ts.map +1 -1
  36. package/dist/server/server/agent/providers/claude/agent.js +111 -38
  37. package/dist/server/server/agent/providers/claude/agent.js.map +1 -1
  38. package/dist/server/server/agent/providers/claude/models.d.ts +2 -0
  39. package/dist/server/server/agent/providers/claude/models.d.ts.map +1 -1
  40. package/dist/server/server/agent/providers/claude/models.js +78 -0
  41. package/dist/server/server/agent/providers/claude/models.js.map +1 -1
  42. package/dist/server/server/agent/providers/codex/app-server-transport.d.ts +1 -0
  43. package/dist/server/server/agent/providers/codex/app-server-transport.d.ts.map +1 -1
  44. package/dist/server/server/agent/providers/codex/app-server-transport.js +14 -10
  45. package/dist/server/server/agent/providers/codex/app-server-transport.js.map +1 -1
  46. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +15 -1
  47. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -1
  48. package/dist/server/server/agent/providers/codex-app-server-agent.js +369 -68
  49. package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -1
  50. package/dist/server/server/agent/providers/cursor-acp-agent.d.ts +21 -0
  51. package/dist/server/server/agent/providers/cursor-acp-agent.d.ts.map +1 -0
  52. package/dist/server/server/agent/providers/cursor-acp-agent.js +85 -0
  53. package/dist/server/server/agent/providers/cursor-acp-agent.js.map +1 -0
  54. package/dist/server/server/agent/providers/generic-acp-agent.d.ts +13 -0
  55. package/dist/server/server/agent/providers/generic-acp-agent.d.ts.map +1 -1
  56. package/dist/server/server/agent/providers/generic-acp-agent.js +209 -2
  57. package/dist/server/server/agent/providers/generic-acp-agent.js.map +1 -1
  58. package/dist/server/server/agent/providers/opencode-agent.d.ts +1 -3
  59. package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
  60. package/dist/server/server/agent/providers/opencode-agent.js +73 -75
  61. package/dist/server/server/agent/providers/opencode-agent.js.map +1 -1
  62. package/dist/server/server/agent/providers/pi-direct-agent.d.ts +1 -1
  63. package/dist/server/server/agent/providers/pi-direct-agent.d.ts.map +1 -1
  64. package/dist/server/server/agent/providers/pi-direct-agent.js +14 -0
  65. package/dist/server/server/agent/providers/pi-direct-agent.js.map +1 -1
  66. package/dist/server/server/agent/providers/pi-session-recovery-policy.d.ts +22 -0
  67. package/dist/server/server/agent/providers/pi-session-recovery-policy.d.ts.map +1 -0
  68. package/dist/server/server/agent/providers/pi-session-recovery-policy.js +51 -0
  69. package/dist/server/server/agent/providers/pi-session-recovery-policy.js.map +1 -0
  70. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts.map +1 -1
  71. package/dist/server/server/agent/timeline-projection.d.ts.map +1 -1
  72. package/dist/server/server/agent/timeline-projection.js +9 -0
  73. package/dist/server/server/agent/timeline-projection.js.map +1 -1
  74. package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts +40 -0
  75. package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts.map +1 -0
  76. package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +80 -0
  77. package/dist/server/server/auto-archive-on-merge/archive-if-safe.js.map +1 -0
  78. package/dist/server/server/auto-archive-on-merge/index.d.ts +8 -0
  79. package/dist/server/server/auto-archive-on-merge/index.d.ts.map +1 -0
  80. package/dist/server/server/auto-archive-on-merge/index.js +15 -0
  81. package/dist/server/server/auto-archive-on-merge/index.js.map +1 -0
  82. package/dist/server/server/bootstrap.d.ts +1 -0
  83. package/dist/server/server/bootstrap.d.ts.map +1 -1
  84. package/dist/server/server/bootstrap.js +74 -38
  85. package/dist/server/server/bootstrap.js.map +1 -1
  86. package/dist/server/server/checkout/status-projection.d.ts.map +1 -1
  87. package/dist/server/server/checkout/status-projection.js +5 -1
  88. package/dist/server/server/checkout/status-projection.js.map +1 -1
  89. package/dist/server/server/config.d.ts.map +1 -1
  90. package/dist/server/server/config.js +3 -1
  91. package/dist/server/server/config.js.map +1 -1
  92. package/dist/server/server/daemon-config-store.js +1 -0
  93. package/dist/server/server/daemon-config-store.js.map +1 -1
  94. package/dist/server/server/loop/rpc-schemas.d.ts +96 -96
  95. package/dist/server/server/loop-service.d.ts +18 -18
  96. package/dist/server/server/paseo-worktree-service.d.ts +3 -1
  97. package/dist/server/server/paseo-worktree-service.d.ts.map +1 -1
  98. package/dist/server/server/paseo-worktree-service.js +55 -18
  99. package/dist/server/server/paseo-worktree-service.js.map +1 -1
  100. package/dist/server/server/persisted-config.d.ts +7 -0
  101. package/dist/server/server/persisted-config.d.ts.map +1 -1
  102. package/dist/server/server/persisted-config.js +1 -0
  103. package/dist/server/server/persisted-config.js.map +1 -1
  104. package/dist/server/server/relay-transport.d.ts +2 -1
  105. package/dist/server/server/relay-transport.d.ts.map +1 -1
  106. package/dist/server/server/relay-transport.js +26 -4
  107. package/dist/server/server/relay-transport.js.map +1 -1
  108. package/dist/server/server/session.d.ts +6 -0
  109. package/dist/server/server/session.d.ts.map +1 -1
  110. package/dist/server/server/session.js +193 -33
  111. package/dist/server/server/session.js.map +1 -1
  112. package/dist/server/server/websocket-server.d.ts.map +1 -1
  113. package/dist/server/server/websocket-server.js +5 -0
  114. package/dist/server/server/websocket-server.js.map +1 -1
  115. package/dist/server/server/workspace-git-service.d.ts +6 -1
  116. package/dist/server/server/workspace-git-service.d.ts.map +1 -1
  117. package/dist/server/server/workspace-git-service.js +27 -4
  118. package/dist/server/server/workspace-git-service.js.map +1 -1
  119. package/dist/server/server/workspace-reconciliation-service.d.ts +4 -2
  120. package/dist/server/server/workspace-reconciliation-service.d.ts.map +1 -1
  121. package/dist/server/server/workspace-reconciliation-service.js +112 -14
  122. package/dist/server/server/workspace-reconciliation-service.js.map +1 -1
  123. package/dist/server/server/workspace-registry.d.ts +6 -1
  124. package/dist/server/server/workspace-registry.d.ts.map +1 -1
  125. package/dist/server/server/workspace-registry.js +11 -0
  126. package/dist/server/server/workspace-registry.js.map +1 -1
  127. package/dist/server/server/worktree-session.d.ts.map +1 -1
  128. package/dist/server/server/worktree-session.js +1 -0
  129. package/dist/server/server/worktree-session.js.map +1 -1
  130. package/dist/server/services/github-service.d.ts +46 -0
  131. package/dist/server/services/github-service.d.ts.map +1 -1
  132. package/dist/server/services/github-service.js +274 -5
  133. package/dist/server/services/github-service.js.map +1 -1
  134. package/dist/server/shared/messages.d.ts +3427 -290
  135. package/dist/server/shared/messages.d.ts.map +1 -1
  136. package/dist/server/shared/messages.js +93 -3
  137. package/dist/server/shared/messages.js.map +1 -1
  138. package/dist/server/shared/terminal-input-mode.d.ts +26 -0
  139. package/dist/server/shared/terminal-input-mode.d.ts.map +1 -0
  140. package/dist/server/shared/terminal-input-mode.js +151 -0
  141. package/dist/server/shared/terminal-input-mode.js.map +1 -0
  142. package/dist/server/terminal/terminal-session-controller.d.ts.map +1 -1
  143. package/dist/server/terminal/terminal-session-controller.js +12 -2
  144. package/dist/server/terminal/terminal-session-controller.js.map +1 -1
  145. package/dist/server/terminal/terminal.d.ts +1 -0
  146. package/dist/server/terminal/terminal.d.ts.map +1 -1
  147. package/dist/server/terminal/terminal.js +16 -3
  148. package/dist/server/terminal/terminal.js.map +1 -1
  149. package/dist/server/terminal/worker-terminal-manager.d.ts.map +1 -1
  150. package/dist/server/terminal/worker-terminal-manager.js +8 -0
  151. package/dist/server/terminal/worker-terminal-manager.js.map +1 -1
  152. package/dist/server/utils/checkout-git.d.ts +4 -1
  153. package/dist/server/utils/checkout-git.d.ts.map +1 -1
  154. package/dist/server/utils/checkout-git.js +85 -29
  155. package/dist/server/utils/checkout-git.js.map +1 -1
  156. package/dist/server/utils/directory-suggestions.d.ts.map +1 -1
  157. package/dist/server/utils/directory-suggestions.js +51 -14
  158. package/dist/server/utils/directory-suggestions.js.map +1 -1
  159. package/dist/server/utils/executable.d.ts.map +1 -1
  160. package/dist/server/utils/executable.js +6 -3
  161. package/dist/server/utils/executable.js.map +1 -1
  162. package/dist/server/utils/run-git-command.d.ts +2 -0
  163. package/dist/server/utils/run-git-command.d.ts.map +1 -1
  164. package/dist/server/utils/run-git-command.js +41 -1
  165. package/dist/server/utils/run-git-command.js.map +1 -1
  166. package/dist/server/utils/worktree.js +1 -1
  167. package/dist/server/utils/worktree.js.map +1 -1
  168. package/dist/src/server/agent/agent-sdk-types.js +7 -0
  169. package/dist/src/server/agent/agent-sdk-types.js.map +1 -1
  170. package/dist/src/server/agent/provider-manifest.js +14 -0
  171. package/dist/src/server/agent/provider-manifest.js.map +1 -1
  172. package/dist/src/server/persisted-config.js +1 -0
  173. package/dist/src/server/persisted-config.js.map +1 -1
  174. package/dist/src/shared/messages.js +93 -3
  175. package/dist/src/shared/messages.js.map +1 -1
  176. package/dist/src/utils/executable.js +6 -3
  177. package/dist/src/utils/executable.js.map +1 -1
  178. package/package.json +3 -3
@@ -5,13 +5,14 @@ import os from "node:os";
5
5
  import path from "node:path";
6
6
  import { mapClaudeCanceledToolCall, mapClaudeCompletedToolCall, mapClaudeFailedToolCall, mapClaudeRunningToolCall, } from "./tool-call-mapper.js";
7
7
  import { mapTaskNotificationSystemRecordToToolCall, mapTaskNotificationUserContentToToolCall, } from "./task-notification-tool-call.js";
8
- import { getClaudeModels, normalizeClaudeRuntimeModelId } from "./models.js";
8
+ import { getClaudeModelsWithSettings, normalizeClaudeRuntimeModelId } from "./models.js";
9
9
  import { parsePartialJsonObject } from "./partial-json.js";
10
10
  import { ClaudeSidechainTracker } from "./sidechain-tracker.js";
11
11
  import { formatDiagnosticStatus, formatProviderDiagnostic, formatProviderDiagnosticError, toDiagnosticErrorMessage, } from "../diagnostic-utils.js";
12
12
  import { appendOrReplaceGrowingAssistantMessage, runProviderTurn } from "../provider-runner.js";
13
13
  import { renderPromptAttachmentAsText } from "../../prompt-attachments.js";
14
14
  import { claudeQuery } from "./query.js";
15
+ import { normalizeProviderReplayTimestamp } from "../../provider-history-timestamps.js";
15
16
  import { getAgentStreamEventTurnId, } from "../../agent-sdk-types.js";
16
17
  import { createProviderEnv, createProviderEnvSpec, } from "../../provider-launch-config.js";
17
18
  import { findExecutable, isCommandAvailable } from "../../../../utils/executable.js";
@@ -19,7 +20,11 @@ import { withTimeout } from "../../../../utils/promise-timeout.js";
19
20
  import { execCommand } from "../../../../utils/spawn.js";
20
21
  import { getOrchestratorModeInstructions } from "../../orchestrator-instructions.js";
21
22
  const fsPromises = promises;
22
- const CLAUDE_SETTING_SOURCES = ["user", "project"];
23
+ const CLAUDE_SETTING_SOURCES = [
24
+ "user",
25
+ "project",
26
+ "local",
27
+ ];
23
28
  function readNonEmptyString(value) {
24
29
  return typeof value === "string" && value.trim().length > 0 ? value : null;
25
30
  }
@@ -91,6 +96,11 @@ const DEFAULT_MODES = [
91
96
  label: "Always Ask",
92
97
  description: "Prompts for permission the first time a tool is used",
93
98
  },
99
+ {
100
+ id: "auto",
101
+ label: "Auto mode",
102
+ description: "Uses a model classifier to review permission prompts automatically",
103
+ },
94
104
  {
95
105
  id: "acceptEdits",
96
106
  label: "Accept File Edits",
@@ -434,6 +444,34 @@ function isMcpServersRecord(value) {
434
444
  function isPermissionMode(value) {
435
445
  return typeof value === "string" && VALID_CLAUDE_MODES.has(value);
436
446
  }
447
+ function isTruthyEnvValue(value) {
448
+ const normalized = value?.trim().toLowerCase();
449
+ return (normalized !== undefined &&
450
+ normalized.length > 0 &&
451
+ normalized !== "0" &&
452
+ normalized !== "false" &&
453
+ normalized !== "no" &&
454
+ normalized !== "off");
455
+ }
456
+ function detectIneligibleAutoModeTransport(env) {
457
+ if (isTruthyEnvValue(env.CLAUDE_CODE_USE_BEDROCK)) {
458
+ return "Bedrock";
459
+ }
460
+ if (isTruthyEnvValue(env.CLAUDE_CODE_USE_VERTEX)) {
461
+ return "Vertex";
462
+ }
463
+ return null;
464
+ }
465
+ function assertClaudeAutoModeEligible(mode, env) {
466
+ if (mode !== "auto") {
467
+ return;
468
+ }
469
+ const transport = detectIneligibleAutoModeTransport(env);
470
+ if (transport === null) {
471
+ return;
472
+ }
473
+ throw new Error(`Claude Auto mode requires the Anthropic API and is not supported when Claude Code uses ${transport}. Select another permission mode or unset the ${transport === "Bedrock" ? "CLAUDE_CODE_USE_BEDROCK" : "CLAUDE_CODE_USE_VERTEX"} environment variable.`);
474
+ }
437
475
  function coerceSessionMetadata(metadata) {
438
476
  if (!isMetadata(metadata)) {
439
477
  return {};
@@ -885,8 +923,8 @@ export class ClaudeAgentClient {
885
923
  });
886
924
  }
887
925
  async listModels(_options) {
888
- // Claude exposes a static catalog here; cwd/force are intentionally irrelevant.
889
- return getClaudeModels();
926
+ // Claude exposes a global catalog here; cwd/force are intentionally irrelevant.
927
+ return await getClaudeModelsWithSettings(this.logger);
890
928
  }
891
929
  async listPersistedAgents(options) {
892
930
  const configDir = process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude");
@@ -1360,8 +1398,13 @@ class ClaudeAgentSession {
1360
1398
  const history = this.persistedHistory;
1361
1399
  this.persistedHistory = [];
1362
1400
  this.historyPending = false;
1363
- for (const item of history) {
1364
- yield { type: "timeline", item, provider: "claude" };
1401
+ for (const entry of history) {
1402
+ yield {
1403
+ type: "timeline",
1404
+ item: entry.item,
1405
+ provider: "claude",
1406
+ timestamp: entry.timestamp,
1407
+ };
1365
1408
  }
1366
1409
  }
1367
1410
  async getAvailableModes() {
@@ -1377,6 +1420,7 @@ class ClaudeAgentSession {
1377
1420
  throw new Error(`Invalid mode '${modeId}' for Claude provider. Valid modes: ${validModesList}`);
1378
1421
  }
1379
1422
  const normalized = isPermissionMode(modeId) ? modeId : "default";
1423
+ assertClaudeAutoModeEligible(normalized, this.buildSdkEnv(this.config.extra?.claude));
1380
1424
  const previousMode = this.currentMode;
1381
1425
  const activeQuery = await this.ensureQuery();
1382
1426
  await activeQuery.setPermissionMode(normalized);
@@ -1681,9 +1725,9 @@ class ClaudeAgentSession {
1681
1725
  pushUnique(historyIds[idx]);
1682
1726
  }
1683
1727
  for (let idx = this.persistedHistory.length - 1; idx >= 0; idx -= 1) {
1684
- const item = this.persistedHistory[idx];
1685
- if (item?.type === "user_message") {
1686
- pushUnique(item.messageId);
1728
+ const entry = this.persistedHistory[idx];
1729
+ if (entry?.item.type === "user_message") {
1730
+ pushUnique(entry.item.messageId);
1687
1731
  }
1688
1732
  }
1689
1733
  for (let idx = this.userMessageIds.length - 1; idx >= 0; idx -= 1) {
@@ -1820,11 +1864,8 @@ class ClaudeAgentSession {
1820
1864
  .filter((entry) => typeof entry === "string" && entry.length > 0)
1821
1865
  .join("\n\n");
1822
1866
  }
1823
- async buildOptions() {
1824
- const { thinking, effort } = this.resolveThinkingConfig();
1825
- const appendedSystemPrompt = this.buildAppendedSystemPrompt();
1826
- const extraClaudeOptions = this.config.extra?.claude;
1827
- const sdkEnv = createProviderEnv({
1867
+ buildSdkEnv(extraClaudeOptions) {
1868
+ return createProviderEnv({
1828
1869
  baseEnv: process.env,
1829
1870
  runtimeSettings: this.runtimeSettings,
1830
1871
  overlays: [
@@ -1837,6 +1878,13 @@ class ClaudeAgentSession {
1837
1878
  this.launchEnv,
1838
1879
  ],
1839
1880
  });
1881
+ }
1882
+ async buildOptions() {
1883
+ const { thinking, effort } = this.resolveThinkingConfig();
1884
+ const appendedSystemPrompt = this.buildAppendedSystemPrompt();
1885
+ const extraClaudeOptions = this.config.extra?.claude;
1886
+ const sdkEnv = this.buildSdkEnv(extraClaudeOptions);
1887
+ assertClaudeAutoModeEligible(this.currentMode, sdkEnv);
1840
1888
  const claudeBinary = await this.resolveBinary();
1841
1889
  this.logger.debug({
1842
1890
  claudeBinary,
@@ -2464,29 +2512,7 @@ class ClaudeAgentSession {
2464
2512
  return;
2465
2513
  }
2466
2514
  if (message.subtype === "task_notification") {
2467
- // TODO: subagent timelines are best-effort. Subagent task_notifications
2468
- // arrive without parent_tool_use_id but with tool_use_id pointing at the
2469
- // parent's Task call, so they slip past the sidechain router and pollute
2470
- // the parent timeline. Drop them here; eventually thread them into the
2471
- // parent Task tool call's sub_agent log instead.
2472
- const taskUseId = message.tool_use_id;
2473
- const cachedTool = taskUseId ? this.toolUseCache.get(taskUseId) : undefined;
2474
- if (cachedTool?.name === "Task") {
2475
- return;
2476
- }
2477
- const taskNotificationItem = mapTaskNotificationSystemRecordToToolCall(message);
2478
- if (taskNotificationItem) {
2479
- events.push({
2480
- type: "timeline",
2481
- item: taskNotificationItem,
2482
- provider: "claude",
2483
- });
2484
- }
2485
- const usage = readUsageFromTaskNotification(message);
2486
- if (typeof usage === "number") {
2487
- this.lastContextWindowUsedTokens = usage;
2488
- events.push(this.createUsageUpdatedEvent(usage));
2489
- }
2515
+ this.appendTaskNotificationEvents(message, events);
2490
2516
  return;
2491
2517
  }
2492
2518
  if (message.subtype === "task_progress") {
@@ -2497,6 +2523,31 @@ class ClaudeAgentSession {
2497
2523
  }
2498
2524
  }
2499
2525
  }
2526
+ appendTaskNotificationEvents(message, events) {
2527
+ // TODO: subagent timelines are best-effort. Subagent task_notifications
2528
+ // arrive without parent_tool_use_id but with tool_use_id pointing at the
2529
+ // parent's Task call, so they slip past the sidechain router and pollute
2530
+ // the parent timeline. Drop them here; eventually thread them into the
2531
+ // parent Task tool call's sub_agent log instead.
2532
+ const taskUseId = message.tool_use_id;
2533
+ const cachedTool = taskUseId ? this.toolUseCache.get(taskUseId) : undefined;
2534
+ if (cachedTool?.name === "Task") {
2535
+ return;
2536
+ }
2537
+ const taskNotificationItem = mapTaskNotificationSystemRecordToToolCall(message);
2538
+ if (taskNotificationItem) {
2539
+ events.push({
2540
+ type: "timeline",
2541
+ item: taskNotificationItem,
2542
+ provider: "claude",
2543
+ });
2544
+ }
2545
+ const usage = readUsageFromTaskNotification(message);
2546
+ if (typeof usage === "number") {
2547
+ this.lastContextWindowUsedTokens = usage;
2548
+ events.push(this.createUsageUpdatedEvent(usage));
2549
+ }
2550
+ }
2500
2551
  appendUserMessageEvents(message, events) {
2501
2552
  if (isSyntheticUserEntry(message)) {
2502
2553
  return;
@@ -2570,6 +2621,24 @@ class ClaudeAgentSession {
2570
2621
  appendResultEvents(message, events) {
2571
2622
  const usage = this.convertUsage(message, message.modelUsage);
2572
2623
  if (message.subtype === "success") {
2624
+ // Built-in slash commands (e.g. /voice, /usage, "Unknown command: …")
2625
+ // run client-side in the Claude CLI with no model turn — output_tokens
2626
+ // is 0 and the user-visible text is carried in `result`. Surface it as
2627
+ // an assistant message so the turn doesn't end silently. Normal turns
2628
+ // have output_tokens > 0 and their text is already in the stream.
2629
+ const resultText = typeof message.result === "string" ? message.result.trim() : "";
2630
+ const outputTokens = message.usage?.output_tokens;
2631
+ if (resultText.length > 0 && outputTokens === 0) {
2632
+ events.push({
2633
+ type: "timeline",
2634
+ provider: "claude",
2635
+ item: {
2636
+ type: "assistant_message",
2637
+ text: resultText,
2638
+ messageId: message.uuid,
2639
+ },
2640
+ });
2641
+ }
2573
2642
  events.push({ type: "turn_completed", provider: "claude", usage });
2574
2643
  return;
2575
2644
  }
@@ -2886,9 +2955,13 @@ class ClaudeAgentSession {
2886
2955
  if (entry.type === "user" && typeof entry.uuid === "string") {
2887
2956
  this.rememberUserMessageId(entry.uuid);
2888
2957
  }
2958
+ const historyTimestamp = normalizeProviderReplayTimestamp(entry.timestamp);
2889
2959
  const items = this.convertHistoryEntry(entry);
2890
2960
  if (items.length > 0) {
2891
- timeline.push(...items);
2961
+ timeline.push(...items.map((item) => ({
2962
+ item,
2963
+ timestamp: historyTimestamp ?? undefined,
2964
+ })));
2892
2965
  }
2893
2966
  }
2894
2967
  resolveHistoryPath(sessionId) {