@getpaseo/server 0.1.61 → 0.1.63

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 (464) hide show
  1. package/README.md +4 -0
  2. package/dist/server/client/daemon-client-runtime-metrics.d.ts +6 -6
  3. package/dist/server/client/daemon-client-runtime-metrics.d.ts.map +1 -1
  4. package/dist/server/client/daemon-client-transport-types.d.ts +13 -13
  5. package/dist/server/client/daemon-client-transport-types.d.ts.map +1 -1
  6. package/dist/server/client/daemon-client-websocket-transport.d.ts +1 -1
  7. package/dist/server/client/daemon-client-websocket-transport.d.ts.map +1 -1
  8. package/dist/server/client/daemon-client-websocket-transport.js +5 -4
  9. package/dist/server/client/daemon-client-websocket-transport.js.map +1 -1
  10. package/dist/server/client/daemon-client.d.ts +59 -37
  11. package/dist/server/client/daemon-client.d.ts.map +1 -1
  12. package/dist/server/client/daemon-client.js +62 -17
  13. package/dist/server/client/daemon-client.js.map +1 -1
  14. package/dist/server/server/agent/agent-loading.d.ts.map +1 -1
  15. package/dist/server/server/agent/agent-loading.js +5 -3
  16. package/dist/server/server/agent/agent-loading.js.map +1 -1
  17. package/dist/server/server/agent/agent-manager.d.ts +45 -19
  18. package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
  19. package/dist/server/server/agent/agent-manager.js +393 -290
  20. package/dist/server/server/agent/agent-manager.js.map +1 -1
  21. package/dist/server/server/agent/agent-metadata-generator.d.ts +6 -6
  22. package/dist/server/server/agent/agent-metadata-generator.d.ts.map +1 -1
  23. package/dist/server/server/agent/agent-metadata-generator.js +46 -38
  24. package/dist/server/server/agent/agent-metadata-generator.js.map +1 -1
  25. package/dist/server/server/agent/agent-projections.d.ts +4 -6
  26. package/dist/server/server/agent/agent-projections.d.ts.map +1 -1
  27. package/dist/server/server/agent/agent-projections.js +59 -65
  28. package/dist/server/server/agent/agent-projections.js.map +1 -1
  29. package/dist/server/server/agent/agent-response-loop.d.ts +4 -4
  30. package/dist/server/server/agent/agent-response-loop.d.ts.map +1 -1
  31. package/dist/server/server/agent/agent-response-loop.js +58 -45
  32. package/dist/server/server/agent/agent-response-loop.js.map +1 -1
  33. package/dist/server/server/agent/agent-sdk-types.d.ts +43 -40
  34. package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -1
  35. package/dist/server/server/agent/agent-sdk-types.js.map +1 -1
  36. package/dist/server/server/agent/agent-storage.d.ts +2 -2
  37. package/dist/server/server/agent/agent-storage.d.ts.map +1 -1
  38. package/dist/server/server/agent/agent-storage.js +29 -36
  39. package/dist/server/server/agent/agent-storage.js.map +1 -1
  40. package/dist/server/server/agent/agent-stream-coalescer.d.ts +6 -6
  41. package/dist/server/server/agent/agent-stream-coalescer.d.ts.map +1 -1
  42. package/dist/server/server/agent/agent-timeline-store-types.d.ts +10 -10
  43. package/dist/server/server/agent/agent-timeline-store-types.d.ts.map +1 -1
  44. package/dist/server/server/agent/agent-timeline-store.d.ts +2 -2
  45. package/dist/server/server/agent/agent-timeline-store.d.ts.map +1 -1
  46. package/dist/server/server/agent/agent-timeline-store.js +85 -64
  47. package/dist/server/server/agent/agent-timeline-store.js.map +1 -1
  48. package/dist/server/server/agent/mcp-server.d.ts.map +1 -1
  49. package/dist/server/server/agent/mcp-server.js +185 -148
  50. package/dist/server/server/agent/mcp-server.js.map +1 -1
  51. package/dist/server/server/agent/mcp-shared.d.ts +9 -2
  52. package/dist/server/server/agent/mcp-shared.d.ts.map +1 -1
  53. package/dist/server/server/agent/mcp-shared.js +2 -0
  54. package/dist/server/server/agent/mcp-shared.js.map +1 -1
  55. package/dist/server/server/agent/model-resolver.d.ts +2 -2
  56. package/dist/server/server/agent/model-resolver.d.ts.map +1 -1
  57. package/dist/server/server/agent/model-resolver.js +9 -5
  58. package/dist/server/server/agent/model-resolver.js.map +1 -1
  59. package/dist/server/server/agent/provider-launch-config.d.ts +28 -17
  60. package/dist/server/server/agent/provider-launch-config.d.ts.map +1 -1
  61. package/dist/server/server/agent/provider-launch-config.js +20 -9
  62. package/dist/server/server/agent/provider-launch-config.js.map +1 -1
  63. package/dist/server/server/agent/provider-registry.d.ts +4 -2
  64. package/dist/server/server/agent/provider-registry.d.ts.map +1 -1
  65. package/dist/server/server/agent/provider-registry.js +24 -21
  66. package/dist/server/server/agent/provider-registry.js.map +1 -1
  67. package/dist/server/server/agent/provider-snapshot-manager.d.ts +6 -5
  68. package/dist/server/server/agent/provider-snapshot-manager.d.ts.map +1 -1
  69. package/dist/server/server/agent/provider-snapshot-manager.js +40 -31
  70. package/dist/server/server/agent/provider-snapshot-manager.js.map +1 -1
  71. package/dist/server/server/agent/providers/acp-agent.d.ts +11 -12
  72. package/dist/server/server/agent/providers/acp-agent.d.ts.map +1 -1
  73. package/dist/server/server/agent/providers/acp-agent.js +148 -122
  74. package/dist/server/server/agent/providers/acp-agent.js.map +1 -1
  75. package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts +2 -0
  76. package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts.map +1 -1
  77. package/dist/server/server/agent/providers/claude/sidechain-tracker.js +47 -45
  78. package/dist/server/server/agent/providers/claude/sidechain-tracker.js.map +1 -1
  79. package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts +2 -2
  80. package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts.map +1 -1
  81. package/dist/server/server/agent/providers/claude/task-notification-tool-call.js +10 -5
  82. package/dist/server/server/agent/providers/claude/task-notification-tool-call.js.map +1 -1
  83. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts.map +1 -1
  84. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js +11 -2
  85. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js.map +1 -1
  86. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts +2 -2
  87. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts.map +1 -1
  88. package/dist/server/server/agent/providers/claude/tool-call-mapper.js +20 -13
  89. package/dist/server/server/agent/providers/claude/tool-call-mapper.js.map +1 -1
  90. package/dist/server/server/agent/providers/claude-agent.d.ts +20 -8
  91. package/dist/server/server/agent/providers/claude-agent.d.ts.map +1 -1
  92. package/dist/server/server/agent/providers/claude-agent.js +610 -460
  93. package/dist/server/server/agent/providers/claude-agent.js.map +1 -1
  94. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts +2 -2
  95. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts.map +1 -1
  96. package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts +2 -2
  97. package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts.map +1 -1
  98. package/dist/server/server/agent/providers/codex/tool-call-mapper.js +49 -44
  99. package/dist/server/server/agent/providers/codex/tool-call-mapper.js.map +1 -1
  100. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +27 -8
  101. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -1
  102. package/dist/server/server/agent/providers/codex-app-server-agent.js +564 -492
  103. package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -1
  104. package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts +2 -2
  105. package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts.map +1 -1
  106. package/dist/server/server/agent/providers/codex-rollout-timeline.js +58 -47
  107. package/dist/server/server/agent/providers/codex-rollout-timeline.js.map +1 -1
  108. package/dist/server/server/agent/providers/copilot-acp-agent.d.ts +2 -2
  109. package/dist/server/server/agent/providers/copilot-acp-agent.d.ts.map +1 -1
  110. package/dist/server/server/agent/providers/diagnostic-utils.d.ts +3 -3
  111. package/dist/server/server/agent/providers/diagnostic-utils.d.ts.map +1 -1
  112. package/dist/server/server/agent/providers/diagnostic-utils.js +82 -9
  113. package/dist/server/server/agent/providers/diagnostic-utils.js.map +1 -1
  114. package/dist/server/server/agent/providers/generic-acp-agent.d.ts +2 -2
  115. package/dist/server/server/agent/providers/generic-acp-agent.d.ts.map +1 -1
  116. package/dist/server/server/agent/providers/mock-load-test-agent.d.ts.map +1 -1
  117. package/dist/server/server/agent/providers/mock-load-test-agent.js.map +1 -1
  118. package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts +2 -2
  119. package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts.map +1 -1
  120. package/dist/server/server/agent/providers/opencode-agent.d.ts +2 -2
  121. package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
  122. package/dist/server/server/agent/providers/opencode-agent.js +385 -360
  123. package/dist/server/server/agent/providers/opencode-agent.js.map +1 -1
  124. package/dist/server/server/agent/providers/pi-direct-agent.d.ts +1 -0
  125. package/dist/server/server/agent/providers/pi-direct-agent.d.ts.map +1 -1
  126. package/dist/server/server/agent/providers/pi-direct-agent.js +109 -140
  127. package/dist/server/server/agent/providers/pi-direct-agent.js.map +1 -1
  128. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.d.ts.map +1 -1
  129. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.js +3 -1
  130. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.js.map +1 -1
  131. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +3 -3
  132. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts.map +1 -1
  133. package/dist/server/server/agent/providers/tool-call-detail-primitives.js +102 -73
  134. package/dist/server/server/agent/providers/tool-call-detail-primitives.js.map +1 -1
  135. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +2 -2
  136. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts.map +1 -1
  137. package/dist/server/server/agent/stt-manager.d.ts.map +1 -1
  138. package/dist/server/server/agent/stt-manager.js +63 -53
  139. package/dist/server/server/agent/stt-manager.js.map +1 -1
  140. package/dist/server/server/agent/timeline-projection.d.ts +6 -6
  141. package/dist/server/server/agent/timeline-projection.d.ts.map +1 -1
  142. package/dist/server/server/agent/timeline-projection.js +11 -6
  143. package/dist/server/server/agent/timeline-projection.js.map +1 -1
  144. package/dist/server/server/agent/tts-manager.d.ts.map +1 -1
  145. package/dist/server/server/agent/tts-manager.js +1 -0
  146. package/dist/server/server/agent/tts-manager.js.map +1 -1
  147. package/dist/server/server/agent-attention-policy.d.ts +2 -2
  148. package/dist/server/server/agent-attention-policy.d.ts.map +1 -1
  149. package/dist/server/server/bootstrap.d.ts +4 -4
  150. package/dist/server/server/bootstrap.d.ts.map +1 -1
  151. package/dist/server/server/bootstrap.js +493 -485
  152. package/dist/server/server/bootstrap.js.map +1 -1
  153. package/dist/server/server/chat/chat-service.d.ts +1 -1
  154. package/dist/server/server/chat/chat-service.d.ts.map +1 -1
  155. package/dist/server/server/chat/chat-service.js +3 -3
  156. package/dist/server/server/chat/chat-service.js.map +1 -1
  157. package/dist/server/server/checkout-diff-manager.d.ts +2 -2
  158. package/dist/server/server/checkout-diff-manager.d.ts.map +1 -1
  159. package/dist/server/server/checkout-git-utils.d.ts +5 -3
  160. package/dist/server/server/checkout-git-utils.d.ts.map +1 -1
  161. package/dist/server/server/checkout-git-utils.js +1 -2
  162. package/dist/server/server/checkout-git-utils.js.map +1 -1
  163. package/dist/server/server/config.d.ts.map +1 -1
  164. package/dist/server/server/config.js +68 -39
  165. package/dist/server/server/config.js.map +1 -1
  166. package/dist/server/server/connection-offer.d.ts +2 -2
  167. package/dist/server/server/connection-offer.d.ts.map +1 -1
  168. package/dist/server/server/daemon-config-store.d.ts +5 -3
  169. package/dist/server/server/daemon-config-store.d.ts.map +1 -1
  170. package/dist/server/server/daemon-config-store.js +26 -0
  171. package/dist/server/server/daemon-config-store.js.map +1 -1
  172. package/dist/server/server/daemon-keypair.d.ts +2 -2
  173. package/dist/server/server/daemon-keypair.d.ts.map +1 -1
  174. package/dist/server/server/editor-targets.d.ts +4 -4
  175. package/dist/server/server/editor-targets.d.ts.map +1 -1
  176. package/dist/server/server/editor-targets.js +11 -15
  177. package/dist/server/server/editor-targets.js.map +1 -1
  178. package/dist/server/server/exports.d.ts +3 -3
  179. package/dist/server/server/exports.d.ts.map +1 -1
  180. package/dist/server/server/exports.js +1 -3
  181. package/dist/server/server/exports.js.map +1 -1
  182. package/dist/server/server/file-download/token-store.d.ts +4 -4
  183. package/dist/server/server/file-download/token-store.d.ts.map +1 -1
  184. package/dist/server/server/index.js +16 -12
  185. package/dist/server/server/index.js.map +1 -1
  186. package/dist/server/server/logger.d.ts +4 -4
  187. package/dist/server/server/logger.d.ts.map +1 -1
  188. package/dist/server/server/logger.js +26 -20
  189. package/dist/server/server/logger.js.map +1 -1
  190. package/dist/server/server/loop/rpc-schemas.d.ts +52 -52
  191. package/dist/server/server/loop-service.d.ts +13 -12
  192. package/dist/server/server/loop-service.d.ts.map +1 -1
  193. package/dist/server/server/loop-service.js +22 -18
  194. package/dist/server/server/loop-service.js.map +1 -1
  195. package/dist/server/server/package-version.d.ts +2 -2
  196. package/dist/server/server/package-version.d.ts.map +1 -1
  197. package/dist/server/server/package-version.js +19 -17
  198. package/dist/server/server/package-version.js.map +1 -1
  199. package/dist/server/server/pairing-offer.d.ts +2 -2
  200. package/dist/server/server/pairing-offer.d.ts.map +1 -1
  201. package/dist/server/server/paseo-env.d.ts +9 -0
  202. package/dist/server/server/paseo-env.d.ts.map +1 -0
  203. package/dist/server/server/paseo-env.js +70 -0
  204. package/dist/server/server/paseo-env.js.map +1 -0
  205. package/dist/server/server/paseo-worktree-archive-service.d.ts +4 -4
  206. package/dist/server/server/paseo-worktree-archive-service.d.ts.map +1 -1
  207. package/dist/server/server/paseo-worktree-archive-service.js +11 -11
  208. package/dist/server/server/paseo-worktree-archive-service.js.map +1 -1
  209. package/dist/server/server/persisted-config.d.ts +62 -62
  210. package/dist/server/server/persisted-config.d.ts.map +1 -1
  211. package/dist/server/server/persisted-config.js +4 -4
  212. package/dist/server/server/persisted-config.js.map +1 -1
  213. package/dist/server/server/persistence-hooks.d.ts +8 -9
  214. package/dist/server/server/persistence-hooks.d.ts.map +1 -1
  215. package/dist/server/server/persistence-hooks.js +4 -12
  216. package/dist/server/server/persistence-hooks.js.map +1 -1
  217. package/dist/server/server/pid-lock.js.map +1 -1
  218. package/dist/server/server/push/push-service.d.ts.map +1 -1
  219. package/dist/server/server/push/push-service.js +1 -3
  220. package/dist/server/server/push/push-service.js.map +1 -1
  221. package/dist/server/server/relay-transport.d.ts +8 -8
  222. package/dist/server/server/relay-transport.d.ts.map +1 -1
  223. package/dist/server/server/relay-transport.js +27 -16
  224. package/dist/server/server/relay-transport.js.map +1 -1
  225. package/dist/server/server/schedule/service.d.ts.map +1 -1
  226. package/dist/server/server/schedule/service.js +2 -2
  227. package/dist/server/server/schedule/service.js.map +1 -1
  228. package/dist/server/server/script-health-monitor.d.ts.map +1 -1
  229. package/dist/server/server/script-health-monitor.js +7 -6
  230. package/dist/server/server/script-health-monitor.js.map +1 -1
  231. package/dist/server/server/script-proxy.js +1 -1
  232. package/dist/server/server/script-proxy.js.map +1 -1
  233. package/dist/server/server/script-status-projection.d.ts +4 -4
  234. package/dist/server/server/script-status-projection.d.ts.map +1 -1
  235. package/dist/server/server/script-status-projection.js +54 -44
  236. package/dist/server/server/script-status-projection.js.map +1 -1
  237. package/dist/server/server/server-id.d.ts +4 -4
  238. package/dist/server/server/server-id.d.ts.map +1 -1
  239. package/dist/server/server/session.d.ts +50 -19
  240. package/dist/server/server/session.d.ts.map +1 -1
  241. package/dist/server/server/session.js +1116 -783
  242. package/dist/server/server/session.js.map +1 -1
  243. package/dist/server/server/speech/audio.js +1 -1
  244. package/dist/server/server/speech/audio.js.map +1 -1
  245. package/dist/server/server/speech/providers/local/config.d.ts +6 -6
  246. package/dist/server/server/speech/providers/local/config.d.ts.map +1 -1
  247. package/dist/server/server/speech/providers/local/config.js +41 -16
  248. package/dist/server/server/speech/providers/local/config.js.map +1 -1
  249. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.d.ts +2 -2
  250. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.d.ts.map +1 -1
  251. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.js +42 -19
  252. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.js.map +1 -1
  253. package/dist/server/server/speech/providers/local/runtime.d.ts +4 -4
  254. package/dist/server/server/speech/providers/local/runtime.d.ts.map +1 -1
  255. package/dist/server/server/speech/providers/local/runtime.js +108 -77
  256. package/dist/server/server/speech/providers/local/runtime.js.map +1 -1
  257. package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts +2 -2
  258. package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts.map +1 -1
  259. package/dist/server/server/speech/providers/local/sherpa/model-catalog.js +1 -4
  260. package/dist/server/server/speech/providers/local/sherpa/model-catalog.js.map +1 -1
  261. package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts +2 -2
  262. package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts.map +1 -1
  263. package/dist/server/server/speech/providers/local/sherpa/model-downloader.js +19 -19
  264. package/dist/server/server/speech/providers/local/sherpa/model-downloader.js.map +1 -1
  265. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts +28 -7
  266. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts.map +1 -1
  267. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js.map +1 -1
  268. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.d.ts +23 -4
  269. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.d.ts.map +1 -1
  270. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.js +35 -28
  271. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.js.map +1 -1
  272. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.d.ts +5 -5
  273. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.d.ts.map +1 -1
  274. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts +7 -7
  275. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts.map +1 -1
  276. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js +5 -0
  277. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js.map +1 -1
  278. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.d.ts.map +1 -1
  279. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js +3 -1
  280. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js.map +1 -1
  281. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts +2 -2
  282. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts.map +1 -1
  283. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js +3 -1
  284. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js.map +1 -1
  285. package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.d.ts.map +1 -1
  286. package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.js +10 -4
  287. package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.js.map +1 -1
  288. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.d.ts +2 -2
  289. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.d.ts.map +1 -1
  290. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.d.ts +2 -2
  291. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.d.ts.map +1 -1
  292. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.js +4 -1
  293. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.js.map +1 -1
  294. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts +2 -2
  295. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts.map +1 -1
  296. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js +18 -11
  297. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js.map +1 -1
  298. package/dist/server/server/speech/providers/openai/config.d.ts +2 -2
  299. package/dist/server/server/speech/providers/openai/config.d.ts.map +1 -1
  300. package/dist/server/server/speech/providers/openai/config.js +58 -31
  301. package/dist/server/server/speech/providers/openai/config.js.map +1 -1
  302. package/dist/server/server/speech/providers/openai/realtime-transcription-session.d.ts.map +1 -1
  303. package/dist/server/server/speech/providers/openai/realtime-transcription-session.js +2 -2
  304. package/dist/server/server/speech/providers/openai/realtime-transcription-session.js.map +1 -1
  305. package/dist/server/server/speech/providers/openai/runtime.d.ts +4 -4
  306. package/dist/server/server/speech/providers/openai/runtime.d.ts.map +1 -1
  307. package/dist/server/server/speech/providers/openai/runtime.js +37 -32
  308. package/dist/server/server/speech/providers/openai/runtime.js.map +1 -1
  309. package/dist/server/server/speech/providers/openai/stt.d.ts.map +1 -1
  310. package/dist/server/server/speech/providers/openai/stt.js +4 -3
  311. package/dist/server/server/speech/providers/openai/stt.js.map +1 -1
  312. package/dist/server/server/speech/providers/openai/tts.d.ts.map +1 -1
  313. package/dist/server/server/speech/providers/openai/tts.js +3 -2
  314. package/dist/server/server/speech/providers/openai/tts.js.map +1 -1
  315. package/dist/server/server/speech/speech-config-resolver.d.ts.map +1 -1
  316. package/dist/server/server/speech/speech-config-resolver.js +46 -17
  317. package/dist/server/server/speech/speech-config-resolver.js.map +1 -1
  318. package/dist/server/server/speech/speech-provider.d.ts +2 -2
  319. package/dist/server/server/speech/speech-provider.d.ts.map +1 -1
  320. package/dist/server/server/speech/speech-runtime.d.ts +6 -6
  321. package/dist/server/server/speech/speech-runtime.d.ts.map +1 -1
  322. package/dist/server/server/speech/speech-runtime.js +17 -17
  323. package/dist/server/server/speech/speech-runtime.js.map +1 -1
  324. package/dist/server/server/speech/speech-types.d.ts +2 -2
  325. package/dist/server/server/speech/speech-types.d.ts.map +1 -1
  326. package/dist/server/server/speech/turn-detection-provider.d.ts +2 -2
  327. package/dist/server/server/speech/turn-detection-provider.d.ts.map +1 -1
  328. package/dist/server/server/utils/diff-highlighter.d.ts +0 -3
  329. package/dist/server/server/utils/diff-highlighter.d.ts.map +1 -1
  330. package/dist/server/server/utils/diff-highlighter.js +67 -66
  331. package/dist/server/server/utils/diff-highlighter.js.map +1 -1
  332. package/dist/server/server/voice/voice-turn-controller.d.ts.map +1 -1
  333. package/dist/server/server/voice/voice-turn-controller.js +1 -0
  334. package/dist/server/server/voice/voice-turn-controller.js.map +1 -1
  335. package/dist/server/server/voice-types.d.ts +2 -2
  336. package/dist/server/server/voice-types.d.ts.map +1 -1
  337. package/dist/server/server/websocket-server.d.ts +33 -23
  338. package/dist/server/server/websocket-server.d.ts.map +1 -1
  339. package/dist/server/server/websocket-server.js +349 -241
  340. package/dist/server/server/websocket-server.js.map +1 -1
  341. package/dist/server/server/workspace-git-metadata.d.ts +2 -2
  342. package/dist/server/server/workspace-git-metadata.d.ts.map +1 -1
  343. package/dist/server/server/workspace-git-metadata.js +2 -32
  344. package/dist/server/server/workspace-git-metadata.js.map +1 -1
  345. package/dist/server/server/workspace-git-service.d.ts +17 -13
  346. package/dist/server/server/workspace-git-service.d.ts.map +1 -1
  347. package/dist/server/server/workspace-git-service.js +232 -140
  348. package/dist/server/server/workspace-git-service.js.map +1 -1
  349. package/dist/server/server/workspace-reconciliation-service.d.ts +5 -4
  350. package/dist/server/server/workspace-reconciliation-service.d.ts.map +1 -1
  351. package/dist/server/server/workspace-reconciliation-service.js +82 -82
  352. package/dist/server/server/workspace-reconciliation-service.js.map +1 -1
  353. package/dist/server/server/workspace-registry-bootstrap.d.ts.map +1 -1
  354. package/dist/server/server/workspace-registry-bootstrap.js +40 -33
  355. package/dist/server/server/workspace-registry-bootstrap.js.map +1 -1
  356. package/dist/server/server/workspace-registry-model.d.ts +19 -6
  357. package/dist/server/server/workspace-registry-model.d.ts.map +1 -1
  358. package/dist/server/server/workspace-registry-model.js +35 -21
  359. package/dist/server/server/workspace-registry-model.js.map +1 -1
  360. package/dist/server/server/workspace-registry.d.ts +2 -2
  361. package/dist/server/server/workspace-script-runtime-store.d.ts +2 -2
  362. package/dist/server/server/workspace-script-runtime-store.d.ts.map +1 -1
  363. package/dist/server/server/workspace-service-env.js +3 -3
  364. package/dist/server/server/workspace-service-env.js.map +1 -1
  365. package/dist/server/server/worktree-bootstrap.d.ts +4 -4
  366. package/dist/server/server/worktree-bootstrap.d.ts.map +1 -1
  367. package/dist/server/server/worktree-bootstrap.js +95 -67
  368. package/dist/server/server/worktree-bootstrap.js.map +1 -1
  369. package/dist/server/server/worktree-session.d.ts +8 -8
  370. package/dist/server/server/worktree-session.d.ts.map +1 -1
  371. package/dist/server/server/worktree-session.js +27 -19
  372. package/dist/server/server/worktree-session.js.map +1 -1
  373. package/dist/server/services/github-service.d.ts +2 -7
  374. package/dist/server/services/github-service.d.ts.map +1 -1
  375. package/dist/server/services/github-service.js +156 -157
  376. package/dist/server/services/github-service.js.map +1 -1
  377. package/dist/server/shared/agent-attention-notification.d.ts +9 -8
  378. package/dist/server/shared/agent-attention-notification.d.ts.map +1 -1
  379. package/dist/server/shared/agent-attention-notification.js +27 -17
  380. package/dist/server/shared/agent-attention-notification.js.map +1 -1
  381. package/dist/server/shared/daemon-endpoints.d.ts +2 -2
  382. package/dist/server/shared/daemon-endpoints.d.ts.map +1 -1
  383. package/dist/server/shared/daemon-endpoints.js +17 -2
  384. package/dist/server/shared/daemon-endpoints.js.map +1 -1
  385. package/dist/server/shared/messages.d.ts +21962 -3049
  386. package/dist/server/shared/messages.d.ts.map +1 -1
  387. package/dist/server/shared/messages.js +79 -2
  388. package/dist/server/shared/messages.js.map +1 -1
  389. package/dist/server/shared/terminal-stream-protocol.d.ts +2 -2
  390. package/dist/server/shared/terminal-stream-protocol.d.ts.map +1 -1
  391. package/dist/server/shared/tool-call-display.d.ts +2 -2
  392. package/dist/server/shared/tool-call-display.d.ts.map +1 -1
  393. package/dist/server/terminal/terminal-manager.d.ts.map +1 -1
  394. package/dist/server/terminal/terminal-manager.js +1 -3
  395. package/dist/server/terminal/terminal-manager.js.map +1 -1
  396. package/dist/server/terminal/terminal-output-coalescer.d.ts +6 -6
  397. package/dist/server/terminal/terminal-output-coalescer.d.ts.map +1 -1
  398. package/dist/server/terminal/terminal.d.ts +3 -2
  399. package/dist/server/terminal/terminal.d.ts.map +1 -1
  400. package/dist/server/terminal/terminal.js +57 -19
  401. package/dist/server/terminal/terminal.js.map +1 -1
  402. package/dist/server/utils/checkout-git.d.ts +13 -12
  403. package/dist/server/utils/checkout-git.d.ts.map +1 -1
  404. package/dist/server/utils/checkout-git.js +416 -282
  405. package/dist/server/utils/checkout-git.js.map +1 -1
  406. package/dist/server/utils/directory-suggestions.js +12 -33
  407. package/dist/server/utils/directory-suggestions.js.map +1 -1
  408. package/dist/server/utils/executable.d.ts +1 -14
  409. package/dist/server/utils/executable.d.ts.map +1 -1
  410. package/dist/server/utils/executable.js +13 -49
  411. package/dist/server/utils/executable.js.map +1 -1
  412. package/dist/server/utils/github-remote.d.ts +13 -0
  413. package/dist/server/utils/github-remote.d.ts.map +1 -0
  414. package/dist/server/utils/github-remote.js +128 -0
  415. package/dist/server/utils/github-remote.js.map +1 -0
  416. package/dist/server/utils/paseo-config-file.d.ts +30 -0
  417. package/dist/server/utils/paseo-config-file.d.ts.map +1 -0
  418. package/dist/server/utils/paseo-config-file.js +90 -0
  419. package/dist/server/utils/paseo-config-file.js.map +1 -0
  420. package/dist/server/utils/paseo-config-schema.d.ts +290 -0
  421. package/dist/server/utils/paseo-config-schema.d.ts.map +1 -0
  422. package/dist/server/utils/paseo-config-schema.js +60 -0
  423. package/dist/server/utils/paseo-config-schema.js.map +1 -0
  424. package/dist/server/utils/project-icon.d.ts.map +1 -1
  425. package/dist/server/utils/project-icon.js +84 -109
  426. package/dist/server/utils/project-icon.js.map +1 -1
  427. package/dist/server/utils/promise-timeout.d.ts +2 -2
  428. package/dist/server/utils/promise-timeout.d.ts.map +1 -1
  429. package/dist/server/utils/run-git-command.d.ts +3 -1
  430. package/dist/server/utils/run-git-command.d.ts.map +1 -1
  431. package/dist/server/utils/run-git-command.js +10 -1
  432. package/dist/server/utils/run-git-command.js.map +1 -1
  433. package/dist/server/utils/script-hostname.d.ts +2 -2
  434. package/dist/server/utils/script-hostname.d.ts.map +1 -1
  435. package/dist/server/utils/spawn.d.ts +10 -3
  436. package/dist/server/utils/spawn.d.ts.map +1 -1
  437. package/dist/server/utils/spawn.js +30 -5
  438. package/dist/server/utils/spawn.js.map +1 -1
  439. package/dist/server/utils/windows-command.d.ts +15 -0
  440. package/dist/server/utils/windows-command.d.ts.map +1 -0
  441. package/dist/server/utils/windows-command.js +37 -0
  442. package/dist/server/utils/windows-command.js.map +1 -0
  443. package/dist/server/utils/worktree.d.ts +10 -7
  444. package/dist/server/utils/worktree.d.ts.map +1 -1
  445. package/dist/server/utils/worktree.js +64 -55
  446. package/dist/server/utils/worktree.js.map +1 -1
  447. package/dist/src/server/pid-lock.js.map +1 -1
  448. package/package.json +15 -20
  449. package/dist/server/server/agent/llm-openai.d.ts +0 -7
  450. package/dist/server/server/agent/llm-openai.d.ts.map +0 -1
  451. package/dist/server/server/agent/llm-openai.js +0 -8
  452. package/dist/server/server/agent/llm-openai.js.map +0 -1
  453. package/dist/server/server/agent/orchestrator.d.ts +0 -12
  454. package/dist/server/server/agent/orchestrator.d.ts.map +0 -1
  455. package/dist/server/server/agent/orchestrator.js +0 -12
  456. package/dist/server/server/agent/orchestrator.js.map +0 -1
  457. package/dist/server/server/types.d.ts +0 -5
  458. package/dist/server/server/types.d.ts.map +0 -1
  459. package/dist/server/server/types.js +0 -3
  460. package/dist/server/server/types.js.map +0 -1
  461. package/dist/server/server/workspace-registry.test-helpers.d.ts +0 -37
  462. package/dist/server/server/workspace-registry.test-helpers.d.ts.map +0 -1
  463. package/dist/server/server/workspace-registry.test-helpers.js +0 -121
  464. package/dist/server/server/workspace-registry.test-helpers.js.map +0 -1
@@ -11,7 +11,7 @@ import { parsePartialJsonObject } from "./claude/partial-json.js";
11
11
  import { ClaudeSidechainTracker } from "./claude/sidechain-tracker.js";
12
12
  import { formatDiagnosticStatus, formatProviderDiagnostic, formatProviderDiagnosticError, toDiagnosticErrorMessage, } from "./diagnostic-utils.js";
13
13
  import { renderPromptAttachmentAsText } from "../prompt-attachments.js";
14
- import { applyProviderEnv } from "../provider-launch-config.js";
14
+ import { createProviderEnv, createProviderEnvSpec, } from "../provider-launch-config.js";
15
15
  import { findExecutable, isCommandAvailable } from "../../../utils/executable.js";
16
16
  import { withTimeout } from "../../../utils/promise-timeout.js";
17
17
  import { execCommand, spawnProcess } from "../../../utils/spawn.js";
@@ -59,6 +59,38 @@ const INTERRUPT_TOOL_USE_PLACEHOLDER = "[Request interrupted by user for tool us
59
59
  const INTERRUPT_PLACEHOLDER_PATTERN = /^\[Request interrupted by user(?:[^\]]*)\]$/;
60
60
  const NO_RESPONSE_REQUESTED_PLACEHOLDER = "No response requested.";
61
61
  const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
62
+ function resolvePathEnvKey() {
63
+ if (process.env["Path"] !== undefined)
64
+ return "Path";
65
+ if (process.env["PATH"] !== undefined)
66
+ return "PATH";
67
+ return null;
68
+ }
69
+ function errorToMessageString(error) {
70
+ if (typeof error === "string")
71
+ return error;
72
+ if (error instanceof Error)
73
+ return error.message;
74
+ return "";
75
+ }
76
+ function firstStringField(input, primaryKey, secondaryKey) {
77
+ const primary = input[primaryKey];
78
+ if (typeof primary === "string")
79
+ return primary;
80
+ const secondary = input[secondaryKey];
81
+ if (typeof secondary === "string")
82
+ return secondary;
83
+ return undefined;
84
+ }
85
+ function extractSessionIdRaw(msg) {
86
+ if (typeof msg.session_id === "string")
87
+ return msg.session_id;
88
+ if (typeof msg.sessionId === "string")
89
+ return msg.sessionId;
90
+ if (typeof msg.session?.id === "string")
91
+ return msg.session.id;
92
+ return "";
93
+ }
62
94
  function resolveClaudeSpawnCommand(spawnOptions, runtimeSettings) {
63
95
  const commandConfig = runtimeSettings?.command;
64
96
  if (!commandConfig || commandConfig.mode === "default") {
@@ -92,10 +124,11 @@ function applyRuntimeSettingsToClaudeOptions(options, runtimeSettings, launchEnv
92
124
  const command = isDefaultRuntime ? process.execPath : resolved.command;
93
125
  const child = spawnProcess(command, resolved.args, {
94
126
  cwd: spawnOptions.cwd,
95
- env: {
96
- ...applyProviderEnv(spawnOptions.env, runtimeSettings),
97
- ...(launchEnv ?? {}),
98
- },
127
+ ...createProviderEnvSpec({
128
+ baseEnv: spawnOptions.env,
129
+ runtimeSettings,
130
+ overlays: [launchEnv],
131
+ }),
99
132
  signal: spawnOptions.signal,
100
133
  stdio: ["pipe", "pipe", "pipe"],
101
134
  // Bypass cmd.exe on Windows: the SDK passes --mcp-config with inline JSON
@@ -332,6 +365,26 @@ export function extractUserMessageText(content) {
332
365
  function isMetadata(value) {
333
366
  return typeof value === "object" && value !== null;
334
367
  }
368
+ function createDefaultToolUseCacheEntry(id, block) {
369
+ const nameFromBlock = typeof block.name === "string" && block.name.length > 0 ? block.name : "tool";
370
+ let server;
371
+ if (typeof block.server === "string" && block.server.length > 0) {
372
+ server = block.server;
373
+ }
374
+ else if (typeof block.name === "string" && block.name.length > 0) {
375
+ server = block.name;
376
+ }
377
+ else {
378
+ server = "tool";
379
+ }
380
+ return {
381
+ id,
382
+ name: nameFromBlock,
383
+ server,
384
+ classification: "generic",
385
+ started: false,
386
+ };
387
+ }
335
388
  function readTrimmedString(value) {
336
389
  if (typeof value !== "string") {
337
390
  return undefined;
@@ -728,31 +781,44 @@ function isSyntheticUserEntry(entry) {
728
781
  const candidate = entry;
729
782
  return candidate.isSynthetic === true || candidate.isMeta === true;
730
783
  }
784
+ function firstTrimmedString(sources) {
785
+ for (const source of sources) {
786
+ const value = readTrimmedString(source);
787
+ if (value) {
788
+ return value;
789
+ }
790
+ }
791
+ return null;
792
+ }
731
793
  export function readEventIdentifiers(message) {
732
794
  const root = message;
733
795
  const messageType = readTrimmedString(root.type);
734
796
  const streamEvent = root.event;
735
797
  const streamEventMessage = streamEvent?.message;
736
798
  const messageContainer = root.message;
799
+ const messageIdFromUuid = messageType === "user" ? root.uuid : undefined;
737
800
  return {
738
- taskId: readTrimmedString(root.task_id) ??
739
- readTrimmedString(streamEvent?.task_id) ??
740
- readTrimmedString(streamEventMessage?.task_id) ??
741
- readTrimmedString(messageContainer?.task_id) ??
742
- null,
743
- parentMessageId: readTrimmedString(root.parent_message_id) ??
744
- readTrimmedString(streamEvent?.parent_message_id) ??
745
- readTrimmedString(streamEventMessage?.parent_message_id) ??
746
- readTrimmedString(messageContainer?.parent_message_id) ??
747
- null,
748
- messageId: readTrimmedString(root.message_id) ??
749
- readTrimmedString(streamEvent?.message_id) ??
750
- readTrimmedString(streamEventMessage?.id) ??
751
- readTrimmedString(streamEventMessage?.message_id) ??
752
- readTrimmedString(messageContainer?.id) ??
753
- readTrimmedString(messageContainer?.message_id) ??
754
- (messageType === "user" ? readTrimmedString(root.uuid) : null) ??
755
- null,
801
+ taskId: firstTrimmedString([
802
+ root.task_id,
803
+ streamEvent?.task_id,
804
+ streamEventMessage?.task_id,
805
+ messageContainer?.task_id,
806
+ ]),
807
+ parentMessageId: firstTrimmedString([
808
+ root.parent_message_id,
809
+ streamEvent?.parent_message_id,
810
+ streamEventMessage?.parent_message_id,
811
+ messageContainer?.parent_message_id,
812
+ ]),
813
+ messageId: firstTrimmedString([
814
+ root.message_id,
815
+ streamEvent?.message_id,
816
+ streamEventMessage?.id,
817
+ streamEventMessage?.message_id,
818
+ messageContainer?.id,
819
+ messageContainer?.message_id,
820
+ messageIdFromUuid,
821
+ ]),
756
822
  };
757
823
  }
758
824
  const claudeDebug = process.env.PASEO_CLAUDE_DEBUG === "1";
@@ -781,7 +847,11 @@ export class ClaudeAgentClient {
781
847
  if (!merged.cwd) {
782
848
  throw new Error("Claude resume requires the original working directory in metadata");
783
849
  }
784
- const mergedConfig = { ...merged, provider: "claude", cwd: merged.cwd };
850
+ const mergedConfig = {
851
+ ...merged,
852
+ provider: "claude",
853
+ cwd: merged.cwd,
854
+ };
785
855
  const claudeConfig = this.assertConfig(mergedConfig);
786
856
  return new ClaudeAgentSession(claudeConfig, {
787
857
  defaults: this.defaults,
@@ -804,17 +874,10 @@ export class ClaudeAgentClient {
804
874
  }
805
875
  const limit = options?.limit ?? 20;
806
876
  const candidates = await collectRecentClaudeSessions(projectsRoot, limit * 3);
807
- const descriptors = [];
808
- for (const candidate of candidates) {
809
- const descriptor = await parseClaudeSessionDescriptor(candidate.path, candidate.mtime);
810
- if (descriptor) {
811
- descriptors.push(descriptor);
812
- }
813
- if (descriptors.length >= limit) {
814
- break;
815
- }
816
- }
817
- return descriptors;
877
+ const parsed = await Promise.all(candidates.map((candidate) => parseClaudeSessionDescriptor(candidate.path, candidate.mtime)));
878
+ return parsed
879
+ .filter((descriptor) => descriptor !== null)
880
+ .slice(0, limit);
818
881
  }
819
882
  async isAvailable() {
820
883
  const command = this.runtimeSettings?.command;
@@ -835,7 +898,10 @@ export class ClaudeAgentClient {
835
898
  let status = formatDiagnosticStatus(available);
836
899
  if (available) {
837
900
  try {
838
- const models = await this.listModels({ cwd: os.homedir(), force: false });
901
+ const models = await this.listModels({
902
+ cwd: os.homedir(),
903
+ force: false,
904
+ });
839
905
  modelsValue = String(models.length);
840
906
  }
841
907
  catch (error) {
@@ -871,16 +937,20 @@ export class ClaudeAgentClient {
871
937
  }
872
938
  async function resolveClaudeVersion(runtimeSettings) {
873
939
  const command = runtimeSettings?.command;
940
+ const envSpec = createProviderEnvSpec({ runtimeSettings });
874
941
  try {
875
942
  if (command?.mode === "replace") {
876
- const { stdout } = await execCommand(command.argv[0], [...command.argv.slice(1), "--version"], { timeout: 5000 });
943
+ const { stdout } = await execCommand(command.argv[0], [...command.argv.slice(1), "--version"], { ...envSpec, timeout: 5000 });
877
944
  return stdout.trim() || null;
878
945
  }
879
946
  const executable = await findExecutable("claude");
880
947
  if (!executable) {
881
948
  return null;
882
949
  }
883
- const { stdout } = await execCommand(executable, ["--version"], { timeout: 5000 });
950
+ const { stdout } = await execCommand(executable, ["--version"], {
951
+ ...envSpec,
952
+ timeout: 5000,
953
+ });
884
954
  return stdout.trim() || null;
885
955
  }
886
956
  catch {
@@ -891,7 +961,10 @@ async function resolveClaudeAuth(runtimeSettings) {
891
961
  const command = runtimeSettings?.command;
892
962
  const run = async (executable, args) => {
893
963
  try {
894
- return await execCommand(executable, args, { timeout: 5000 });
964
+ return await execCommand(executable, args, {
965
+ ...createProviderEnvSpec({ runtimeSettings }),
966
+ timeout: 5000,
967
+ });
895
968
  }
896
969
  catch (error) {
897
970
  const err = error;
@@ -1048,11 +1121,17 @@ class ClaudeAgentSession {
1048
1121
  kind,
1049
1122
  input,
1050
1123
  detail: toolDetail,
1051
- suggestions: options.suggestions?.map((suggestion) => ({ ...suggestion })),
1124
+ suggestions: options.suggestions?.map((suggestion) => ({
1125
+ ...suggestion,
1126
+ })),
1052
1127
  actions: kind === "plan" ? buildClaudePlanPermissionActions(this.planResumeMode) : undefined,
1053
1128
  metadata: Object.keys(metadata).length ? metadata : undefined,
1054
1129
  };
1055
- this.pushEvent({ type: "permission_requested", provider: "claude", request });
1130
+ this.pushEvent({
1131
+ type: "permission_requested",
1132
+ provider: "claude",
1133
+ request,
1134
+ });
1056
1135
  return await new Promise((resolve, reject) => {
1057
1136
  const cleanupFns = [];
1058
1137
  const cleanup = () => {
@@ -1328,8 +1407,8 @@ class ClaudeAgentSession {
1328
1407
  }
1329
1408
  const normalized = isPermissionMode(modeId) ? modeId : "default";
1330
1409
  const previousMode = this.currentMode;
1331
- const query = await this.ensureQuery();
1332
- await query.setPermissionMode(normalized);
1410
+ const activeQuery = await this.ensureQuery();
1411
+ await activeQuery.setPermissionMode(normalized);
1333
1412
  if (normalized === "plan") {
1334
1413
  if (previousMode !== "plan") {
1335
1414
  this.planResumeMode = previousMode;
@@ -1342,8 +1421,8 @@ class ClaudeAgentSession {
1342
1421
  }
1343
1422
  async setModel(modelId) {
1344
1423
  const normalizedModelId = typeof modelId === "string" && modelId.trim().length > 0 ? modelId : null;
1345
- const query = await this.ensureQuery();
1346
- await query.setModel(normalizedModelId ?? undefined);
1424
+ const activeQuery = await this.ensureQuery();
1425
+ await activeQuery.setModel(normalizedModelId ?? undefined);
1347
1426
  this.config.model = normalizedModelId ?? undefined;
1348
1427
  this.lastOptionsModel = normalizedModelId ?? this.lastOptionsModel;
1349
1428
  this.lastRuntimeModel = null;
@@ -1577,8 +1656,8 @@ class ClaudeAgentSession {
1577
1656
  }
1578
1657
  async rewindFilesOnce(messageId) {
1579
1658
  try {
1580
- const query = await this.ensureFreshQuery();
1581
- return await query.rewindFiles(messageId, { dryRun: false });
1659
+ const activeQuery = await this.ensureFreshQuery();
1660
+ return await activeQuery.rewindFiles(messageId, { dryRun: false });
1582
1661
  }
1583
1662
  catch (error) {
1584
1663
  // The Claude SDK transport can close after a rewind call.
@@ -1712,32 +1791,46 @@ class ClaudeAgentSession {
1712
1791
  this.logger.warn({ err: error, label }, "Claude query operation did not settle cleanly");
1713
1792
  }
1714
1793
  }
1715
- async buildOptions() {
1794
+ resolveThinkingConfig() {
1716
1795
  const thinkingOptionId = this.config.thinkingOptionId && this.config.thinkingOptionId !== "default"
1717
1796
  ? this.config.thinkingOptionId
1718
1797
  : undefined;
1719
- let thinking;
1720
- let effort;
1721
1798
  if (thinkingOptionId && isClaudeThinkingEffort(thinkingOptionId)) {
1722
- thinking = { type: "adaptive" };
1723
1799
  // SDK 0.2.71 types `effort` as 'low' | 'medium' | 'high' | 'max'; Opus 4.7
1724
1800
  // adds 'xhigh' which the binary accepts but the typings don't yet expose.
1725
- effort = thinkingOptionId;
1801
+ return {
1802
+ thinking: { type: "adaptive" },
1803
+ effort: thinkingOptionId,
1804
+ };
1726
1805
  }
1727
- const appendedSystemPrompt = [
1728
- getOrchestratorModeInstructions(),
1729
- this.config.systemPrompt?.trim(),
1730
- ]
1806
+ return { thinking: undefined, effort: undefined };
1807
+ }
1808
+ buildAppendedSystemPrompt() {
1809
+ return [getOrchestratorModeInstructions(), this.config.systemPrompt?.trim()]
1731
1810
  .filter((entry) => typeof entry === "string" && entry.length > 0)
1732
1811
  .join("\n\n");
1812
+ }
1813
+ async buildOptions() {
1814
+ const { thinking, effort } = this.resolveThinkingConfig();
1815
+ const appendedSystemPrompt = this.buildAppendedSystemPrompt();
1816
+ const extraClaudeOptions = this.config.extra?.claude;
1817
+ const sdkEnv = createProviderEnv({
1818
+ baseEnv: process.env,
1819
+ runtimeSettings: this.runtimeSettings,
1820
+ overlays: [
1821
+ extraClaudeOptions?.env,
1822
+ {
1823
+ // Increase MCP timeouts for long-running tool calls (10 minutes)
1824
+ MCP_TIMEOUT: "600000",
1825
+ MCP_TOOL_TIMEOUT: "600000",
1826
+ },
1827
+ this.launchEnv,
1828
+ ],
1829
+ });
1733
1830
  const claudeBinary = await findExecutable("claude");
1734
1831
  this.logger.debug({
1735
1832
  claudeBinary,
1736
- pathEnvKey: process.env["Path"] !== undefined
1737
- ? "Path"
1738
- : process.env["PATH"] !== undefined
1739
- ? "PATH"
1740
- : null,
1833
+ pathEnvKey: resolvePathEnvKey(),
1741
1834
  pathIncludesClaudeLocalBin: (process.env["Path"] ?? process.env["PATH"] ?? "")
1742
1835
  .toLowerCase()
1743
1836
  .includes("\\.local\\bin"),
@@ -1765,13 +1858,6 @@ class ClaudeAgentSession {
1765
1858
  this.captureStderr(data);
1766
1859
  this.logger.error({ stderr: data.trim() }, "Claude Agent SDK stderr");
1767
1860
  },
1768
- env: {
1769
- ...process.env,
1770
- // Increase MCP timeouts for long-running tool calls (10 minutes)
1771
- MCP_TIMEOUT: "600000",
1772
- MCP_TOOL_TIMEOUT: "600000",
1773
- ...(this.launchEnv ?? {}),
1774
- },
1775
1861
  // Required for provider-level /rewind support.
1776
1862
  enableFileCheckpointing: true,
1777
1863
  // If we have a session ID from a previous query (e.g., after interrupt),
@@ -1779,7 +1865,8 @@ class ClaudeAgentSession {
1779
1865
  ...(this.claudeSessionId ? { resume: this.claudeSessionId } : {}),
1780
1866
  ...(thinking ? { thinking } : {}),
1781
1867
  ...(effort ? { effort } : {}),
1782
- ...this.config.extra?.claude,
1868
+ ...extraClaudeOptions,
1869
+ env: sdkEnv,
1783
1870
  };
1784
1871
  if (this.config.mcpServers) {
1785
1872
  base.mcpServers = this.normalizeMcpServers(this.config.mcpServers);
@@ -1827,7 +1914,10 @@ class ClaudeAgentSession {
1827
1914
  });
1828
1915
  }
1829
1916
  else if (chunk.type === "github_pr" || chunk.type === "github_issue") {
1830
- content.push({ type: "text", text: renderPromptAttachmentAsText(chunk) });
1917
+ content.push({
1918
+ type: "text",
1919
+ text: renderPromptAttachmentAsText(chunk),
1920
+ });
1831
1921
  }
1832
1922
  }
1833
1923
  }
@@ -1900,7 +1990,7 @@ class ClaudeAgentSession {
1900
1990
  if (this.getRecentStderrDiagnostic()) {
1901
1991
  return;
1902
1992
  }
1903
- const message = typeof error === "string" ? error : error instanceof Error ? error.message : "";
1993
+ const message = errorToMessageString(error);
1904
1994
  if (!/\bprocess exited with code\b/i.test(message) &&
1905
1995
  !/\bterminated by signal\b/i.test(message)) {
1906
1996
  return;
@@ -1965,11 +2055,16 @@ class ClaudeAgentSession {
1965
2055
  if (consecutiveRecoveries >= 3) {
1966
2056
  return false;
1967
2057
  }
1968
- const message = typeof error === "string"
1969
- ? error
1970
- : error instanceof Error
1971
- ? `${error.message}\n${error.stack ?? ""}`
1972
- : JSON.stringify(error);
2058
+ let message;
2059
+ if (typeof error === "string") {
2060
+ message = error;
2061
+ }
2062
+ else if (error instanceof Error) {
2063
+ message = `${error.message}\n${error.stack ?? ""}`;
2064
+ }
2065
+ else {
2066
+ message = JSON.stringify(error);
2067
+ }
1973
2068
  return message.toLowerCase().includes("request was aborted");
1974
2069
  }
1975
2070
  finishForegroundTurn(event) {
@@ -2055,23 +2150,39 @@ class ClaudeAgentSession {
2055
2150
  return;
2056
2151
  }
2057
2152
  let consecutiveInterruptAbortRecoveries = 0;
2153
+ const logRawMessage = (message) => {
2154
+ if (!claudeDebug) {
2155
+ return;
2156
+ }
2157
+ this.logger.trace({
2158
+ claudeSessionId: this.claudeSessionId,
2159
+ messageType: message.type,
2160
+ messageSubtype: "subtype" in message ? message.subtype : undefined,
2161
+ messageUuid: "uuid" in message ? message.uuid : undefined,
2162
+ }, "Claude query pump: raw SDK message");
2163
+ };
2164
+ const handlePumpedMessage = async (message) => {
2165
+ logRawMessage(message);
2166
+ consecutiveInterruptAbortRecoveries = 0;
2167
+ if (await this.handleMissingResumedConversation(message, activeQuery)) {
2168
+ return true;
2169
+ }
2170
+ this.routeSdkMessageFromPump(message);
2171
+ return false;
2172
+ };
2173
+ const drainActiveQuery = async () => {
2174
+ for await (const message of activeQuery) {
2175
+ if (await handlePumpedMessage(message)) {
2176
+ return true;
2177
+ }
2178
+ }
2179
+ return false;
2180
+ };
2058
2181
  try {
2059
2182
  while (!this.closed && this.query === activeQuery) {
2060
2183
  try {
2061
- for await (const message of activeQuery) {
2062
- if (claudeDebug) {
2063
- this.logger.trace({
2064
- claudeSessionId: this.claudeSessionId,
2065
- messageType: message.type,
2066
- messageSubtype: "subtype" in message ? message.subtype : undefined,
2067
- messageUuid: "uuid" in message ? message.uuid : undefined,
2068
- }, "Claude query pump: raw SDK message");
2069
- }
2070
- consecutiveInterruptAbortRecoveries = 0;
2071
- if (await this.handleMissingResumedConversation(message, activeQuery)) {
2072
- return;
2073
- }
2074
- this.routeSdkMessageFromPump(message);
2184
+ if (await drainActiveQuery()) {
2185
+ return;
2075
2186
  }
2076
2187
  if (!this.closed && this.query === activeQuery) {
2077
2188
  this.failActiveTurns("Claude stream ended before terminal result");
@@ -2101,7 +2212,16 @@ class ClaudeAgentSession {
2101
2212
  }
2102
2213
  }
2103
2214
  }
2104
- routeSdkMessageFromPump(message) {
2215
+ isEchoedForegroundUserMessage(event) {
2216
+ if (event.type !== "timeline" ||
2217
+ event.item.type !== "user_message" ||
2218
+ !this.activeForegroundTurnId ||
2219
+ !this.lastForegroundPromptText) {
2220
+ return false;
2221
+ }
2222
+ return event.item.text.trim() === this.lastForegroundPromptText.trim();
2223
+ }
2224
+ shouldSuppressStaleResult(message) {
2105
2225
  // Suppress stale results from interrupted requests. The cancel path already
2106
2226
  // emitted the terminal event; this result is leftover from the killed API
2107
2227
  // request. Consume the flag on ANY result so it doesn't linger.
@@ -2109,19 +2229,27 @@ class ClaudeAgentSession {
2109
2229
  this.pendingInterruptAbort = false;
2110
2230
  if (message.subtype !== "success") {
2111
2231
  this.logger.debug("Suppressing stale non-success result from interrupted request");
2112
- return;
2232
+ return true;
2113
2233
  }
2114
2234
  }
2115
2235
  if (message.type === "result" && message.subtype !== "success" && this.isAbortError(message)) {
2116
2236
  this.logger.debug("Suppressing abort result by content");
2117
- return;
2237
+ return true;
2118
2238
  }
2119
- const isForeground = Boolean(this.activeForegroundTurnId);
2120
- const assistantishMessage = message.type === "assistant" ||
2239
+ return false;
2240
+ }
2241
+ isAssistantishMessage(message) {
2242
+ return (message.type === "assistant" ||
2121
2243
  message.type === "stream_event" ||
2122
2244
  message.type === "tool_progress" ||
2123
- (message.type === "system" && message.subtype === "task_notification");
2124
- if (!isForeground && assistantishMessage) {
2245
+ (message.type === "system" && message.subtype === "task_notification"));
2246
+ }
2247
+ routeSdkMessageFromPump(message) {
2248
+ if (this.shouldSuppressStaleResult(message)) {
2249
+ return;
2250
+ }
2251
+ const isForeground = Boolean(this.activeForegroundTurnId);
2252
+ if (!isForeground && this.isAssistantishMessage(message)) {
2125
2253
  this.startAutonomousTurn();
2126
2254
  }
2127
2255
  if (!isForeground && !this.autonomousTurn && message.type === "result") {
@@ -2152,17 +2280,7 @@ class ClaudeAgentSession {
2152
2280
  provider: "claude",
2153
2281
  }));
2154
2282
  // User message dedup: suppress echoed user messages that match the foreground prompt
2155
- const filteredMessageEvents = messageEvents.filter((event) => {
2156
- if (event.type === "timeline" &&
2157
- event.item.type === "user_message" &&
2158
- this.activeForegroundTurnId &&
2159
- this.lastForegroundPromptText) {
2160
- if (event.item.text.trim() === this.lastForegroundPromptText.trim()) {
2161
- return false;
2162
- }
2163
- }
2164
- return true;
2165
- });
2283
+ const filteredMessageEvents = messageEvents.filter((event) => !this.isEchoedForegroundUserMessage(event));
2166
2284
  const events = [...filteredMessageEvents, ...assistantTimelineEvents];
2167
2285
  if (events.length === 0) {
2168
2286
  return;
@@ -2183,7 +2301,7 @@ class ClaudeAgentSession {
2183
2301
  }
2184
2302
  this.dispatchEvents(events);
2185
2303
  }
2186
- async handleMissingResumedConversation(message, query) {
2304
+ async handleMissingResumedConversation(message, activeQuery) {
2187
2305
  const staleResumeError = this.readMissingResumedConversationError(message);
2188
2306
  if (!staleResumeError) {
2189
2307
  return false;
@@ -2194,8 +2312,8 @@ class ClaudeAgentSession {
2194
2312
  }, "Claude resumed session no longer exists; invalidating persisted session");
2195
2313
  this.failActiveTurns(staleResumeError);
2196
2314
  this.input?.end();
2197
- await this.awaitWithTimeout(query.return?.(), "query pump return on missing resumed conversation");
2198
- if (this.query === query) {
2315
+ await this.awaitWithTimeout(activeQuery.return?.(), "query pump return on missing resumed conversation");
2316
+ if (this.query === activeQuery) {
2199
2317
  this.query = null;
2200
2318
  this.input = null;
2201
2319
  }
@@ -2242,118 +2360,11 @@ class ClaudeAgentSession {
2242
2360
  }
2243
2361
  switch (message.type) {
2244
2362
  case "system":
2245
- if (message.subtype === "init") {
2246
- const threadSessionId = this.handleSystemMessage(message);
2247
- if (threadSessionId) {
2248
- events.push({
2249
- type: "thread_started",
2250
- provider: "claude",
2251
- sessionId: threadSessionId,
2252
- });
2253
- }
2254
- }
2255
- else if (message.subtype === "status") {
2256
- const status = message.status;
2257
- if (status === "compacting") {
2258
- this.compacting = true;
2259
- events.push({
2260
- type: "timeline",
2261
- item: { type: "compaction", status: "loading" },
2262
- provider: "claude",
2263
- });
2264
- }
2265
- }
2266
- else if (message.subtype === "compact_boundary") {
2267
- const compactMetadata = readCompactionMetadata(message);
2268
- events.push({
2269
- type: "timeline",
2270
- item: {
2271
- type: "compaction",
2272
- status: "completed",
2273
- trigger: compactMetadata?.trigger === "manual" ? "manual" : "auto",
2274
- preTokens: compactMetadata?.preTokens,
2275
- },
2276
- provider: "claude",
2277
- });
2278
- }
2279
- else if (message.subtype === "task_notification") {
2280
- const taskNotificationItem = mapTaskNotificationSystemRecordToToolCall(message);
2281
- if (taskNotificationItem) {
2282
- events.push({
2283
- type: "timeline",
2284
- item: taskNotificationItem,
2285
- provider: "claude",
2286
- });
2287
- }
2288
- const usage = readUsageFromTaskNotification(message);
2289
- if (typeof usage === "number") {
2290
- this.lastContextWindowUsedTokens = usage;
2291
- events.push(this.createUsageUpdatedEvent(usage));
2292
- }
2293
- }
2294
- else if (message.subtype === "task_progress") {
2295
- this.lastContextWindowUsedTokens =
2296
- readContextWindowUsedTokensFromTaskProgress(message) ??
2297
- this.lastContextWindowUsedTokens;
2298
- if (typeof this.lastContextWindowUsedTokens === "number") {
2299
- events.push(this.createUsageUpdatedEvent(this.lastContextWindowUsedTokens));
2300
- }
2301
- }
2363
+ this.appendSystemMessageEvents(message, events);
2302
2364
  break;
2303
- case "user": {
2304
- if (isSyntheticUserEntry(message)) {
2305
- break;
2306
- }
2307
- if (this.compacting) {
2308
- this.compacting = false;
2309
- break;
2310
- }
2311
- const messageId = typeof message.uuid === "string" && message.uuid.length > 0 ? message.uuid : undefined;
2312
- this.rememberUserMessageId(messageId);
2313
- const content = message.message?.content;
2314
- const taskNotificationItem = mapTaskNotificationUserContentToToolCall({
2315
- content,
2316
- messageId,
2317
- });
2318
- if (taskNotificationItem) {
2319
- events.push({
2320
- type: "timeline",
2321
- item: taskNotificationItem,
2322
- provider: "claude",
2323
- });
2324
- break;
2325
- }
2326
- if (typeof content === "string" && content.length > 0) {
2327
- if (!isClaudeTranscriptNoiseText(content)) {
2328
- events.push({
2329
- type: "timeline",
2330
- item: {
2331
- type: "user_message",
2332
- text: content,
2333
- ...(messageId ? { messageId } : {}),
2334
- },
2335
- provider: "claude",
2336
- });
2337
- }
2338
- }
2339
- else if (Array.isArray(content)) {
2340
- const timelineItems = this.mapBlocksToTimeline(content, {
2341
- textMessageType: "user_message",
2342
- });
2343
- for (const item of timelineItems) {
2344
- if (item.type === "user_message" && messageId && !item.messageId) {
2345
- events.push({
2346
- type: "timeline",
2347
- item: { ...item, messageId },
2348
- provider: "claude",
2349
- });
2350
- continue;
2351
- }
2352
- events.push({ type: "timeline", item, provider: "claude" });
2353
- }
2354
- }
2365
+ case "user":
2366
+ this.appendUserMessageEvents(message, events);
2355
2367
  break;
2356
- }
2357
2368
  case "assistant": {
2358
2369
  const timelineItems = this.mapBlocksToTimeline(message.message.content, {
2359
2370
  suppressAssistantText: options?.suppressAssistantText ?? false,
@@ -2364,48 +2375,163 @@ class ClaudeAgentSession {
2364
2375
  }
2365
2376
  break;
2366
2377
  }
2367
- case "stream_event": {
2368
- const usageUpdatedEvent = this.trackStreamEventUsage(message.event);
2369
- if (usageUpdatedEvent) {
2370
- events.push(usageUpdatedEvent);
2371
- }
2372
- const timelineItems = this.mapPartialEvent(message.event, {
2373
- suppressAssistantText: options?.suppressAssistantText ?? false,
2374
- suppressReasoning: options?.suppressReasoning ?? false,
2375
- });
2376
- for (const item of timelineItems) {
2377
- events.push({ type: "timeline", item, provider: "claude" });
2378
- }
2378
+ case "stream_event":
2379
+ this.appendStreamEventEvents(message, events, options);
2379
2380
  break;
2380
- }
2381
- case "result": {
2382
- const usage = this.convertUsage(message, message.modelUsage);
2383
- if (message.subtype === "success") {
2384
- events.push({ type: "turn_completed", provider: "claude", usage });
2385
- }
2386
- else {
2387
- const errorMessage = "errors" in message && Array.isArray(message.errors) && message.errors.length > 0
2388
- ? message.errors.join("\n")
2389
- : "Claude run failed";
2390
- events.push(this.buildTurnFailedEvent(errorMessage));
2391
- }
2381
+ case "result":
2382
+ this.appendResultEvents(message, events);
2392
2383
  break;
2393
- }
2394
2384
  default:
2395
2385
  break;
2396
2386
  }
2397
2387
  return events;
2398
2388
  }
2389
+ appendSystemMessageEvents(message, events) {
2390
+ if (message.subtype === "init") {
2391
+ const threadSessionId = this.handleSystemMessage(message);
2392
+ if (threadSessionId) {
2393
+ events.push({
2394
+ type: "thread_started",
2395
+ provider: "claude",
2396
+ sessionId: threadSessionId,
2397
+ });
2398
+ }
2399
+ return;
2400
+ }
2401
+ if (message.subtype === "status") {
2402
+ const status = message.status;
2403
+ if (status === "compacting") {
2404
+ this.compacting = true;
2405
+ events.push({
2406
+ type: "timeline",
2407
+ item: { type: "compaction", status: "loading" },
2408
+ provider: "claude",
2409
+ });
2410
+ }
2411
+ return;
2412
+ }
2413
+ if (message.subtype === "compact_boundary") {
2414
+ const compactMetadata = readCompactionMetadata(message);
2415
+ events.push({
2416
+ type: "timeline",
2417
+ item: {
2418
+ type: "compaction",
2419
+ status: "completed",
2420
+ trigger: compactMetadata?.trigger === "manual" ? "manual" : "auto",
2421
+ preTokens: compactMetadata?.preTokens,
2422
+ },
2423
+ provider: "claude",
2424
+ });
2425
+ return;
2426
+ }
2427
+ if (message.subtype === "task_notification") {
2428
+ const taskNotificationItem = mapTaskNotificationSystemRecordToToolCall(message);
2429
+ if (taskNotificationItem) {
2430
+ events.push({
2431
+ type: "timeline",
2432
+ item: taskNotificationItem,
2433
+ provider: "claude",
2434
+ });
2435
+ }
2436
+ const usage = readUsageFromTaskNotification(message);
2437
+ if (typeof usage === "number") {
2438
+ this.lastContextWindowUsedTokens = usage;
2439
+ events.push(this.createUsageUpdatedEvent(usage));
2440
+ }
2441
+ return;
2442
+ }
2443
+ if (message.subtype === "task_progress") {
2444
+ this.lastContextWindowUsedTokens =
2445
+ readContextWindowUsedTokensFromTaskProgress(message) ?? this.lastContextWindowUsedTokens;
2446
+ if (typeof this.lastContextWindowUsedTokens === "number") {
2447
+ events.push(this.createUsageUpdatedEvent(this.lastContextWindowUsedTokens));
2448
+ }
2449
+ }
2450
+ }
2451
+ appendUserMessageEvents(message, events) {
2452
+ if (isSyntheticUserEntry(message)) {
2453
+ return;
2454
+ }
2455
+ if (this.compacting) {
2456
+ this.compacting = false;
2457
+ return;
2458
+ }
2459
+ const messageId = typeof message.uuid === "string" && message.uuid.length > 0 ? message.uuid : undefined;
2460
+ this.rememberUserMessageId(messageId);
2461
+ const content = message.message?.content;
2462
+ const taskNotificationItem = mapTaskNotificationUserContentToToolCall({
2463
+ content,
2464
+ messageId,
2465
+ });
2466
+ if (taskNotificationItem) {
2467
+ events.push({
2468
+ type: "timeline",
2469
+ item: taskNotificationItem,
2470
+ provider: "claude",
2471
+ });
2472
+ return;
2473
+ }
2474
+ if (typeof content === "string" && content.length > 0) {
2475
+ if (!isClaudeTranscriptNoiseText(content)) {
2476
+ events.push({
2477
+ type: "timeline",
2478
+ item: {
2479
+ type: "user_message",
2480
+ text: content,
2481
+ ...(messageId ? { messageId } : {}),
2482
+ },
2483
+ provider: "claude",
2484
+ });
2485
+ }
2486
+ return;
2487
+ }
2488
+ if (Array.isArray(content)) {
2489
+ this.appendUserContentArrayEvents(content, messageId, events);
2490
+ }
2491
+ }
2492
+ appendUserContentArrayEvents(content, messageId, events) {
2493
+ const timelineItems = this.mapBlocksToTimeline(content, {
2494
+ textMessageType: "user_message",
2495
+ });
2496
+ for (const item of timelineItems) {
2497
+ if (item.type === "user_message" && messageId && !item.messageId) {
2498
+ events.push({
2499
+ type: "timeline",
2500
+ item: { ...item, messageId },
2501
+ provider: "claude",
2502
+ });
2503
+ continue;
2504
+ }
2505
+ events.push({ type: "timeline", item, provider: "claude" });
2506
+ }
2507
+ }
2508
+ appendStreamEventEvents(message, events, options) {
2509
+ const usageUpdatedEvent = this.trackStreamEventUsage(message.event);
2510
+ if (usageUpdatedEvent) {
2511
+ events.push(usageUpdatedEvent);
2512
+ }
2513
+ const timelineItems = this.mapPartialEvent(message.event, {
2514
+ suppressAssistantText: options?.suppressAssistantText ?? false,
2515
+ suppressReasoning: options?.suppressReasoning ?? false,
2516
+ });
2517
+ for (const item of timelineItems) {
2518
+ events.push({ type: "timeline", item, provider: "claude" });
2519
+ }
2520
+ }
2521
+ appendResultEvents(message, events) {
2522
+ const usage = this.convertUsage(message, message.modelUsage);
2523
+ if (message.subtype === "success") {
2524
+ events.push({ type: "turn_completed", provider: "claude", usage });
2525
+ return;
2526
+ }
2527
+ const errorMessage = "errors" in message && Array.isArray(message.errors) && message.errors.length > 0
2528
+ ? message.errors.join("\n")
2529
+ : "Claude run failed";
2530
+ events.push(this.buildTurnFailedEvent(errorMessage));
2531
+ }
2399
2532
  captureSessionIdFromMessage(message) {
2400
2533
  const msg = message;
2401
- const sessionIdRaw = typeof msg.session_id === "string"
2402
- ? msg.session_id
2403
- : typeof msg.sessionId === "string"
2404
- ? msg.sessionId
2405
- : typeof msg.session?.id === "string"
2406
- ? msg.session.id
2407
- : "";
2408
- const sessionId = sessionIdRaw.trim();
2534
+ const sessionId = extractSessionIdRaw(msg).trim();
2409
2535
  if (!sessionId) {
2410
2536
  return null;
2411
2537
  }
@@ -2430,14 +2556,7 @@ class ClaudeAgentSession {
2430
2556
  return null;
2431
2557
  }
2432
2558
  const msg = message;
2433
- const newSessionIdRaw = typeof msg.session_id === "string"
2434
- ? msg.session_id
2435
- : typeof msg.sessionId === "string"
2436
- ? msg.sessionId
2437
- : typeof msg.session?.id === "string"
2438
- ? msg.session.id
2439
- : "";
2440
- const newSessionId = newSessionIdRaw.trim();
2559
+ const newSessionId = extractSessionIdRaw(msg).trim();
2441
2560
  if (!newSessionId) {
2442
2561
  return null;
2443
2562
  }
@@ -2651,7 +2770,7 @@ class ClaudeAgentSession {
2651
2770
  }
2652
2771
  this.ingestPersistedHistory(fs.readFileSync(historyPath, "utf8"));
2653
2772
  }
2654
- catch (error) {
2773
+ catch {
2655
2774
  // ignore history load failures
2656
2775
  }
2657
2776
  }
@@ -2734,50 +2853,16 @@ class ClaudeAgentSession {
2734
2853
  // User SDK entries can arrive as multiple text blocks, but Paseo treats them as one message.
2735
2854
  const userTextParts = [];
2736
2855
  for (const block of content) {
2737
- switch (block.type) {
2738
- case "text":
2739
- case "text_delta":
2740
- if (block.text &&
2741
- block.text !== INTERRUPT_TOOL_USE_PLACEHOLDER &&
2742
- !isClaudeTranscriptNoiseText(block.text)) {
2743
- if (textMessageType === "user_message") {
2744
- const trimmed = block.text.trim();
2745
- if (trimmed) {
2746
- userTextParts.push(trimmed);
2747
- }
2748
- }
2749
- else if (!suppressText) {
2750
- items.push({ type: "assistant_message", text: block.text });
2751
- }
2752
- }
2753
- break;
2754
- case "thinking":
2755
- case "thinking_delta":
2756
- if (block.thinking) {
2757
- if (!suppressReasoning) {
2758
- items.push({ type: "reasoning", text: block.thinking });
2759
- }
2760
- }
2761
- break;
2762
- case "tool_use":
2763
- case "server_tool_use":
2764
- case "mcp_tool_use": {
2765
- this.handleToolUseStart(block, items);
2766
- break;
2767
- }
2768
- case "tool_result":
2769
- case "mcp_tool_result":
2770
- case "web_fetch_tool_result":
2771
- case "web_search_tool_result":
2772
- case "code_execution_tool_result":
2773
- case "bash_code_execution_tool_result":
2774
- case "text_editor_code_execution_tool_result": {
2775
- this.handleToolResult(block, items);
2776
- break;
2777
- }
2778
- default:
2779
- break;
2856
+ if (!isClaudeContentChunk(block)) {
2857
+ continue;
2780
2858
  }
2859
+ this.mapBlockToTimeline(block, {
2860
+ items,
2861
+ userTextParts,
2862
+ textMessageType,
2863
+ suppressText,
2864
+ suppressReasoning,
2865
+ });
2781
2866
  }
2782
2867
  if (textMessageType === "user_message" && userTextParts.length > 0) {
2783
2868
  items.unshift({
@@ -2787,6 +2872,53 @@ class ClaudeAgentSession {
2787
2872
  }
2788
2873
  return items;
2789
2874
  }
2875
+ appendTextBlockToTimeline(block, context) {
2876
+ const { items, userTextParts, textMessageType, suppressText } = context;
2877
+ const text = typeof block.text === "string" ? block.text : "";
2878
+ if (!text || text === INTERRUPT_TOOL_USE_PLACEHOLDER || isClaudeTranscriptNoiseText(text)) {
2879
+ return;
2880
+ }
2881
+ if (textMessageType === "user_message") {
2882
+ const trimmed = text.trim();
2883
+ if (trimmed) {
2884
+ userTextParts.push(trimmed);
2885
+ }
2886
+ return;
2887
+ }
2888
+ if (!suppressText) {
2889
+ items.push({ type: "assistant_message", text });
2890
+ }
2891
+ }
2892
+ mapBlockToTimeline(block, context) {
2893
+ switch (block.type) {
2894
+ case "text":
2895
+ case "text_delta":
2896
+ this.appendTextBlockToTimeline(block, context);
2897
+ break;
2898
+ case "thinking":
2899
+ case "thinking_delta":
2900
+ if (typeof block.thinking === "string" && block.thinking && !context.suppressReasoning) {
2901
+ context.items.push({ type: "reasoning", text: block.thinking });
2902
+ }
2903
+ break;
2904
+ case "tool_use":
2905
+ case "server_tool_use":
2906
+ case "mcp_tool_use":
2907
+ this.handleToolUseStart(block, context.items);
2908
+ break;
2909
+ case "tool_result":
2910
+ case "mcp_tool_result":
2911
+ case "web_fetch_tool_result":
2912
+ case "web_search_tool_result":
2913
+ case "code_execution_tool_result":
2914
+ case "bash_code_execution_tool_result":
2915
+ case "text_editor_code_execution_tool_result":
2916
+ this.handleToolResult(block, context.items);
2917
+ break;
2918
+ default:
2919
+ break;
2920
+ }
2921
+ }
2790
2922
  handleToolUseStart(block, items) {
2791
2923
  const entry = this.upsertToolUseEntry(block);
2792
2924
  if (!entry) {
@@ -2806,7 +2938,8 @@ class ClaudeAgentSession {
2806
2938
  }
2807
2939
  handleToolResult(block, items) {
2808
2940
  const entry = typeof block.tool_use_id === "string" ? this.toolUseCache.get(block.tool_use_id) : undefined;
2809
- const toolName = entry?.name ?? block.tool_name ?? "tool";
2941
+ const blockToolName = typeof block.tool_name === "string" ? block.tool_name : undefined;
2942
+ const toolName = entry?.name ?? blockToolName ?? "tool";
2810
2943
  const callId = typeof block.tool_use_id === "string" && block.tool_use_id.length > 0
2811
2944
  ? block.tool_use_id
2812
2945
  : (entry?.id ?? null);
@@ -2838,8 +2971,10 @@ class ClaudeAgentSession {
2838
2971
  if (block.is_error) {
2839
2972
  return undefined;
2840
2973
  }
2841
- const server = entry?.server ?? block.server ?? "tool";
2842
- const tool = entry?.name ?? block.tool_name ?? "tool";
2974
+ const blockServer = typeof block.server === "string" ? block.server : undefined;
2975
+ const blockToolName = typeof block.tool_name === "string" ? block.tool_name : undefined;
2976
+ const server = entry?.server ?? blockServer ?? "tool";
2977
+ const tool = entry?.name ?? blockToolName ?? "tool";
2843
2978
  const content = coerceToolResultContentToString(block.content);
2844
2979
  const input = entry?.input;
2845
2980
  // Build structured result based on tool type
@@ -2865,17 +3000,39 @@ class ClaudeAgentSession {
2865
3000
  }
2866
3001
  return Object.keys(result).length > 0 ? result : undefined;
2867
3002
  }
2868
- buildStructuredToolResult(server, tool, output, input) {
2869
- const normalizedServer = server.toLowerCase();
2870
- const normalizedTool = tool.toLowerCase();
2871
- // Command execution tools
3003
+ isCommandExecutionTool(normalizedServer, normalizedTool, input) {
2872
3004
  if (normalizedServer.includes("bash") ||
2873
3005
  normalizedServer.includes("shell") ||
2874
- normalizedServer.includes("command") ||
2875
- normalizedTool.includes("bash") ||
3006
+ normalizedServer.includes("command")) {
3007
+ return true;
3008
+ }
3009
+ if (normalizedTool.includes("bash") ||
2876
3010
  normalizedTool.includes("shell") ||
2877
- normalizedTool.includes("command") ||
2878
- (input && (typeof input.command === "string" || Array.isArray(input.command)))) {
3011
+ normalizedTool.includes("command")) {
3012
+ return true;
3013
+ }
3014
+ return Boolean(input && (typeof input.command === "string" || Array.isArray(input.command)));
3015
+ }
3016
+ static isFileWriteTool(normalizedTool) {
3017
+ return (normalizedTool.includes("write") ||
3018
+ normalizedTool === "write_file" ||
3019
+ normalizedTool === "create_file");
3020
+ }
3021
+ static isFileEditTool(normalizedTool) {
3022
+ return (normalizedTool.includes("edit") ||
3023
+ normalizedTool.includes("patch") ||
3024
+ normalizedTool === "apply_patch" ||
3025
+ normalizedTool === "apply_diff");
3026
+ }
3027
+ static isFileReadTool(normalizedTool) {
3028
+ return (normalizedTool.includes("read") ||
3029
+ normalizedTool === "read_file" ||
3030
+ normalizedTool === "view_file");
3031
+ }
3032
+ buildStructuredToolResult(server, tool, output, input) {
3033
+ const normalizedServer = server.toLowerCase();
3034
+ const normalizedTool = tool.toLowerCase();
3035
+ if (this.isCommandExecutionTool(normalizedServer, normalizedTool, input)) {
2879
3036
  const command = this.extractCommandText(input ?? {}) ?? "command";
2880
3037
  return {
2881
3038
  type: "command",
@@ -2884,64 +3041,43 @@ class ClaudeAgentSession {
2884
3041
  cwd: typeof input?.cwd === "string" ? input.cwd : undefined,
2885
3042
  };
2886
3043
  }
2887
- // File write tools (new files or complete replacements)
2888
- if (normalizedTool.includes("write") ||
2889
- normalizedTool === "write_file" ||
2890
- normalizedTool === "create_file") {
2891
- if (input && typeof input.file_path === "string") {
2892
- return {
2893
- type: "file_write",
2894
- filePath: input.file_path,
2895
- oldContent: "",
2896
- newContent: typeof input.content === "string" ? input.content : output,
2897
- };
2898
- }
3044
+ if (ClaudeAgentSession.isFileWriteTool(normalizedTool) &&
3045
+ input &&
3046
+ typeof input.file_path === "string") {
3047
+ return {
3048
+ type: "file_write",
3049
+ filePath: input.file_path,
3050
+ oldContent: "",
3051
+ newContent: typeof input.content === "string" ? input.content : output,
3052
+ };
2899
3053
  }
2900
- // File edit/patch tools
2901
- if (normalizedTool.includes("edit") ||
2902
- normalizedTool.includes("patch") ||
2903
- normalizedTool === "apply_patch" ||
2904
- normalizedTool === "apply_diff") {
2905
- if (input && typeof input.file_path === "string") {
2906
- // Support both old_str/new_str and old_string/new_string parameter names
2907
- const oldContent = typeof input.old_str === "string"
2908
- ? input.old_str
2909
- : typeof input.old_string === "string"
2910
- ? input.old_string
2911
- : undefined;
2912
- const newContent = typeof input.new_str === "string"
2913
- ? input.new_str
2914
- : typeof input.new_string === "string"
2915
- ? input.new_string
2916
- : undefined;
2917
- return {
2918
- type: "file_edit",
2919
- filePath: input.file_path,
2920
- diff: typeof input.patch === "string"
2921
- ? input.patch
2922
- : typeof input.diff === "string"
2923
- ? input.diff
2924
- : undefined,
2925
- oldContent,
2926
- newContent,
2927
- };
2928
- }
3054
+ if (ClaudeAgentSession.isFileEditTool(normalizedTool) &&
3055
+ input &&
3056
+ typeof input.file_path === "string") {
3057
+ // Support both old_str/new_str and old_string/new_string parameter names
3058
+ const oldContent = firstStringField(input, "old_str", "old_string");
3059
+ const newContent = firstStringField(input, "new_str", "new_string");
3060
+ const diff = firstStringField(input, "patch", "diff");
3061
+ return {
3062
+ type: "file_edit",
3063
+ filePath: input.file_path,
3064
+ diff,
3065
+ oldContent,
3066
+ newContent,
3067
+ };
2929
3068
  }
2930
- // File read tools
2931
- if (normalizedTool.includes("read") ||
2932
- normalizedTool === "read_file" ||
2933
- normalizedTool === "view_file") {
2934
- if (input && typeof input.file_path === "string") {
2935
- return {
2936
- type: "file_read",
2937
- filePath: input.file_path,
2938
- content: output,
2939
- };
2940
- }
3069
+ if (ClaudeAgentSession.isFileReadTool(normalizedTool) &&
3070
+ input &&
3071
+ typeof input.file_path === "string") {
3072
+ return {
3073
+ type: "file_read",
3074
+ filePath: input.file_path,
3075
+ content: output,
3076
+ };
2941
3077
  }
2942
3078
  return undefined;
2943
3079
  }
2944
- mapPartialEvent(event, options) {
3080
+ updatePartialEventToolState(event) {
2945
3081
  if (event.type === "content_block_start") {
2946
3082
  const block = isClaudeContentChunk(event.content_block) ? event.content_block : null;
2947
3083
  if (block?.type === "tool_use" &&
@@ -2950,22 +3086,30 @@ class ClaudeAgentSession {
2950
3086
  this.toolUseIndexToId.set(event.index, block.id);
2951
3087
  this.toolUseInputBuffers.delete(block.id);
2952
3088
  }
3089
+ return false;
2953
3090
  }
2954
- else if (event.type === "content_block_delta") {
3091
+ if (event.type === "content_block_delta") {
2955
3092
  const delta = isClaudeContentChunk(event.delta) ? event.delta : null;
2956
3093
  if (delta?.type === "input_json_delta") {
2957
3094
  const partialJson = typeof delta.partial_json === "string" ? delta.partial_json : undefined;
2958
3095
  this.handleToolInputDelta(event.index, partialJson);
2959
- return [];
3096
+ return true;
2960
3097
  }
3098
+ return false;
2961
3099
  }
2962
- else if (event.type === "content_block_stop" && typeof event.index === "number") {
3100
+ if (event.type === "content_block_stop" && typeof event.index === "number") {
2963
3101
  const toolId = this.toolUseIndexToId.get(event.index);
2964
3102
  if (toolId) {
2965
3103
  this.toolUseIndexToId.delete(event.index);
2966
3104
  this.toolUseInputBuffers.delete(toolId);
2967
3105
  }
2968
3106
  }
3107
+ return false;
3108
+ }
3109
+ mapPartialEvent(event, options) {
3110
+ if (this.updatePartialEventToolState(event)) {
3111
+ return [];
3112
+ }
2969
3113
  switch (event.type) {
2970
3114
  case "content_block_start":
2971
3115
  return isClaudeContentChunk(event.content_block)
@@ -2990,18 +3134,7 @@ class ClaudeAgentSession {
2990
3134
  if (!id) {
2991
3135
  return null;
2992
3136
  }
2993
- const existing = this.toolUseCache.get(id) ??
2994
- {
2995
- id,
2996
- name: typeof block.name === "string" && block.name.length > 0 ? block.name : "tool",
2997
- server: typeof block.server === "string" && block.server.length > 0
2998
- ? block.server
2999
- : typeof block.name === "string" && block.name.length > 0
3000
- ? block.name
3001
- : "tool",
3002
- classification: "generic",
3003
- started: false,
3004
- };
3137
+ const existing = this.toolUseCache.get(id) ?? createDefaultToolUseCacheEntry(id, block);
3005
3138
  if (typeof block.name === "string" && block.name.length > 0) {
3006
3139
  existing.name = block.name;
3007
3140
  }
@@ -3225,37 +3358,47 @@ function normalizeHistoryBlocks(content) {
3225
3358
  }
3226
3359
  return null;
3227
3360
  }
3228
- export function convertClaudeHistoryEntry(entry, mapBlocks) {
3361
+ function convertClaudeHistoryEntryPreamble(entry) {
3229
3362
  if (entry.type === "system" && entry.subtype === "compact_boundary") {
3230
3363
  const compactMetadata = readCompactionMetadata(entry);
3231
- return [
3232
- {
3233
- type: "compaction",
3234
- status: "completed",
3235
- trigger: compactMetadata?.trigger === "manual" ? "manual" : "auto",
3236
- preTokens: compactMetadata?.preTokens,
3237
- },
3238
- ];
3364
+ return {
3365
+ shortCircuit: [
3366
+ {
3367
+ type: "compaction",
3368
+ status: "completed",
3369
+ trigger: compactMetadata?.trigger === "manual" ? "manual" : "auto",
3370
+ preTokens: compactMetadata?.preTokens,
3371
+ },
3372
+ ],
3373
+ };
3239
3374
  }
3240
3375
  const taskNotificationItem = mapTaskNotificationSystemRecordToToolCall(entry);
3241
3376
  if (taskNotificationItem) {
3242
- return [taskNotificationItem];
3377
+ return { shortCircuit: [taskNotificationItem] };
3243
3378
  }
3244
3379
  if (entry.isCompactSummary) {
3245
- return [];
3380
+ return { shortCircuit: [] };
3246
3381
  }
3247
3382
  if (entry.type === "user" && isSyntheticUserEntry(entry)) {
3248
- return [];
3383
+ return { shortCircuit: [] };
3249
3384
  }
3250
3385
  const message = entry?.message;
3251
3386
  if (!message || !("content" in message)) {
3252
- return [];
3387
+ return { shortCircuit: [] };
3253
3388
  }
3254
3389
  const content = message.content;
3255
3390
  if ((entry.type === "user" || entry.type === "assistant") &&
3256
3391
  isClaudeTranscriptNoiseContent(content)) {
3257
- return [];
3392
+ return { shortCircuit: [] };
3258
3393
  }
3394
+ return { proceed: { content } };
3395
+ }
3396
+ export function convertClaudeHistoryEntry(entry, mapBlocks) {
3397
+ const preamble = convertClaudeHistoryEntryPreamble(entry);
3398
+ if ("shortCircuit" in preamble) {
3399
+ return preamble.shortCircuit;
3400
+ }
3401
+ const { content } = preamble.proceed;
3259
3402
  const normalizedBlocks = normalizeHistoryBlocks(content);
3260
3403
  const contentValue = typeof content === "string" ? content : normalizedBlocks;
3261
3404
  const hasToolBlock = normalizedBlocks?.some((block) => hasToolLikeBlock(block)) ?? false;
@@ -3263,12 +3406,12 @@ export function convertClaudeHistoryEntry(entry, mapBlocks) {
3263
3406
  ? entry.uuid
3264
3407
  : null;
3265
3408
  if (entry.type === "user") {
3266
- const taskNotificationItem = mapTaskNotificationUserContentToToolCall({
3409
+ const userTaskNotificationItem = mapTaskNotificationUserContentToToolCall({
3267
3410
  content,
3268
3411
  messageId: userMessageId,
3269
3412
  });
3270
- if (taskNotificationItem) {
3271
- return [taskNotificationItem];
3413
+ if (userTaskNotificationItem) {
3414
+ return [userTaskNotificationItem];
3272
3415
  }
3273
3416
  }
3274
3417
  const timeline = [];
@@ -3357,41 +3500,68 @@ async function collectRecentClaudeSessions(root, limit) {
3357
3500
  catch {
3358
3501
  return [];
3359
3502
  }
3360
- const candidates = [];
3361
- for (const dirName of projectDirs) {
3503
+ const projectFileLists = await Promise.all(projectDirs.map(async (dirName) => {
3362
3504
  const projectPath = path.join(root, dirName);
3363
- let stats;
3364
3505
  try {
3365
- stats = await fsPromises.stat(projectPath);
3506
+ const stats = await fsPromises.stat(projectPath);
3507
+ if (!stats.isDirectory())
3508
+ return { projectPath, files: [] };
3509
+ const files = await fsPromises.readdir(projectPath);
3510
+ return { projectPath, files };
3366
3511
  }
3367
3512
  catch {
3368
- continue;
3513
+ return { projectPath, files: [] };
3369
3514
  }
3370
- if (!stats.isDirectory()) {
3371
- continue;
3372
- }
3373
- let files;
3515
+ }));
3516
+ const fileEntries = projectFileLists.flatMap(({ projectPath, files }) => files.filter((f) => f.endsWith(".jsonl")).map((f) => path.join(projectPath, f)));
3517
+ const statResults = await Promise.all(fileEntries.map(async (fullPath) => {
3374
3518
  try {
3375
- files = await fsPromises.readdir(projectPath);
3519
+ const fileStats = await fsPromises.stat(fullPath);
3520
+ return { path: fullPath, mtime: fileStats.mtime };
3376
3521
  }
3377
3522
  catch {
3378
- continue;
3523
+ return null;
3379
3524
  }
3380
- for (const file of files) {
3381
- if (!file.endsWith(".jsonl")) {
3382
- continue;
3383
- }
3384
- const fullPath = path.join(projectPath, file);
3385
- try {
3386
- const fileStats = await fsPromises.stat(fullPath);
3387
- candidates.push({ path: fullPath, mtime: fileStats.mtime });
3388
- }
3389
- catch {
3390
- // ignore stat errors for individual files
3525
+ }));
3526
+ const candidates = statResults.filter((entry) => entry !== null);
3527
+ return candidates.sort((a, b) => b.mtime.getTime() - a.mtime.getTime()).slice(0, limit);
3528
+ }
3529
+ function isFinishedAccumulator(acc) {
3530
+ return Boolean(acc.sessionId && acc.cwd && acc.title);
3531
+ }
3532
+ function applyClaudeSessionEntryToAccumulator(entryRaw, acc) {
3533
+ if (!entryRaw || typeof entryRaw !== "object") {
3534
+ return;
3535
+ }
3536
+ const entry = entryRaw;
3537
+ if (entry.isSidechain) {
3538
+ return;
3539
+ }
3540
+ if (entry.type === "user" && isSyntheticUserEntry(entry)) {
3541
+ return;
3542
+ }
3543
+ if (!acc.sessionId && typeof entry.sessionId === "string") {
3544
+ acc.sessionId = entry.sessionId;
3545
+ }
3546
+ if (!acc.cwd && typeof entry.cwd === "string") {
3547
+ acc.cwd = entry.cwd;
3548
+ }
3549
+ if (entry.type === "user" && entry.message) {
3550
+ const text = extractClaudeUserText(entry.message);
3551
+ if (text) {
3552
+ if (!acc.title) {
3553
+ acc.title = text;
3391
3554
  }
3555
+ acc.timeline.push({ type: "user_message", text });
3556
+ }
3557
+ return;
3558
+ }
3559
+ if (entry.type === "assistant" && entry.message) {
3560
+ const text = extractClaudeUserText(entry.message);
3561
+ if (text) {
3562
+ acc.timeline.push({ type: "assistant_message", text });
3392
3563
  }
3393
3564
  }
3394
- return candidates.sort((a, b) => b.mtime.getTime() - a.mtime.getTime()).slice(0, limit);
3395
3565
  }
3396
3566
  async function parseClaudeSessionDescriptor(filePath, mtime) {
3397
3567
  let content;
@@ -3401,10 +3571,12 @@ async function parseClaudeSessionDescriptor(filePath, mtime) {
3401
3571
  catch {
3402
3572
  return null;
3403
3573
  }
3404
- let sessionId = null;
3405
- let cwd = null;
3406
- let title = null;
3407
- const timeline = [];
3574
+ const acc = {
3575
+ sessionId: null,
3576
+ cwd: null,
3577
+ title: null,
3578
+ timeline: [],
3579
+ };
3408
3580
  for (const rawLine of content.split(/\r?\n/)) {
3409
3581
  const line = rawLine.trim();
3410
3582
  if (!line)
@@ -3416,37 +3588,12 @@ async function parseClaudeSessionDescriptor(filePath, mtime) {
3416
3588
  catch {
3417
3589
  continue;
3418
3590
  }
3419
- if (entry?.isSidechain) {
3420
- continue;
3421
- }
3422
- if (entry?.type === "user" && isSyntheticUserEntry(entry)) {
3423
- continue;
3424
- }
3425
- if (!sessionId && typeof entry.sessionId === "string") {
3426
- sessionId = entry.sessionId;
3427
- }
3428
- if (!cwd && typeof entry.cwd === "string") {
3429
- cwd = entry.cwd;
3430
- }
3431
- if (entry.type === "user" && entry.message) {
3432
- const text = extractClaudeUserText(entry.message);
3433
- if (text) {
3434
- if (!title) {
3435
- title = text;
3436
- }
3437
- timeline.push({ type: "user_message", text });
3438
- }
3439
- }
3440
- else if (entry.type === "assistant" && entry.message) {
3441
- const text = extractClaudeUserText(entry.message);
3442
- if (text) {
3443
- timeline.push({ type: "assistant_message", text });
3444
- }
3445
- }
3446
- if (sessionId && cwd && title) {
3591
+ applyClaudeSessionEntryToAccumulator(entry, acc);
3592
+ if (isFinishedAccumulator(acc)) {
3447
3593
  break;
3448
3594
  }
3449
3595
  }
3596
+ const { sessionId, cwd, title, timeline } = acc;
3450
3597
  if (!sessionId || !cwd) {
3451
3598
  return null;
3452
3599
  }
@@ -3469,10 +3616,11 @@ async function parseClaudeSessionDescriptor(filePath, mtime) {
3469
3616
  timeline,
3470
3617
  };
3471
3618
  }
3472
- function extractClaudeUserText(message) {
3473
- if (!message) {
3619
+ function extractClaudeUserText(messageRaw) {
3620
+ if (!messageRaw || typeof messageRaw !== "object") {
3474
3621
  return null;
3475
3622
  }
3623
+ const message = messageRaw;
3476
3624
  if (typeof message.content === "string") {
3477
3625
  const normalized = message.content.trim();
3478
3626
  return normalized && !isClaudeTranscriptNoiseText(normalized) ? normalized : null;
@@ -3483,7 +3631,9 @@ function extractClaudeUserText(message) {
3483
3631
  }
3484
3632
  if (Array.isArray(message.content)) {
3485
3633
  for (const block of message.content) {
3486
- if (block && typeof block.text === "string") {
3634
+ if (block &&
3635
+ typeof block === "object" &&
3636
+ typeof block.text === "string") {
3487
3637
  const normalized = block.text.trim();
3488
3638
  if (normalized && !isClaudeTranscriptNoiseText(normalized)) {
3489
3639
  return normalized;