@camerontaylor/paseo-server 0.8.0-fork.1

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 (928) hide show
  1. package/.env.example +31 -0
  2. package/README.md +111 -0
  3. package/dist/scripts/dev-runner.js +37 -0
  4. package/dist/scripts/mcp-stdio-socket-bridge-cli.mjs +62 -0
  5. package/dist/scripts/supervisor-entrypoint.js +160 -0
  6. package/dist/scripts/supervisor-log-config.js +31 -0
  7. package/dist/scripts/supervisor.js +313 -0
  8. package/dist/server/executable-resolution/executable-resolution.d.ts +10 -0
  9. package/dist/server/executable-resolution/executable-resolution.js +121 -0
  10. package/dist/server/executable-resolution/windows.d.ts +18 -0
  11. package/dist/server/executable-resolution/windows.js +65 -0
  12. package/dist/server/server/agent/activity-curator.d.ts +40 -0
  13. package/dist/server/server/agent/activity-curator.js +243 -0
  14. package/dist/server/server/agent/agent-archive.d.ts +11 -0
  15. package/dist/server/server/agent/agent-archive.js +16 -0
  16. package/dist/server/server/agent/agent-configuration-validator.d.ts +18 -0
  17. package/dist/server/server/agent/agent-configuration-validator.js +42 -0
  18. package/dist/server/server/agent/agent-loading.d.ts +17 -0
  19. package/dist/server/server/agent/agent-loading.js +88 -0
  20. package/dist/server/server/agent/agent-manager.d.ts +555 -0
  21. package/dist/server/server/agent/agent-manager.js +3930 -0
  22. package/dist/server/server/agent/agent-owner.d.ts +12 -0
  23. package/dist/server/server/agent/agent-owner.js +12 -0
  24. package/dist/server/server/agent/agent-projections.d.ts +26 -0
  25. package/dist/server/server/agent/agent-projections.js +414 -0
  26. package/dist/server/server/agent/agent-prompt.d.ts +91 -0
  27. package/dist/server/server/agent/agent-prompt.js +359 -0
  28. package/dist/server/server/agent/agent-response-loop.d.ts +72 -0
  29. package/dist/server/server/agent/agent-response-loop.js +336 -0
  30. package/dist/server/server/agent/agent-run-state.d.ts +76 -0
  31. package/dist/server/server/agent/agent-run-state.js +212 -0
  32. package/dist/server/server/agent/agent-sdk-types.d.ts +742 -0
  33. package/dist/server/server/agent/agent-sdk-types.js +25 -0
  34. package/dist/server/server/agent/agent-storage.d.ts +148 -0
  35. package/dist/server/server/agent/agent-storage.js +401 -0
  36. package/dist/server/server/agent/agent-stream-coalescer.d.ts +43 -0
  37. package/dist/server/server/agent/agent-stream-coalescer.js +187 -0
  38. package/dist/server/server/agent/agent-timeline-content.d.ts +6 -0
  39. package/dist/server/server/agent/agent-timeline-content.js +62 -0
  40. package/dist/server/server/agent/agent-timeline-store-types.d.ts +54 -0
  41. package/dist/server/server/agent/agent-timeline-store-types.js +2 -0
  42. package/dist/server/server/agent/agent-timeline-store.d.ts +31 -0
  43. package/dist/server/server/agent/agent-timeline-store.js +249 -0
  44. package/dist/server/server/agent/audio-utils.d.ts +3 -0
  45. package/dist/server/server/agent/audio-utils.js +19 -0
  46. package/dist/server/server/agent/create-agent/create.d.ts +102 -0
  47. package/dist/server/server/agent/create-agent/create.js +362 -0
  48. package/dist/server/server/agent/create-agent/intent.d.ts +25 -0
  49. package/dist/server/server/agent/create-agent/intent.js +30 -0
  50. package/dist/server/server/agent/create-agent-lifecycle-dispatch.d.ts +65 -0
  51. package/dist/server/server/agent/create-agent-lifecycle-dispatch.js +166 -0
  52. package/dist/server/server/agent/create-agent-mode.d.ts +13 -0
  53. package/dist/server/server/agent/create-agent-mode.js +65 -0
  54. package/dist/server/server/agent/create-agent-title.d.ts +10 -0
  55. package/dist/server/server/agent/create-agent-title.js +34 -0
  56. package/dist/server/server/agent/dictation-debug.d.ts +13 -0
  57. package/dist/server/server/agent/dictation-debug.js +50 -0
  58. package/dist/server/server/agent/import-sessions.d.ts +57 -0
  59. package/dist/server/server/agent/import-sessions.js +240 -0
  60. package/dist/server/server/agent/lifecycle-command.d.ts +73 -0
  61. package/dist/server/server/agent/lifecycle-command.js +99 -0
  62. package/dist/server/server/agent/mcp-server.d.ts +5 -0
  63. package/dist/server/server/agent/mcp-server.js +31 -0
  64. package/dist/server/server/agent/mcp-shared.d.ts +181 -0
  65. package/dist/server/server/agent/mcp-shared.js +199 -0
  66. package/dist/server/server/agent/mutable-provider-config-owner.d.ts +8 -0
  67. package/dist/server/server/agent/mutable-provider-config-owner.js +35 -0
  68. package/dist/server/server/agent/paseo-tool-policy.d.ts +9 -0
  69. package/dist/server/server/agent/paseo-tool-policy.js +16 -0
  70. package/dist/server/server/agent/pcm16-resampler.d.ts +14 -0
  71. package/dist/server/server/agent/pcm16-resampler.js +63 -0
  72. package/dist/server/server/agent/permission-response.d.ts +15 -0
  73. package/dist/server/server/agent/permission-response.js +14 -0
  74. package/dist/server/server/agent/plugin-provider.d.ts +16 -0
  75. package/dist/server/server/agent/plugin-provider.js +1356 -0
  76. package/dist/server/server/agent/prompt-attachments.d.ts +12 -0
  77. package/dist/server/server/agent/prompt-attachments.js +182 -0
  78. package/dist/server/server/agent/provider-history-timestamps.d.ts +2 -0
  79. package/dist/server/server/agent/provider-history-timestamps.js +16 -0
  80. package/dist/server/server/agent/provider-launch-config.d.ts +43 -0
  81. package/dist/server/server/agent/provider-launch-config.js +167 -0
  82. package/dist/server/server/agent/provider-notices.d.ts +4 -0
  83. package/dist/server/server/agent/provider-notices.js +9 -0
  84. package/dist/server/server/agent/provider-options.d.ts +19 -0
  85. package/dist/server/server/agent/provider-options.js +53 -0
  86. package/dist/server/server/agent/provider-refresh-deadline.d.ts +11 -0
  87. package/dist/server/server/agent/provider-refresh-deadline.js +65 -0
  88. package/dist/server/server/agent/provider-registry.d.ts +72 -0
  89. package/dist/server/server/agent/provider-registry.js +604 -0
  90. package/dist/server/server/agent/provider-runtime.d.ts +16 -0
  91. package/dist/server/server/agent/provider-runtime.js +35 -0
  92. package/dist/server/server/agent/provider-session-import.d.ts +10 -0
  93. package/dist/server/server/agent/provider-session-import.js +55 -0
  94. package/dist/server/server/agent/provider-snapshot-manager.d.ts +166 -0
  95. package/dist/server/server/agent/provider-snapshot-manager.js +843 -0
  96. package/dist/server/server/agent/provider-subagents/store.d.ts +68 -0
  97. package/dist/server/server/agent/provider-subagents/store.js +111 -0
  98. package/dist/server/server/agent/providers/acp-agent.d.ts +703 -0
  99. package/dist/server/server/agent/providers/acp-agent.js +3412 -0
  100. package/dist/server/server/agent/providers/claude/agent.d.ts +74 -0
  101. package/dist/server/server/agent/providers/claude/agent.js +5236 -0
  102. package/dist/server/server/agent/providers/claude/feature-definitions.d.ts +8 -0
  103. package/dist/server/server/agent/providers/claude/feature-definitions.js +24 -0
  104. package/dist/server/server/agent/providers/claude/hooks.d.ts +12 -0
  105. package/dist/server/server/agent/providers/claude/hooks.js +20 -0
  106. package/dist/server/server/agent/providers/claude/model-manifest.d.ts +147 -0
  107. package/dist/server/server/agent/providers/claude/model-manifest.js +342 -0
  108. package/dist/server/server/agent/providers/claude/models.d.ts +28 -0
  109. package/dist/server/server/agent/providers/claude/models.js +141 -0
  110. package/dist/server/server/agent/providers/claude/options.d.ts +85 -0
  111. package/dist/server/server/agent/providers/claude/options.js +93 -0
  112. package/dist/server/server/agent/providers/claude/partial-json.d.ts +5 -0
  113. package/dist/server/server/agent/providers/claude/partial-json.js +306 -0
  114. package/dist/server/server/agent/providers/claude/project-dir.d.ts +6 -0
  115. package/dist/server/server/agent/providers/claude/project-dir.js +57 -0
  116. package/dist/server/server/agent/providers/claude/query.d.ts +17 -0
  117. package/dist/server/server/agent/providers/claude/query.js +86 -0
  118. package/dist/server/server/agent/providers/claude/rewind.d.ts +30 -0
  119. package/dist/server/server/agent/providers/claude/rewind.js +30 -0
  120. package/dist/server/server/agent/providers/claude/side-question.d.ts +16 -0
  121. package/dist/server/server/agent/providers/claude/side-question.js +57 -0
  122. package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts +35 -0
  123. package/dist/server/server/agent/providers/claude/sidechain-tracker.js +392 -0
  124. package/dist/server/server/agent/providers/claude/subagents/live-source.d.ts +161 -0
  125. package/dist/server/server/agent/providers/claude/subagents/live-source.js +415 -0
  126. package/dist/server/server/agent/providers/claude/subagents/observation.d.ts +53 -0
  127. package/dist/server/server/agent/providers/claude/subagents/observation.js +57 -0
  128. package/dist/server/server/agent/providers/claude/subagents/presentation.d.ts +12 -0
  129. package/dist/server/server/agent/providers/claude/subagents/presentation.js +41 -0
  130. package/dist/server/server/agent/providers/claude/subagents/replay-source.d.ts +70 -0
  131. package/dist/server/server/agent/providers/claude/subagents/replay-source.js +305 -0
  132. package/dist/server/server/agent/providers/claude/subagents/workflow-output.d.ts +4 -0
  133. package/dist/server/server/agent/providers/claude/subagents/workflow-output.js +86 -0
  134. package/dist/server/server/agent/providers/claude/subagents/workflow-replay-source.d.ts +38 -0
  135. package/dist/server/server/agent/providers/claude/subagents/workflow-replay-source.js +225 -0
  136. package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts +37 -0
  137. package/dist/server/server/agent/providers/claude/task-notification-tool-call.js +296 -0
  138. package/dist/server/server/agent/providers/claude/task-state.d.ts +18 -0
  139. package/dist/server/server/agent/providers/claude/task-state.js +185 -0
  140. package/dist/server/server/agent/providers/claude/test-rewind-claude-sdk.d.ts +24 -0
  141. package/dist/server/server/agent/providers/claude/test-rewind-claude-sdk.js +23 -0
  142. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts +3 -0
  143. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js +130 -0
  144. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts +16 -0
  145. package/dist/server/server/agent/providers/claude/tool-call-mapper.js +129 -0
  146. package/dist/server/server/agent/providers/codex/app-server-transport.d.ts +101 -0
  147. package/dist/server/server/agent/providers/codex/app-server-transport.js +290 -0
  148. package/dist/server/server/agent/providers/codex/async-questions.d.ts +18 -0
  149. package/dist/server/server/agent/providers/codex/async-questions.js +135 -0
  150. package/dist/server/server/agent/providers/codex/options.d.ts +59 -0
  151. package/dist/server/server/agent/providers/codex/options.js +82 -0
  152. package/dist/server/server/agent/providers/codex/rewind.d.ts +24 -0
  153. package/dist/server/server/agent/providers/codex/rewind.js +77 -0
  154. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts +12 -0
  155. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.js +104 -0
  156. package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts +24 -0
  157. package/dist/server/server/agent/providers/codex/tool-call-mapper.js +909 -0
  158. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +384 -0
  159. package/dist/server/server/agent/providers/codex-app-server-agent.js +5877 -0
  160. package/dist/server/server/agent/providers/codex-feature-definitions.d.ts +11 -0
  161. package/dist/server/server/agent/providers/codex-feature-definitions.js +55 -0
  162. package/dist/server/server/agent/providers/copilot-acp-agent.d.ts +26 -0
  163. package/dist/server/server/agent/providers/copilot-acp-agent.js +187 -0
  164. package/dist/server/server/agent/providers/cursor-acp-agent.d.ts +17 -0
  165. package/dist/server/server/agent/providers/cursor-acp-agent.js +31 -0
  166. package/dist/server/server/agent/providers/diagnostic-utils.d.ts +36 -0
  167. package/dist/server/server/agent/providers/diagnostic-utils.js +356 -0
  168. package/dist/server/server/agent/providers/generic-acp-agent.d.ts +55 -0
  169. package/dist/server/server/agent/providers/generic-acp-agent.js +178 -0
  170. package/dist/server/server/agent/providers/gjc-acp-agent.d.ts +155 -0
  171. package/dist/server/server/agent/providers/gjc-acp-agent.js +588 -0
  172. package/dist/server/server/agent/providers/jsonl-frame-decoder.d.ts +17 -0
  173. package/dist/server/server/agent/providers/jsonl-frame-decoder.js +149 -0
  174. package/dist/server/server/agent/providers/jsonl-rpc-process.d.ts +63 -0
  175. package/dist/server/server/agent/providers/jsonl-rpc-process.js +207 -0
  176. package/dist/server/server/agent/providers/kimi-acp-agent.d.ts +35 -0
  177. package/dist/server/server/agent/providers/kimi-acp-agent.js +65 -0
  178. package/dist/server/server/agent/providers/kiro-acp-agent.d.ts +17 -0
  179. package/dist/server/server/agent/providers/kiro-acp-agent.js +78 -0
  180. package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +111 -0
  181. package/dist/server/server/agent/providers/mock-load-test-agent.js +1340 -0
  182. package/dist/server/server/agent/providers/mock-slow-provider.d.ts +14 -0
  183. package/dist/server/server/agent/providers/mock-slow-provider.js +40 -0
  184. package/dist/server/server/agent/providers/omp/advisor-message.d.ts +11 -0
  185. package/dist/server/server/agent/providers/omp/advisor-message.js +80 -0
  186. package/dist/server/server/agent/providers/omp/agent.d.ts +178 -0
  187. package/dist/server/server/agent/providers/omp/agent.js +1952 -0
  188. package/dist/server/server/agent/providers/omp/cli-runtime.d.ts +22 -0
  189. package/dist/server/server/agent/providers/omp/cli-runtime.js +208 -0
  190. package/dist/server/server/agent/providers/omp/commands.d.ts +8 -0
  191. package/dist/server/server/agent/providers/omp/commands.js +62 -0
  192. package/dist/server/server/agent/providers/omp/custom-message.d.ts +7 -0
  193. package/dist/server/server/agent/providers/omp/custom-message.js +4 -0
  194. package/dist/server/server/agent/providers/omp/event-mapper.d.ts +13 -0
  195. package/dist/server/server/agent/providers/omp/event-mapper.js +267 -0
  196. package/dist/server/server/agent/providers/omp/history-hooks.d.ts +3 -0
  197. package/dist/server/server/agent/providers/omp/history-hooks.js +13 -0
  198. package/dist/server/server/agent/providers/omp/history.d.ts +19 -0
  199. package/dist/server/server/agent/providers/omp/history.js +306 -0
  200. package/dist/server/server/agent/providers/omp/host-tools.d.ts +14 -0
  201. package/dist/server/server/agent/providers/omp/host-tools.js +196 -0
  202. package/dist/server/server/agent/providers/omp/map-omp-model.d.ts +11 -0
  203. package/dist/server/server/agent/providers/omp/map-omp-model.js +67 -0
  204. package/dist/server/server/agent/providers/omp/message-history.d.ts +38 -0
  205. package/dist/server/server/agent/providers/omp/message-history.js +216 -0
  206. package/dist/server/server/agent/providers/omp/protocol-session.d.ts +13 -0
  207. package/dist/server/server/agent/providers/omp/protocol-session.js +39 -0
  208. package/dist/server/server/agent/providers/omp/provider-config.d.ts +43 -0
  209. package/dist/server/server/agent/providers/omp/provider-config.js +120 -0
  210. package/dist/server/server/agent/providers/omp/rpc-types.d.ts +2040 -0
  211. package/dist/server/server/agent/providers/omp/rpc-types.js +551 -0
  212. package/dist/server/server/agent/providers/omp/rpc-ui-permission-mapper.d.ts +24 -0
  213. package/dist/server/server/agent/providers/omp/rpc-ui-permission-mapper.js +156 -0
  214. package/dist/server/server/agent/providers/omp/runtime.d.ts +85 -0
  215. package/dist/server/server/agent/providers/omp/runtime.js +62 -0
  216. package/dist/server/server/agent/providers/omp/session-descriptor.d.ts +16 -0
  217. package/dist/server/server/agent/providers/omp/session-descriptor.js +389 -0
  218. package/dist/server/server/agent/providers/omp/subagent-card-tracker.d.ts +33 -0
  219. package/dist/server/server/agent/providers/omp/subagent-card-tracker.js +264 -0
  220. package/dist/server/server/agent/providers/omp/subagent-index.d.ts +13 -0
  221. package/dist/server/server/agent/providers/omp/subagent-index.js +111 -0
  222. package/dist/server/server/agent/providers/omp/subagent-title.d.ts +2 -0
  223. package/dist/server/server/agent/providers/omp/subagent-title.js +14 -0
  224. package/dist/server/server/agent/providers/omp/system-notice.d.ts +8 -0
  225. package/dist/server/server/agent/providers/omp/system-notice.js +68 -0
  226. package/dist/server/server/agent/providers/omp/todo-mapper.d.ts +9 -0
  227. package/dist/server/server/agent/providers/omp/todo-mapper.js +52 -0
  228. package/dist/server/server/agent/providers/omp/tool-call-detail.d.ts +110 -0
  229. package/dist/server/server/agent/providers/omp/tool-call-detail.js +288 -0
  230. package/dist/server/server/agent/providers/omp/tool-call-id.d.ts +4 -0
  231. package/dist/server/server/agent/providers/omp/tool-call-id.js +34 -0
  232. package/dist/server/server/agent/providers/omp/tool-call-mapper.d.ts +7 -0
  233. package/dist/server/server/agent/providers/omp/tool-call-mapper.js +98 -0
  234. package/dist/server/server/agent/providers/omp/usage-poller.d.ts +32 -0
  235. package/dist/server/server/agent/providers/omp/usage-poller.js +141 -0
  236. package/dist/server/server/agent/providers/opencode/bridge-plugin.bundle.mjs +14678 -0
  237. package/dist/server/server/agent/providers/opencode/bridge.d.ts +39 -0
  238. package/dist/server/server/agent/providers/opencode/bridge.js +249 -0
  239. package/dist/server/server/agent/providers/opencode/event-consumer.d.ts +60 -0
  240. package/dist/server/server/agent/providers/opencode/event-consumer.js +221 -0
  241. package/dist/server/server/agent/providers/opencode/options.d.ts +156 -0
  242. package/dist/server/server/agent/providers/opencode/options.js +62 -0
  243. package/dist/server/server/agent/providers/opencode/paths.d.ts +2 -0
  244. package/dist/server/server/agent/providers/opencode/paths.js +7 -0
  245. package/dist/server/server/agent/providers/opencode/rewind.d.ts +18 -0
  246. package/dist/server/server/agent/providers/opencode/rewind.js +14 -0
  247. package/dist/server/server/agent/providers/opencode/server-manager.d.ts +101 -0
  248. package/dist/server/server/agent/providers/opencode/server-manager.js +513 -0
  249. package/dist/server/server/agent/providers/opencode/side-question.d.ts +78 -0
  250. package/dist/server/server/agent/providers/opencode/side-question.js +172 -0
  251. package/dist/server/server/agent/providers/opencode/subagent-presentation.d.ts +36 -0
  252. package/dist/server/server/agent/providers/opencode/subagent-presentation.js +62 -0
  253. package/dist/server/server/agent/providers/opencode/test-server-manager.d.ts +22 -0
  254. package/dist/server/server/agent/providers/opencode/test-server-manager.js +43 -0
  255. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts +3 -0
  256. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +256 -0
  257. package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts +13 -0
  258. package/dist/server/server/agent/providers/opencode/tool-call-mapper.js +53 -0
  259. package/dist/server/server/agent/providers/opencode-agent.d.ts +393 -0
  260. package/dist/server/server/agent/providers/opencode-agent.js +4106 -0
  261. package/dist/server/server/agent/providers/pi/agent.d.ts +164 -0
  262. package/dist/server/server/agent/providers/pi/agent.js +2236 -0
  263. package/dist/server/server/agent/providers/pi/cli-runtime.d.ts +21 -0
  264. package/dist/server/server/agent/providers/pi/cli-runtime.js +177 -0
  265. package/dist/server/server/agent/providers/pi/history-mapper.d.ts +36 -0
  266. package/dist/server/server/agent/providers/pi/history-mapper.js +212 -0
  267. package/dist/server/server/agent/providers/pi/rewind.d.ts +8 -0
  268. package/dist/server/server/agent/providers/pi/rewind.js +8 -0
  269. package/dist/server/server/agent/providers/pi/rpc-types.d.ts +252 -0
  270. package/dist/server/server/agent/providers/pi/rpc-types.js +2 -0
  271. package/dist/server/server/agent/providers/pi/runtime.d.ts +77 -0
  272. package/dist/server/server/agent/providers/pi/runtime.js +65 -0
  273. package/dist/server/server/agent/providers/pi/session-descriptor.d.ts +16 -0
  274. package/dist/server/server/agent/providers/pi/session-descriptor.js +355 -0
  275. package/dist/server/server/agent/providers/pi/tool-call-mapper.d.ts +113 -0
  276. package/dist/server/server/agent/providers/pi/tool-call-mapper.js +340 -0
  277. package/dist/server/server/agent/providers/pi/usage-poller.d.ts +32 -0
  278. package/dist/server/server/agent/providers/pi/usage-poller.js +141 -0
  279. package/dist/server/server/agent/providers/provider-image-output.d.ts +25 -0
  280. package/dist/server/server/agent/providers/provider-image-output.js +165 -0
  281. package/dist/server/server/agent/providers/provider-runner.d.ts +27 -0
  282. package/dist/server/server/agent/providers/provider-runner.js +81 -0
  283. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +884 -0
  284. package/dist/server/server/agent/providers/tool-call-detail-primitives.js +778 -0
  285. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +25 -0
  286. package/dist/server/server/agent/providers/tool-call-mapper-utils.js +208 -0
  287. package/dist/server/server/agent/providers/trae-acp-agent.d.ts +15 -0
  288. package/dist/server/server/agent/providers/trae-acp-agent.js +18 -0
  289. package/dist/server/server/agent/recordings-debug.d.ts +3 -0
  290. package/dist/server/server/agent/recordings-debug.js +19 -0
  291. package/dist/server/server/agent/rewind/rewind.d.ts +10 -0
  292. package/dist/server/server/agent/rewind/rewind.js +29 -0
  293. package/dist/server/server/agent/rewind/test-rewind-session.d.ts +48 -0
  294. package/dist/server/server/agent/rewind/test-rewind-session.js +88 -0
  295. package/dist/server/server/agent/runtime-mcp-config.d.ts +14 -0
  296. package/dist/server/server/agent/runtime-mcp-config.js +53 -0
  297. package/dist/server/server/agent/side-conversations/store.d.ts +33 -0
  298. package/dist/server/server/agent/side-conversations/store.js +62 -0
  299. package/dist/server/server/agent/stale-provider-session-error.d.ts +6 -0
  300. package/dist/server/server/agent/stale-provider-session-error.js +11 -0
  301. package/dist/server/server/agent/structured-generation-providers.d.ts +29 -0
  302. package/dist/server/server/agent/structured-generation-providers.js +193 -0
  303. package/dist/server/server/agent/stt-debug.d.ts +10 -0
  304. package/dist/server/server/agent/stt-debug.js +33 -0
  305. package/dist/server/server/agent/stt-manager.d.ts +38 -0
  306. package/dist/server/server/agent/stt-manager.js +246 -0
  307. package/dist/server/server/agent/system-prompt.d.ts +2 -0
  308. package/dist/server/server/agent/system-prompt.js +8 -0
  309. package/dist/server/server/agent/timeline-append.d.ts +10 -0
  310. package/dist/server/server/agent/timeline-append.js +27 -0
  311. package/dist/server/server/agent/timeline-page-bounds.d.ts +19 -0
  312. package/dist/server/server/agent/timeline-page-bounds.js +37 -0
  313. package/dist/server/server/agent/timeline-projection.d.ts +74 -0
  314. package/dist/server/server/agent/timeline-projection.js +467 -0
  315. package/dist/server/server/agent/timeline-prompt-index.d.ts +12 -0
  316. package/dist/server/server/agent/timeline-prompt-index.js +23 -0
  317. package/dist/server/server/agent/tools/paseo-tool-serialization.d.ts +4 -0
  318. package/dist/server/server/agent/tools/paseo-tool-serialization.js +58 -0
  319. package/dist/server/server/agent/tools/paseo-tools.d.ts +62 -0
  320. package/dist/server/server/agent/tools/paseo-tools.js +2445 -0
  321. package/dist/server/server/agent/tools/types.d.ts +39 -0
  322. package/dist/server/server/agent/tools/types.js +2 -0
  323. package/dist/server/server/agent/tts-debug.d.ts +8 -0
  324. package/dist/server/server/agent/tts-debug.js +24 -0
  325. package/dist/server/server/agent/tts-manager.d.ts +41 -0
  326. package/dist/server/server/agent/tts-manager.js +375 -0
  327. package/dist/server/server/agent-attention-policy.d.ts +29 -0
  328. package/dist/server/server/agent-attention-policy.js +36 -0
  329. package/dist/server/server/agent-history-search.d.ts +48 -0
  330. package/dist/server/server/agent-history-search.js +129 -0
  331. package/dist/server/server/atomic-file.d.ts +3 -0
  332. package/dist/server/server/atomic-file.js +19 -0
  333. package/dist/server/server/auth.d.ts +38 -0
  334. package/dist/server/server/auth.js +122 -0
  335. package/dist/server/server/authorization/index.d.ts +18 -0
  336. package/dist/server/server/authorization/index.js +47 -0
  337. package/dist/server/server/authorization/operation-permissions.d.ts +8 -0
  338. package/dist/server/server/authorization/operation-permissions.js +438 -0
  339. package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts +40 -0
  340. package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +64 -0
  341. package/dist/server/server/auto-archive-on-merge/index.d.ts +13 -0
  342. package/dist/server/server/auto-archive-on-merge/index.js +77 -0
  343. package/dist/server/server/bootstrap.d.ts +166 -0
  344. package/dist/server/server/bootstrap.js +1388 -0
  345. package/dist/server/server/browser-tools/broker.d.ts +45 -0
  346. package/dist/server/server/browser-tools/broker.js +390 -0
  347. package/dist/server/server/browser-tools/errors.d.ts +22 -0
  348. package/dist/server/server/browser-tools/errors.js +27 -0
  349. package/dist/server/server/browser-tools/policy.d.ts +10 -0
  350. package/dist/server/server/browser-tools/policy.js +16 -0
  351. package/dist/server/server/browser-tools/tools.d.ts +16 -0
  352. package/dist/server/server/browser-tools/tools.js +796 -0
  353. package/dist/server/server/checkout/status-projection.d.ts +19 -0
  354. package/dist/server/server/checkout/status-projection.js +127 -0
  355. package/dist/server/server/checkout-diff-manager.d.ts +48 -0
  356. package/dist/server/server/checkout-diff-manager.js +284 -0
  357. package/dist/server/server/checkout-git-utils.d.ts +11 -0
  358. package/dist/server/server/checkout-git-utils.js +34 -0
  359. package/dist/server/server/client-message-id.d.ts +3 -0
  360. package/dist/server/server/client-message-id.js +12 -0
  361. package/dist/server/server/config.d.ts +26 -0
  362. package/dist/server/server/config.js +594 -0
  363. package/dist/server/server/connection-offer.d.ts +20 -0
  364. package/dist/server/server/connection-offer.js +59 -0
  365. package/dist/server/server/creation/index.d.ts +41 -0
  366. package/dist/server/server/creation/index.js +250 -0
  367. package/dist/server/server/daemon-config-store.d.ts +63 -0
  368. package/dist/server/server/daemon-config-store.js +524 -0
  369. package/dist/server/server/daemon-keypair.d.ts +8 -0
  370. package/dist/server/server/daemon-keypair.js +42 -0
  371. package/dist/server/server/daemon-version.d.ts +5 -0
  372. package/dist/server/server/daemon-version.js +22 -0
  373. package/dist/server/server/daemon-worker.d.ts +2 -0
  374. package/dist/server/server/daemon-worker.js +287 -0
  375. package/dist/server/server/dictation/dictation-stream-manager.d.ts +88 -0
  376. package/dist/server/server/dictation/dictation-stream-manager.js +578 -0
  377. package/dist/server/server/directory-sync/index.d.ts +45 -0
  378. package/dist/server/server/directory-sync/index.js +98 -0
  379. package/dist/server/server/directory-sync/internal/versioned-collection.d.ts +56 -0
  380. package/dist/server/server/directory-sync/internal/versioned-collection.js +94 -0
  381. package/dist/server/server/exports.d.ts +24 -0
  382. package/dist/server/server/exports.js +24 -0
  383. package/dist/server/server/file-download/token-store.d.ts +24 -0
  384. package/dist/server/server/file-download/token-store.js +40 -0
  385. package/dist/server/server/file-explorer/observer.d.ts +32 -0
  386. package/dist/server/server/file-explorer/observer.js +130 -0
  387. package/dist/server/server/file-explorer/service.d.ts +125 -0
  388. package/dist/server/server/file-explorer/service.js +663 -0
  389. package/dist/server/server/file-observer/index.d.ts +43 -0
  390. package/dist/server/server/file-observer/index.js +114 -0
  391. package/dist/server/server/file-observer/internal/contracts.d.ts +26 -0
  392. package/dist/server/server/file-observer/internal/contracts.js +2 -0
  393. package/dist/server/server/file-observer/internal/linux.d.ts +4 -0
  394. package/dist/server/server/file-observer/internal/linux.js +260 -0
  395. package/dist/server/server/file-observer/internal/native-recursive.d.ts +9 -0
  396. package/dist/server/server/file-observer/internal/native-recursive.js +577 -0
  397. package/dist/server/server/file-observer/internal/observation.d.ts +21 -0
  398. package/dist/server/server/file-observer/internal/observation.js +129 -0
  399. package/dist/server/server/file-observer/internal/paths.d.ts +10 -0
  400. package/dist/server/server/file-observer/internal/paths.js +43 -0
  401. package/dist/server/server/file-upload/index.d.ts +27 -0
  402. package/dist/server/server/file-upload/index.js +158 -0
  403. package/dist/server/server/git-metadata-event-rules.d.ts +123 -0
  404. package/dist/server/server/git-metadata-event-rules.js +152 -0
  405. package/dist/server/server/hostnames.d.ts +13 -0
  406. package/dist/server/server/hostnames.js +94 -0
  407. package/dist/server/server/hub/daemon-executions.d.ts +89 -0
  408. package/dist/server/server/hub/daemon-executions.js +287 -0
  409. package/dist/server/server/hub/execution-controller.d.ts +30 -0
  410. package/dist/server/server/hub/execution-controller.js +220 -0
  411. package/dist/server/server/hub/relationship-controller.d.ts +116 -0
  412. package/dist/server/server/hub/relationship-controller.js +534 -0
  413. package/dist/server/server/hub/relationship-remote.d.ts +68 -0
  414. package/dist/server/server/hub/relationship-remote.js +159 -0
  415. package/dist/server/server/hub/relationship-retry.d.ts +7 -0
  416. package/dist/server/server/hub/relationship-retry.js +15 -0
  417. package/dist/server/server/json-utils.d.ts +11 -0
  418. package/dist/server/server/json-utils.js +45 -0
  419. package/dist/server/server/lifecycle-reasons.d.ts +4 -0
  420. package/dist/server/server/lifecycle-reasons.js +6 -0
  421. package/dist/server/server/logger.d.ts +29 -0
  422. package/dist/server/server/logger.js +127 -0
  423. package/dist/server/server/managed-processes/managed-processes.d.ts +76 -0
  424. package/dist/server/server/managed-processes/managed-processes.js +326 -0
  425. package/dist/server/server/messages.d.ts +9 -0
  426. package/dist/server/server/messages.js +29 -0
  427. package/dist/server/server/migrations/backfill-workspace-id.migration.d.ts +9 -0
  428. package/dist/server/server/migrations/backfill-workspace-id.migration.js +64 -0
  429. package/dist/server/server/orchestration-skills/index.d.ts +18 -0
  430. package/dist/server/server/orchestration-skills/index.js +18 -0
  431. package/dist/server/server/orchestration-skills/internal/controller.d.ts +39 -0
  432. package/dist/server/server/orchestration-skills/internal/controller.js +108 -0
  433. package/dist/server/server/orchestration-skills/internal/operations.d.ts +43 -0
  434. package/dist/server/server/orchestration-skills/internal/operations.js +178 -0
  435. package/dist/server/server/orchestration-skills/internal/paths.d.ts +4 -0
  436. package/dist/server/server/orchestration-skills/internal/paths.js +21 -0
  437. package/dist/server/server/orchestration-skills/internal/selection-store.d.ts +12 -0
  438. package/dist/server/server/orchestration-skills/internal/selection-store.js +39 -0
  439. package/dist/server/server/orchestration-skills/internal/sync.d.ts +21 -0
  440. package/dist/server/server/orchestration-skills/internal/sync.js +177 -0
  441. package/dist/server/server/orchestration-skills/internal/transaction.d.ts +22 -0
  442. package/dist/server/server/orchestration-skills/internal/transaction.js +483 -0
  443. package/dist/server/server/package-version.d.ts +19 -0
  444. package/dist/server/server/package-version.js +60 -0
  445. package/dist/server/server/pagination/cursor.d.ts +16 -0
  446. package/dist/server/server/pagination/cursor.js +62 -0
  447. package/dist/server/server/pagination/sortable-pager.d.ts +24 -0
  448. package/dist/server/server/pagination/sortable-pager.js +68 -0
  449. package/dist/server/server/pairing-offer.d.ts +18 -0
  450. package/dist/server/server/pairing-offer.js +47 -0
  451. package/dist/server/server/pairing-qr.d.ts +2 -0
  452. package/dist/server/server/pairing-qr.js +15 -0
  453. package/dist/server/server/paseo-env.d.ts +13 -0
  454. package/dist/server/server/paseo-env.js +54 -0
  455. package/dist/server/server/paseo-home.d.ts +2 -0
  456. package/dist/server/server/paseo-home.js +19 -0
  457. package/dist/server/server/paseo-worktree-service.d.ts +45 -0
  458. package/dist/server/server/paseo-worktree-service.js +191 -0
  459. package/dist/server/server/path-utils.d.ts +5 -0
  460. package/dist/server/server/path-utils.js +34 -0
  461. package/dist/server/server/persisted-config.d.ts +397 -0
  462. package/dist/server/server/persisted-config.js +411 -0
  463. package/dist/server/server/persistence-hooks.d.ts +32 -0
  464. package/dist/server/server/persistence-hooks.js +96 -0
  465. package/dist/server/server/pid-lock.d.ts +44 -0
  466. package/dist/server/server/pid-lock.js +285 -0
  467. package/dist/server/server/plugins/compiler-imports.d.ts +13 -0
  468. package/dist/server/server/plugins/compiler-imports.js +90 -0
  469. package/dist/server/server/plugins/compiler.d.ts +10 -0
  470. package/dist/server/server/plugins/compiler.js +354 -0
  471. package/dist/server/server/plugins/daemon-transport.d.ts +9 -0
  472. package/dist/server/server/plugins/daemon-transport.js +68 -0
  473. package/dist/server/server/plugins/index.d.ts +102 -0
  474. package/dist/server/server/plugins/index.js +575 -0
  475. package/dist/server/server/plugins/lifecycle/index.d.ts +40 -0
  476. package/dist/server/server/plugins/lifecycle/index.js +200 -0
  477. package/dist/server/server/plugins/managed-source.d.ts +50 -0
  478. package/dist/server/server/plugins/managed-source.js +327 -0
  479. package/dist/server/server/plugins/manifest.d.ts +12 -0
  480. package/dist/server/server/plugins/manifest.js +26 -0
  481. package/dist/server/server/plugins/plugin-process-protocol.d.ts +120 -0
  482. package/dist/server/server/plugins/plugin-process-protocol.js +154 -0
  483. package/dist/server/server/plugins/plugin-process.d.ts +2 -0
  484. package/dist/server/server/plugins/plugin-process.js +419 -0
  485. package/dist/server/server/plugins/plugin-sdk-specifiers.d.ts +5 -0
  486. package/dist/server/server/plugins/plugin-sdk-specifiers.js +23 -0
  487. package/dist/server/server/plugins/plugin-session-identity.d.ts +4 -0
  488. package/dist/server/server/plugins/plugin-session-identity.js +11 -0
  489. package/dist/server/server/plugins/preparation.d.ts +4 -0
  490. package/dist/server/server/plugins/preparation.js +49 -0
  491. package/dist/server/server/plugins/provider-icon.d.ts +2 -0
  492. package/dist/server/server/plugins/provider-icon.js +55 -0
  493. package/dist/server/server/plugins/runtime.d.ts +83 -0
  494. package/dist/server/server/plugins/runtime.js +836 -0
  495. package/dist/server/server/plugins/session-socket.d.ts +23 -0
  496. package/dist/server/server/plugins/session-socket.js +82 -0
  497. package/dist/server/server/plugins/settings/index.d.ts +96 -0
  498. package/dist/server/server/plugins/settings/index.js +115 -0
  499. package/dist/server/server/private-files.d.ts +6 -0
  500. package/dist/server/server/private-files.js +37 -0
  501. package/dist/server/server/process-diagnostics.d.ts +17 -0
  502. package/dist/server/server/process-diagnostics.js +22 -0
  503. package/dist/server/server/project-directory-service.d.ts +30 -0
  504. package/dist/server/server/project-directory-service.js +120 -0
  505. package/dist/server/server/project-key.d.ts +14 -0
  506. package/dist/server/server/project-key.js +44 -0
  507. package/dist/server/server/push/index.d.ts +16 -0
  508. package/dist/server/server/push/index.js +26 -0
  509. package/dist/server/server/push/push-service.d.ts +19 -0
  510. package/dist/server/server/push/push-service.js +66 -0
  511. package/dist/server/server/push/token-store.d.ts +22 -0
  512. package/dist/server/server/push/token-store.js +125 -0
  513. package/dist/server/server/relay-runtime.d.ts +27 -0
  514. package/dist/server/server/relay-runtime.js +46 -0
  515. package/dist/server/server/relay-transport.d.ts +33 -0
  516. package/dist/server/server/relay-transport.js +481 -0
  517. package/dist/server/server/request-receipts/index.d.ts +33 -0
  518. package/dist/server/server/request-receipts/index.js +131 -0
  519. package/dist/server/server/resolve-workspace-id-for-path.d.ts +3 -0
  520. package/dist/server/server/resolve-workspace-id-for-path.js +41 -0
  521. package/dist/server/server/resolve-worktree-creation-intent.d.ts +44 -0
  522. package/dist/server/server/resolve-worktree-creation-intent.js +186 -0
  523. package/dist/server/server/schedule/cron.d.ts +4 -0
  524. package/dist/server/server/schedule/cron.js +83 -0
  525. package/dist/server/server/schedule/service.d.ts +75 -0
  526. package/dist/server/server/schedule/service.js +810 -0
  527. package/dist/server/server/schedule/store.d.ts +27 -0
  528. package/dist/server/server/schedule/store.js +190 -0
  529. package/dist/server/server/script-health-monitor.d.ts +39 -0
  530. package/dist/server/server/script-health-monitor.js +159 -0
  531. package/dist/server/server/script-proxy.d.ts +3 -0
  532. package/dist/server/server/script-proxy.js +2 -0
  533. package/dist/server/server/script-route-branch-handler.d.ts +10 -0
  534. package/dist/server/server/script-route-branch-handler.js +11 -0
  535. package/dist/server/server/script-status-projection.d.ts +36 -0
  536. package/dist/server/server/script-status-projection.js +200 -0
  537. package/dist/server/server/server-id.d.ts +17 -0
  538. package/dist/server/server/server-id.js +68 -0
  539. package/dist/server/server/service-proxy.d.ts +237 -0
  540. package/dist/server/server/service-proxy.js +679 -0
  541. package/dist/server/server/session/agent-config/agent-config-session.d.ts +75 -0
  542. package/dist/server/server/session/agent-config/agent-config-session.js +151 -0
  543. package/dist/server/server/session/agent-updates/agent-updates-service.d.ts +65 -0
  544. package/dist/server/server/session/agent-updates/agent-updates-service.js +266 -0
  545. package/dist/server/server/session/checkout/checkout-session.d.ts +150 -0
  546. package/dist/server/server/session/checkout/checkout-session.js +1187 -0
  547. package/dist/server/server/session/checkout/git-metadata-generator.d.ts +53 -0
  548. package/dist/server/server/session/checkout/git-metadata-generator.js +159 -0
  549. package/dist/server/server/session/daemon/daemon-self-update-session-controller.d.ts +34 -0
  550. package/dist/server/server/session/daemon/daemon-self-update-session-controller.js +90 -0
  551. package/dist/server/server/session/daemon/daemon-self-updater.d.ts +33 -0
  552. package/dist/server/server/session/daemon/daemon-self-updater.js +60 -0
  553. package/dist/server/server/session/daemon/daemon-session.d.ts +90 -0
  554. package/dist/server/server/session/daemon/daemon-session.js +224 -0
  555. package/dist/server/server/session/daemon/diagnostics.d.ts +41 -0
  556. package/dist/server/server/session/daemon/diagnostics.js +431 -0
  557. package/dist/server/server/session/daemon/install-origin.d.ts +7 -0
  558. package/dist/server/server/session/daemon/install-origin.js +64 -0
  559. package/dist/server/server/session/daemon/npm-global-cli.d.ts +29 -0
  560. package/dist/server/server/session/daemon/npm-global-cli.js +98 -0
  561. package/dist/server/server/session/files/workspace-files-session.d.ts +55 -0
  562. package/dist/server/server/session/files/workspace-files-session.js +359 -0
  563. package/dist/server/server/session/git-mutation/git-mutation-service.d.ts +32 -0
  564. package/dist/server/server/session/git-mutation/git-mutation-service.js +74 -0
  565. package/dist/server/server/session/project-config/project-config-session.d.ts +35 -0
  566. package/dist/server/server/session/project-config/project-config-session.js +143 -0
  567. package/dist/server/server/session/project-config/worktree-setup-commit-status.d.ts +6 -0
  568. package/dist/server/server/session/project-config/worktree-setup-commit-status.js +38 -0
  569. package/dist/server/server/session/provider/provider-catalog-session.d.ts +78 -0
  570. package/dist/server/server/session/provider/provider-catalog-session.js +388 -0
  571. package/dist/server/server/session/schedule/schedule-session.d.ts +47 -0
  572. package/dist/server/server/session/schedule/schedule-session.js +188 -0
  573. package/dist/server/server/session/voice/voice-session.d.ts +166 -0
  574. package/dist/server/server/session/voice/voice-session.js +904 -0
  575. package/dist/server/server/session/voice/voice-turn-controller.d.ts +38 -0
  576. package/dist/server/server/session/voice/voice-turn-controller.js +393 -0
  577. package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.d.ts +42 -0
  578. package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.js +170 -0
  579. package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.d.ts +59 -0
  580. package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.js +326 -0
  581. package/dist/server/server/session/workspace-recovery/workspace-recovery-service.d.ts +30 -0
  582. package/dist/server/server/session/workspace-recovery/workspace-recovery-service.js +178 -0
  583. package/dist/server/server/session/workspace-scripts/workspace-scripts-service.d.ts +54 -0
  584. package/dist/server/server/session/workspace-scripts/workspace-scripts-service.js +156 -0
  585. package/dist/server/server/session.d.ts +555 -0
  586. package/dist/server/server/session.js +6540 -0
  587. package/dist/server/server/speech/audio.d.ts +10 -0
  588. package/dist/server/server/speech/audio.js +101 -0
  589. package/dist/server/server/speech/provider-resolver.d.ts +3 -0
  590. package/dist/server/server/speech/provider-resolver.js +7 -0
  591. package/dist/server/server/speech/providers/local/config.d.ts +30 -0
  592. package/dist/server/server/speech/providers/local/config.js +134 -0
  593. package/dist/server/server/speech/providers/local/models.d.ts +12 -0
  594. package/dist/server/server/speech/providers/local/models.js +18 -0
  595. package/dist/server/server/speech/providers/local/runtime.d.ts +31 -0
  596. package/dist/server/server/speech/providers/local/runtime.js +135 -0
  597. package/dist/server/server/speech/providers/local/sherpa/assets/silero_vad.onnx +0 -0
  598. package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts +56 -0
  599. package/dist/server/server/speech/providers/local/sherpa/model-catalog.js +74 -0
  600. package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts +17 -0
  601. package/dist/server/server/speech/providers/local/sherpa/model-downloader.js +145 -0
  602. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts +49 -0
  603. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js +73 -0
  604. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts +9 -0
  605. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js +107 -0
  606. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.d.ts +28 -0
  607. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js +137 -0
  608. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts +21 -0
  609. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js +133 -0
  610. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.d.ts +18 -0
  611. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.js +84 -0
  612. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts +21 -0
  613. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js +101 -0
  614. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.d.ts +19 -0
  615. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.js +49 -0
  616. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.d.ts +38 -0
  617. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.js +176 -0
  618. package/dist/server/server/speech/providers/local/worker-bytes.d.ts +4 -0
  619. package/dist/server/server/speech/providers/local/worker-bytes.js +9 -0
  620. package/dist/server/server/speech/providers/local/worker-client.d.ts +93 -0
  621. package/dist/server/server/speech/providers/local/worker-client.js +590 -0
  622. package/dist/server/server/speech/providers/local/worker-process.d.ts +2 -0
  623. package/dist/server/server/speech/providers/local/worker-process.js +270 -0
  624. package/dist/server/server/speech/providers/local/worker-protocol.d.ts +95 -0
  625. package/dist/server/server/speech/providers/local/worker-protocol.js +2 -0
  626. package/dist/server/server/speech/providers/openai/config.d.ts +19 -0
  627. package/dist/server/server/speech/providers/openai/config.js +148 -0
  628. package/dist/server/server/speech/providers/openai/runtime.d.ts +29 -0
  629. package/dist/server/server/speech/providers/openai/runtime.js +102 -0
  630. package/dist/server/server/speech/providers/openai/stt.d.ts +23 -0
  631. package/dist/server/server/speech/providers/openai/stt.js +209 -0
  632. package/dist/server/server/speech/providers/openai/tts.d.ts +19 -0
  633. package/dist/server/server/speech/providers/openai/tts.js +48 -0
  634. package/dist/server/server/speech/speech-config-resolver.d.ts +11 -0
  635. package/dist/server/server/speech/speech-config-resolver.js +132 -0
  636. package/dist/server/server/speech/speech-provider.d.ts +59 -0
  637. package/dist/server/server/speech/speech-provider.js +2 -0
  638. package/dist/server/server/speech/speech-runtime.d.ts +45 -0
  639. package/dist/server/server/speech/speech-runtime.js +571 -0
  640. package/dist/server/server/speech/speech-types.d.ts +22 -0
  641. package/dist/server/server/speech/speech-types.js +8 -0
  642. package/dist/server/server/speech/turn-detection-provider.d.ts +23 -0
  643. package/dist/server/server/speech/turn-detection-provider.js +2 -0
  644. package/dist/server/server/utils/diff-highlighter.d.ts +57 -0
  645. package/dist/server/server/utils/diff-highlighter.js +304 -0
  646. package/dist/server/server/voice-config.d.ts +15 -0
  647. package/dist/server/server/voice-config.js +54 -0
  648. package/dist/server/server/voice-permission-policy.d.ts +4 -0
  649. package/dist/server/server/voice-permission-policy.js +13 -0
  650. package/dist/server/server/voice-types.d.ts +12 -0
  651. package/dist/server/server/voice-types.js +2 -0
  652. package/dist/server/server/watcher-liveness-canary.d.ts +11 -0
  653. package/dist/server/server/watcher-liveness-canary.js +53 -0
  654. package/dist/server/server/web-ui.d.ts +10 -0
  655. package/dist/server/server/web-ui.js +205 -0
  656. package/dist/server/server/websocket/encrypted-relay-socket.d.ts +23 -0
  657. package/dist/server/server/websocket/encrypted-relay-socket.js +64 -0
  658. package/dist/server/server/websocket/physical-socket.d.ts +36 -0
  659. package/dist/server/server/websocket/physical-socket.js +95 -0
  660. package/dist/server/server/websocket/runtime-metrics.d.ts +95 -0
  661. package/dist/server/server/websocket/runtime-metrics.js +148 -0
  662. package/dist/server/server/websocket-server.d.ts +214 -0
  663. package/dist/server/server/websocket-server.js +2258 -0
  664. package/dist/server/server/workspace-archive-service.d.ts +63 -0
  665. package/dist/server/server/workspace-archive-service.js +355 -0
  666. package/dist/server/server/workspace-auto-name.d.ts +55 -0
  667. package/dist/server/server/workspace-auto-name.js +127 -0
  668. package/dist/server/server/workspace-automation-gate.d.ts +16 -0
  669. package/dist/server/server/workspace-automation-gate.js +35 -0
  670. package/dist/server/server/workspace-bootstrap-dedupe.d.ts +34 -0
  671. package/dist/server/server/workspace-bootstrap-dedupe.js +23 -0
  672. package/dist/server/server/workspace-directory.d.ts +99 -0
  673. package/dist/server/server/workspace-directory.js +467 -0
  674. package/dist/server/server/workspace-git-fetch.d.ts +33 -0
  675. package/dist/server/server/workspace-git-fetch.js +108 -0
  676. package/dist/server/server/workspace-git-metadata.d.ts +8 -0
  677. package/dist/server/server/workspace-git-metadata.js +24 -0
  678. package/dist/server/server/workspace-git-service.d.ts +348 -0
  679. package/dist/server/server/workspace-git-service.js +2534 -0
  680. package/dist/server/server/workspace-labels/index.d.ts +14 -0
  681. package/dist/server/server/workspace-labels/index.js +10 -0
  682. package/dist/server/server/workspace-labels/internal/catalog-store.d.ts +50 -0
  683. package/dist/server/server/workspace-labels/internal/catalog-store.js +203 -0
  684. package/dist/server/server/workspace-labels/internal/sequence.d.ts +43 -0
  685. package/dist/server/server/workspace-labels/internal/sequence.js +80 -0
  686. package/dist/server/server/workspace-labels/internal/service.d.ts +57 -0
  687. package/dist/server/server/workspace-labels/internal/service.js +224 -0
  688. package/dist/server/server/workspace-reconciliation-service.d.ts +103 -0
  689. package/dist/server/server/workspace-reconciliation-service.js +379 -0
  690. package/dist/server/server/workspace-registry-bootstrap-legacy.d.ts +21 -0
  691. package/dist/server/server/workspace-registry-bootstrap-legacy.js +57 -0
  692. package/dist/server/server/workspace-registry-bootstrap.d.ts +14 -0
  693. package/dist/server/server/workspace-registry-bootstrap.js +155 -0
  694. package/dist/server/server/workspace-registry-model.d.ts +56 -0
  695. package/dist/server/server/workspace-registry-model.js +150 -0
  696. package/dist/server/server/workspace-registry.d.ts +228 -0
  697. package/dist/server/server/workspace-registry.js +468 -0
  698. package/dist/server/server/workspace-script-runtime-store.d.ts +28 -0
  699. package/dist/server/server/workspace-script-runtime-store.js +78 -0
  700. package/dist/server/server/workspace-service-env.d.ts +18 -0
  701. package/dist/server/server/workspace-service-env.js +85 -0
  702. package/dist/server/server/workspace-service-port-allocator.d.ts +11 -0
  703. package/dist/server/server/workspace-service-port-allocator.js +89 -0
  704. package/dist/server/server/workspace-service-port-registry.d.ts +24 -0
  705. package/dist/server/server/workspace-service-port-registry.js +172 -0
  706. package/dist/server/server/workspace-setup-runtime.d.ts +7 -0
  707. package/dist/server/server/workspace-setup-runtime.js +30 -0
  708. package/dist/server/server/workspace-source.d.ts +7 -0
  709. package/dist/server/server/workspace-source.js +15 -0
  710. package/dist/server/server/worktree/commands.d.ts +55 -0
  711. package/dist/server/server/worktree/commands.js +99 -0
  712. package/dist/server/server/worktree-bootstrap.d.ts +86 -0
  713. package/dist/server/server/worktree-bootstrap.js +753 -0
  714. package/dist/server/server/worktree-branch-name-generator.d.ts +35 -0
  715. package/dist/server/server/worktree-branch-name-generator.js +89 -0
  716. package/dist/server/server/worktree-core.d.ts +32 -0
  717. package/dist/server/server/worktree-core.js +114 -0
  718. package/dist/server/server/worktree-errors.d.ts +12 -0
  719. package/dist/server/server/worktree-errors.js +28 -0
  720. package/dist/server/server/worktree-session.d.ts +165 -0
  721. package/dist/server/server/worktree-session.js +594 -0
  722. package/dist/server/services/forge-cli-command.d.ts +128 -0
  723. package/dist/server/services/forge-cli-command.js +212 -0
  724. package/dist/server/services/forge-registry.d.ts +25 -0
  725. package/dist/server/services/forge-registry.js +155 -0
  726. package/dist/server/services/forge-resolver.d.ts +38 -0
  727. package/dist/server/services/forge-resolver.js +191 -0
  728. package/dist/server/services/forge-service.d.ts +430 -0
  729. package/dist/server/services/forge-service.js +50 -0
  730. package/dist/server/services/gitea-facts.d.ts +11 -0
  731. package/dist/server/services/gitea-facts.js +4 -0
  732. package/dist/server/services/gitea-service.d.ts +62 -0
  733. package/dist/server/services/gitea-service.js +1844 -0
  734. package/dist/server/services/github-facts.d.ts +27 -0
  735. package/dist/server/services/github-facts.js +4 -0
  736. package/dist/server/services/github-service.d.ts +76 -0
  737. package/dist/server/services/github-service.js +3297 -0
  738. package/dist/server/services/gitlab-facts.d.ts +26 -0
  739. package/dist/server/services/gitlab-facts.js +4 -0
  740. package/dist/server/services/gitlab-service.d.ts +43 -0
  741. package/dist/server/services/gitlab-service.js +1092 -0
  742. package/dist/server/services/quota-fetcher/manifest.d.ts +5 -0
  743. package/dist/server/services/quota-fetcher/manifest.js +118 -0
  744. package/dist/server/services/quota-fetcher/provider.d.ts +18 -0
  745. package/dist/server/services/quota-fetcher/provider.js +2 -0
  746. package/dist/server/services/quota-fetcher/providers/claude.d.ts +40 -0
  747. package/dist/server/services/quota-fetcher/providers/claude.js +389 -0
  748. package/dist/server/services/quota-fetcher/providers/codex.d.ts +23 -0
  749. package/dist/server/services/quota-fetcher/providers/codex.js +167 -0
  750. package/dist/server/services/quota-fetcher/providers/copilot.d.ts +21 -0
  751. package/dist/server/services/quota-fetcher/providers/copilot.js +77 -0
  752. package/dist/server/services/quota-fetcher/providers/cursor.d.ts +19 -0
  753. package/dist/server/services/quota-fetcher/providers/cursor.js +185 -0
  754. package/dist/server/services/quota-fetcher/providers/grok.d.ts +23 -0
  755. package/dist/server/services/quota-fetcher/providers/grok.js +137 -0
  756. package/dist/server/services/quota-fetcher/providers/kimi.d.ts +23 -0
  757. package/dist/server/services/quota-fetcher/providers/kimi.js +260 -0
  758. package/dist/server/services/quota-fetcher/providers/minimax.d.ts +29 -0
  759. package/dist/server/services/quota-fetcher/providers/minimax.js +227 -0
  760. package/dist/server/services/quota-fetcher/providers/zai.d.ts +17 -0
  761. package/dist/server/services/quota-fetcher/providers/zai.js +58 -0
  762. package/dist/server/services/quota-fetcher/service.d.ts +34 -0
  763. package/dist/server/services/quota-fetcher/service.js +74 -0
  764. package/dist/server/services/quota-fetcher/usage.d.ts +39 -0
  765. package/dist/server/services/quota-fetcher/usage.js +78 -0
  766. package/dist/server/skills/paseo/SKILL.md +129 -0
  767. package/dist/server/skills/paseo-advisor/SKILL.md +63 -0
  768. package/dist/server/skills/paseo-committee/SKILL.md +46 -0
  769. package/dist/server/skills/paseo-handoff/SKILL.md +65 -0
  770. package/dist/server/skills/paseo-help/SKILL.md +92 -0
  771. package/dist/server/skills/paseo-plugin/SKILL.md +639 -0
  772. package/dist/server/terminal/activity/terminal-activity-tracker.d.ts +21 -0
  773. package/dist/server/terminal/activity/terminal-activity-tracker.js +65 -0
  774. package/dist/server/terminal/agent-hooks/agent-hook-installer.d.ts +62 -0
  775. package/dist/server/terminal/agent-hooks/agent-hook-installer.js +117 -0
  776. package/dist/server/terminal/agent-hooks/claude/claude-settings.d.ts +7 -0
  777. package/dist/server/terminal/agent-hooks/claude/claude-settings.js +88 -0
  778. package/dist/server/terminal/agent-hooks/claude/claude.d.ts +4 -0
  779. package/dist/server/terminal/agent-hooks/claude/claude.js +47 -0
  780. package/dist/server/terminal/agent-hooks/codex/codex-settings.d.ts +7 -0
  781. package/dist/server/terminal/agent-hooks/codex/codex-settings.js +99 -0
  782. package/dist/server/terminal/agent-hooks/codex/codex.d.ts +4 -0
  783. package/dist/server/terminal/agent-hooks/codex/codex.js +30 -0
  784. package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.d.ts +4 -0
  785. package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.js +81 -0
  786. package/dist/server/terminal/agent-hooks/opencode/opencode.d.ts +3 -0
  787. package/dist/server/terminal/agent-hooks/opencode/opencode.js +23 -0
  788. package/dist/server/terminal/agent-hooks/provider-registry.d.ts +24 -0
  789. package/dist/server/terminal/agent-hooks/provider-registry.js +36 -0
  790. package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.d.ts +10 -0
  791. package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.js +26 -0
  792. package/dist/server/terminal/shell-integration/zsh/.zshenv +17 -0
  793. package/dist/server/terminal/shell-integration/zsh/paseo-integration.zsh +32 -0
  794. package/dist/server/terminal/terminal-capture.d.ts +12 -0
  795. package/dist/server/terminal/terminal-capture.js +43 -0
  796. package/dist/server/terminal/terminal-manager-factory.d.ts +6 -0
  797. package/dist/server/terminal/terminal-manager-factory.js +5 -0
  798. package/dist/server/terminal/terminal-manager.d.ts +80 -0
  799. package/dist/server/terminal/terminal-manager.js +321 -0
  800. package/dist/server/terminal/terminal-output-coalescer.d.ts +34 -0
  801. package/dist/server/terminal/terminal-output-coalescer.js +73 -0
  802. package/dist/server/terminal/terminal-restore.d.ts +18 -0
  803. package/dist/server/terminal/terminal-restore.js +52 -0
  804. package/dist/server/terminal/terminal-session-controller.d.ts +90 -0
  805. package/dist/server/terminal/terminal-session-controller.js +849 -0
  806. package/dist/server/terminal/terminal-size-ownership.d.ts +9 -0
  807. package/dist/server/terminal/terminal-size-ownership.js +23 -0
  808. package/dist/server/terminal/terminal-ts-loader.mjs +20 -0
  809. package/dist/server/terminal/terminal-worker-process.d.ts +2 -0
  810. package/dist/server/terminal/terminal-worker-process.js +308 -0
  811. package/dist/server/terminal/terminal-worker-protocol.d.ts +121 -0
  812. package/dist/server/terminal/terminal-worker-protocol.js +2 -0
  813. package/dist/server/terminal/terminal.d.ts +151 -0
  814. package/dist/server/terminal/terminal.js +1234 -0
  815. package/dist/server/terminal/worker-terminal-manager.d.ts +20 -0
  816. package/dist/server/terminal/worker-terminal-manager.js +688 -0
  817. package/dist/server/utils/build-metadata-prompt.d.ts +19 -0
  818. package/dist/server/utils/build-metadata-prompt.js +29 -0
  819. package/dist/server/utils/checkout-git.d.ts +317 -0
  820. package/dist/server/utils/checkout-git.js +2886 -0
  821. package/dist/server/utils/directory-suggestions.d.ts +29 -0
  822. package/dist/server/utils/directory-suggestions.js +596 -0
  823. package/dist/server/utils/git-command-runtime-metrics.d.ts +67 -0
  824. package/dist/server/utils/git-command-runtime-metrics.js +126 -0
  825. package/dist/server/utils/git-command-trace.d.ts +29 -0
  826. package/dist/server/utils/git-command-trace.js +74 -0
  827. package/dist/server/utils/git-process-scheduler.d.ts +34 -0
  828. package/dist/server/utils/git-process-scheduler.js +112 -0
  829. package/dist/server/utils/git-rev-parse-path.d.ts +3 -0
  830. package/dist/server/utils/git-rev-parse-path.js +21 -0
  831. package/dist/server/utils/paseo-config-file.d.ts +30 -0
  832. package/dist/server/utils/paseo-config-file.js +90 -0
  833. package/dist/server/utils/path.d.ts +27 -0
  834. package/dist/server/utils/path.js +156 -0
  835. package/dist/server/utils/project-custom-icon.d.ts +40 -0
  836. package/dist/server/utils/project-custom-icon.js +144 -0
  837. package/dist/server/utils/project-icon.d.ts +54 -0
  838. package/dist/server/utils/project-icon.js +445 -0
  839. package/dist/server/utils/promise-timeout.d.ts +9 -0
  840. package/dist/server/utils/promise-timeout.js +25 -0
  841. package/dist/server/utils/run-git-command.d.ts +59 -0
  842. package/dist/server/utils/run-git-command.js +393 -0
  843. package/dist/server/utils/spawn.d.ts +26 -0
  844. package/dist/server/utils/spawn.js +60 -0
  845. package/dist/server/utils/ssh-hostname.d.ts +8 -0
  846. package/dist/server/utils/ssh-hostname.js +60 -0
  847. package/dist/server/utils/string-command-shell.d.ts +13 -0
  848. package/dist/server/utils/string-command-shell.js +37 -0
  849. package/dist/server/utils/tree-kill.d.ts +19 -0
  850. package/dist/server/utils/tree-kill.js +77 -0
  851. package/dist/server/utils/windows-command.d.ts +15 -0
  852. package/dist/server/utils/windows-command.js +41 -0
  853. package/dist/server/utils/worktree-metadata.d.ts +77 -0
  854. package/dist/server/utils/worktree-metadata.js +280 -0
  855. package/dist/server/utils/worktree.d.ts +232 -0
  856. package/dist/server/utils/worktree.js +1193 -0
  857. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css +1 -0
  858. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.br +0 -0
  859. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.gz +0 -0
  860. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-29f33408b1a3c5b435c5202d62a36719.js +1 -0
  861. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-29f33408b1a3c5b435c5202d62a36719.js.br +0 -0
  862. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-29f33408b1a3c5b435c5202d62a36719.js.gz +0 -0
  863. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-41547ee520dfff946caa727824742a5c.js +1 -0
  864. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-41547ee520dfff946caa727824742a5c.js.br +0 -0
  865. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-41547ee520dfff946caa727824742a5c.js.gz +0 -0
  866. package/dist/server/web-ui/_expo/static/js/web/index-03b99be4265ac4a2bc5a6d602fd59cc4.js +16819 -0
  867. package/dist/server/web-ui/_expo/static/js/web/index-03b99be4265ac4a2bc5a6d602fd59cc4.js.br +0 -0
  868. package/dist/server/web-ui/_expo/static/js/web/index-03b99be4265ac4a2bc5a6d602fd59cc4.js.gz +0 -0
  869. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-5444610146b0794f1e7d9edad4522d41.js +1 -0
  870. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-5444610146b0794f1e7d9edad4522d41.js.br +0 -0
  871. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-5444610146b0794f1e7d9edad4522d41.js.gz +0 -0
  872. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-88b083190031a44788be59103814f511.js +3 -0
  873. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-88b083190031a44788be59103814f511.js.br +0 -0
  874. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-88b083190031a44788be59103814f511.js.gz +0 -0
  875. package/dist/server/web-ui/apple-touch-icon.png +0 -0
  876. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon-mask.0a328cd9c1afd0afe8e3b1ec5165b1b4.png +0 -0
  877. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon.35ba0eaec5a4f5ed12ca16fabeae451d.png +0 -0
  878. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55.png +0 -0
  879. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@2x.png +0 -0
  880. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@3x.png +0 -0
  881. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@4x.png +0 -0
  882. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7.png +0 -0
  883. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@2x.png +0 -0
  884. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@3x.png +0 -0
  885. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@4x.png +0 -0
  886. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/search-icon.286d67d3f74808a60a78d3ebf1a5fb57.png +0 -0
  887. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/arrow_down.017bc6ba3fc25503e5eb5e53826d48a8.png +0 -0
  888. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/error.d1ea1496f9057eb392d5bbf3732a61b7.png +0 -0
  889. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/file.19eeb73b9593a38f8e9f418337fc7d10.png +0 -0
  890. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/forward.d8b800c443b8972542883e0b9de2bdc6.png +0 -0
  891. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/pkg.ab19f4cbc543357183a20571f68380a3.png +0 -0
  892. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/sitemap.412dd9275b6b48ad28f5e3d81bb1f626.png +0 -0
  893. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/unmatched.20e71bdf79e3a97bf55fd9e164041578.png +0 -0
  894. package/dist/server/web-ui/assets/assets/images/favicon-dark-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
  895. package/dist/server/web-ui/assets/assets/images/favicon-dark-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
  896. package/dist/server/web-ui/assets/assets/images/favicon-dark.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
  897. package/dist/server/web-ui/assets/assets/images/favicon-light-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
  898. package/dist/server/web-ui/assets/assets/images/favicon-light-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
  899. package/dist/server/web-ui/assets/assets/images/favicon-light.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
  900. package/dist/server/web-ui/assets/assets/images/notification-icon.3bf81d33ddbf380606bdd248ba83e158.png +0 -0
  901. package/dist/server/web-ui/favicon.ico +0 -0
  902. package/dist/server/web-ui/index.html +90 -0
  903. package/dist/server/web-ui/index.html.br +0 -0
  904. package/dist/server/web-ui/index.html.gz +0 -0
  905. package/dist/server/web-ui/manifest.json +27 -0
  906. package/dist/server/web-ui/manifest.json.br +0 -0
  907. package/dist/server/web-ui/manifest.json.gz +0 -0
  908. package/dist/server/web-ui/metadata.json +1 -0
  909. package/dist/server/web-ui/metadata.json.br +1 -0
  910. package/dist/server/web-ui/metadata.json.gz +0 -0
  911. package/dist/server/web-ui/pwa-icon-192.png +0 -0
  912. package/dist/server/web-ui/pwa-icon-512.png +0 -0
  913. package/dist/server/web-ui/robots.txt +2 -0
  914. package/dist/src/executable-resolution/executable-resolution.js +121 -0
  915. package/dist/src/executable-resolution/windows.js +65 -0
  916. package/dist/src/server/agent/provider-launch-config.js +167 -0
  917. package/dist/src/server/paseo-env.js +54 -0
  918. package/dist/src/server/paseo-home.js +19 -0
  919. package/dist/src/server/persisted-config.js +411 -0
  920. package/dist/src/server/pid-lock.js +285 -0
  921. package/dist/src/server/private-files.js +37 -0
  922. package/dist/src/server/speech/providers/local/sherpa/sherpa-runtime-env.js +84 -0
  923. package/dist/src/terminal/shell-integration/zsh/.zshenv +17 -0
  924. package/dist/src/terminal/shell-integration/zsh/paseo-integration.zsh +32 -0
  925. package/dist/src/utils/spawn.js +60 -0
  926. package/dist/src/utils/tree-kill.js +77 -0
  927. package/dist/src/utils/windows-command.js +41 -0
  928. package/package.json +125 -0
@@ -0,0 +1,3412 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import fs from "node:fs/promises";
3
+ import { homedir } from "node:os";
4
+ import path from "node:path";
5
+ import { Readable, Writable } from "node:stream";
6
+ import { terminateWithTreeKill } from "../../../utils/tree-kill.js";
7
+ import { ClientSideConnection, PROTOCOL_VERSION, } from "@agentclientprotocol/sdk";
8
+ import { getAgentStreamEventTurnId, } from "../agent-sdk-types.js";
9
+ import { raceProviderRefreshAbort, runProviderRefreshActivity, } from "../provider-refresh-deadline.js";
10
+ import { isDefaultAgentCreateConfigUnattended, resolveDefaultAgentCreateConfig, } from "../create-agent-mode.js";
11
+ import { importSessionFromPersistence } from "../provider-session-import.js";
12
+ import { checkProviderLaunchAvailable, createProviderEnvSpec, resolveProviderLaunch, } from "../provider-launch-config.js";
13
+ import { renderPromptAttachmentAsText } from "../prompt-attachments.js";
14
+ import { appendOrReplaceGrowingAssistantMessage, runProviderTurn } from "./provider-runner.js";
15
+ import { buildStringCommandShellInvocation, createStringCommandShellEnvOverlay, } from "../../../utils/string-command-shell.js";
16
+ import { spawnProcess } from "../../../utils/spawn.js";
17
+ import { toDiagnosticErrorMessage, truncateForDiagnostic, } from "./diagnostic-utils.js";
18
+ import { withTimeout } from "../../../utils/promise-timeout.js";
19
+ const ACP_AUTO_ACCEPT_FEATURE_ID = "auto_accept";
20
+ function assertChildWithPipes(child) {
21
+ if (!child.stdin || !child.stdout || !child.stderr) {
22
+ throw new Error("Child process did not expose stdio pipes");
23
+ }
24
+ }
25
+ function isRecord(value) {
26
+ return value != null && typeof value === "object" && !Array.isArray(value);
27
+ }
28
+ function isACPError(value) {
29
+ return isRecord(value) && typeof value.message === "string" && typeof value.code === "number";
30
+ }
31
+ function extractACPErrorDataMessage(data) {
32
+ if (!isRecord(data)) {
33
+ return null;
34
+ }
35
+ for (const key of ["details", "errorMessage", "message", "detail", "title"]) {
36
+ const value = data[key];
37
+ if (typeof value === "string" && value.trim()) {
38
+ return value.trim();
39
+ }
40
+ }
41
+ return extractACPErrorDataMessage(data.error);
42
+ }
43
+ export function summarizeACPRequestError(error) {
44
+ // Promise rejections are untyped, but the ACP SDK rejects JSON-RPC failures as response.error.
45
+ if (isACPError(error)) {
46
+ const code = String(error.code);
47
+ const detail = extractACPErrorDataMessage(error.data);
48
+ const message = detail && detail !== error.message ? `${error.message}: ${detail}` : error.message;
49
+ const data = error.data === undefined ? "" : ` | data=${JSON.stringify(error.data)}`;
50
+ return {
51
+ message,
52
+ code,
53
+ diagnostic: `${message} | code=${code}${data}`,
54
+ };
55
+ }
56
+ if (error instanceof Error) {
57
+ return { message: error.message };
58
+ }
59
+ return { message: String(error) };
60
+ }
61
+ function toACPRequestError(error) {
62
+ if (!isACPError(error)) {
63
+ return error instanceof Error ? error : new Error(String(error));
64
+ }
65
+ const summary = summarizeACPRequestError(error);
66
+ const next = new Error(summary.message);
67
+ next.name = "ACPRequestError";
68
+ return next;
69
+ }
70
+ function resolveTerminalCommand(command, args) {
71
+ if (args && args.length > 0) {
72
+ return { command, args };
73
+ }
74
+ if (!/\s/.test(command.trim())) {
75
+ return { command, args: [] };
76
+ }
77
+ const shell = buildStringCommandShellInvocation({ command, windowsShell: "cmd" });
78
+ return { command: shell.shell, args: shell.args, shell: false };
79
+ }
80
+ function formatDurationMs(startedAt) {
81
+ return `${Math.max(0, Date.now() - startedAt)}ms`;
82
+ }
83
+ function pushACPStderrRow(rows, stderrChunks) {
84
+ const stderr = stderrChunks.join("").trim();
85
+ if (!stderr) {
86
+ return;
87
+ }
88
+ rows.push({
89
+ label: "ACP stderr",
90
+ value: truncateForDiagnostic(stderr),
91
+ });
92
+ }
93
+ export const DEFAULT_ACP_CAPABILITIES = {
94
+ supportsStreaming: true,
95
+ supportsSessionPersistence: true,
96
+ supportsSessionListing: true,
97
+ supportsDynamicModes: true,
98
+ supportsMcpServers: true,
99
+ supportsReasoningStream: true,
100
+ supportsToolInvocations: true,
101
+ supportsRewindConversation: false,
102
+ supportsRewindFiles: false,
103
+ supportsRewindBoth: false,
104
+ };
105
+ function acpSessionListRequest(cursor, cwd) {
106
+ return {
107
+ ...(cursor ? { cursor } : {}),
108
+ ...(cwd ? { cwd } : {}),
109
+ };
110
+ }
111
+ const BASE_ACP_CLIENT_CAPABILITIES = {
112
+ fs: {
113
+ readTextFile: false,
114
+ writeTextFile: false,
115
+ },
116
+ terminal: true,
117
+ };
118
+ export function buildACPClientCapabilities(meta, override) {
119
+ const capabilities = {
120
+ ...BASE_ACP_CLIENT_CAPABILITIES,
121
+ ...override,
122
+ fs: {
123
+ ...BASE_ACP_CLIENT_CAPABILITIES.fs,
124
+ ...override?.fs,
125
+ },
126
+ };
127
+ return meta && Object.keys(meta).length > 0 ? { ...capabilities, _meta: meta } : capabilities;
128
+ }
129
+ // Suppress interactive auth side-effects (e.g. Gemini CLI opening a Google
130
+ // sign-in URL in the browser) when probing an ACP agent for models/modes.
131
+ // NO_BROWSER is honored by Gemini CLI; other ACP agents ignore it.
132
+ const PROBE_ENV = { NO_BROWSER: "true" };
133
+ const ACP_DIAGNOSTIC_PHASE_TIMEOUT_MS = 20000;
134
+ const ACP_PROBE_CLOSE_TIMEOUT_MS = 2000;
135
+ const ACP_IMPORT_HISTORY_LOAD_TIMEOUT_MS = 30000;
136
+ const ACP_IMPORT_HISTORY_BUDGET_MS = 60000;
137
+ function summarizeMalformedACPStdoutError(error) {
138
+ return {
139
+ type: error instanceof Error ? error.name : typeof error,
140
+ message: "ACP stdout line was not valid JSON",
141
+ };
142
+ }
143
+ function normalizeACPIncomingMessage(message) {
144
+ if ("id" in message &&
145
+ !("method" in message) &&
146
+ typeof message.id === "string" &&
147
+ /^\d+$/.test(message.id)) {
148
+ const numericId = Number(message.id);
149
+ if (Number.isSafeInteger(numericId)) {
150
+ return {
151
+ ...message,
152
+ // COMPAT(deepseek-tui-acp-id): added v0.1.78, remove after 2026-11-19
153
+ // once the ACP SDK accepts stringified numeric response IDs.
154
+ id: numericId,
155
+ };
156
+ }
157
+ }
158
+ return message;
159
+ }
160
+ export function createLoggedNdJsonStream(output, input, options) {
161
+ const textEncoder = new TextEncoder();
162
+ const textDecoder = new TextDecoder();
163
+ const readable = new ReadableStream({
164
+ async start(controller) {
165
+ let content = "";
166
+ const reader = input.getReader();
167
+ try {
168
+ while (true) {
169
+ const { value, done } = await reader.read();
170
+ if (done) {
171
+ break;
172
+ }
173
+ if (!value) {
174
+ continue;
175
+ }
176
+ content += textDecoder.decode(value, { stream: true });
177
+ const lines = content.split("\n");
178
+ content = lines.pop() || "";
179
+ for (const line of lines) {
180
+ const trimmedLine = line.trim();
181
+ if (!trimmedLine) {
182
+ continue;
183
+ }
184
+ try {
185
+ const message = JSON.parse(trimmedLine);
186
+ controller.enqueue(normalizeACPIncomingMessage(message));
187
+ }
188
+ catch (error) {
189
+ options.logger.warn({
190
+ err: summarizeMalformedACPStdoutError(error),
191
+ provider: options.provider,
192
+ }, "ACP agent emitted non-JSON stdout; ignoring line");
193
+ }
194
+ }
195
+ }
196
+ }
197
+ finally {
198
+ reader.releaseLock();
199
+ controller.close();
200
+ }
201
+ },
202
+ });
203
+ const writable = new WritableStream({
204
+ async write(message) {
205
+ const writer = output.getWriter();
206
+ try {
207
+ await writer.write(textEncoder.encode(`${JSON.stringify(message)}\n`));
208
+ }
209
+ finally {
210
+ writer.releaseLock();
211
+ }
212
+ },
213
+ });
214
+ return { readable, writable };
215
+ }
216
+ class ACPImportHistoryCollector {
217
+ constructor() {
218
+ this.prompts = new Map();
219
+ }
220
+ begin(sessionId) {
221
+ this.prompts.set(sessionId, { completed: [], current: null, hasConversation: false });
222
+ }
223
+ accept(params) {
224
+ const state = this.prompts.get(params.sessionId);
225
+ if (!state)
226
+ return;
227
+ const update = params.update;
228
+ if (isACPConversationUpdate(update))
229
+ state.hasConversation = true;
230
+ if (update.sessionUpdate !== "user_message_chunk") {
231
+ this.flushCurrent(state);
232
+ return;
233
+ }
234
+ const text = contentBlockToText(update.content);
235
+ if (!text)
236
+ return;
237
+ const messageId = update.messageId ?? null;
238
+ if (state.current?.messageId && messageId !== state.current.messageId) {
239
+ this.flushCurrent(state);
240
+ }
241
+ state.current ?? (state.current = { messageId, text: "" });
242
+ state.current.text += text;
243
+ }
244
+ finish(sessionId) {
245
+ const state = this.prompts.get(sessionId);
246
+ if (!state) {
247
+ return { firstPromptPreview: null, lastPromptPreview: null, hasConversation: false };
248
+ }
249
+ this.flushCurrent(state);
250
+ this.prompts.delete(sessionId);
251
+ return {
252
+ firstPromptPreview: normalizeACPImportPromptPreview(state.completed[0] ?? null),
253
+ lastPromptPreview: normalizeACPImportPromptPreview(state.completed.at(-1) ?? null),
254
+ hasConversation: state.hasConversation,
255
+ };
256
+ }
257
+ discard(sessionId) {
258
+ this.prompts.delete(sessionId);
259
+ }
260
+ flushCurrent(state) {
261
+ if (state.current?.text.trim())
262
+ state.completed.push(state.current.text);
263
+ state.current = null;
264
+ }
265
+ }
266
+ export function mapACPUsage(usage) {
267
+ if (!usage) {
268
+ return undefined;
269
+ }
270
+ return {
271
+ inputTokens: usage.inputTokens ?? undefined,
272
+ outputTokens: usage.outputTokens ?? undefined,
273
+ cachedInputTokens: usage.cachedReadTokens ?? undefined,
274
+ };
275
+ }
276
+ export function resolveACPModeSelection({ modeId, availableModes, configOptions, }) {
277
+ const configOption = findSelectConfigOption({ configOptions, category: "mode" });
278
+ return {
279
+ availableMode: availableModes.find((mode) => mode.id === modeId) ?? null,
280
+ configOption,
281
+ configChoice: findSelectConfigChoice({ option: configOption, value: modeId }),
282
+ hasAvailableModes: availableModes.length > 0,
283
+ };
284
+ }
285
+ export function resolveACPModelSelection({ modelId, availableModels, configOptions, }) {
286
+ const configOption = findSelectConfigOption({ configOptions, category: "model" });
287
+ return {
288
+ availableModel: availableModels?.find((model) => model.modelId === modelId) ?? null,
289
+ configOption,
290
+ configChoice: findSelectConfigChoice({ option: configOption, value: modelId }),
291
+ hasAvailableModels: Boolean(availableModels?.length),
292
+ };
293
+ }
294
+ export function deriveModesFromACP(fallbackModes, modeState, configOptions) {
295
+ if (modeState?.availableModes?.length) {
296
+ return {
297
+ modes: modeState.availableModes.map((mode) => ({
298
+ id: mode.id,
299
+ label: mode.name,
300
+ description: mode.description ?? undefined,
301
+ })),
302
+ currentModeId: modeState.currentModeId ?? null,
303
+ };
304
+ }
305
+ const modeOption = findSelectConfigOption({ configOptions, category: "mode" });
306
+ if (modeOption) {
307
+ const flatOptions = flattenSelectOptions(modeOption.options);
308
+ return {
309
+ modes: flatOptions.map((option) => ({
310
+ id: option.value,
311
+ label: option.name,
312
+ description: option.description ?? undefined,
313
+ })),
314
+ currentModeId: modeOption.currentValue,
315
+ };
316
+ }
317
+ return {
318
+ modes: fallbackModes,
319
+ currentModeId: null,
320
+ };
321
+ }
322
+ export function deriveModelDefinitionsFromACP(provider, models, configOptions) {
323
+ const thinkingOptions = deriveSelectorOptions(configOptions, "thought_level");
324
+ const defaultThinkingOptionId = thinkingOptions.find((option) => option.isDefault)?.id ?? null;
325
+ if (models?.availableModels?.length) {
326
+ return models.availableModels.map((model) => ({
327
+ provider,
328
+ id: model.modelId,
329
+ label: model.name,
330
+ description: model.description ?? undefined,
331
+ isDefault: model.modelId === models.currentModelId,
332
+ thinkingOptions: thinkingOptions.length > 0 ? thinkingOptions : undefined,
333
+ defaultThinkingOptionId: defaultThinkingOptionId ?? undefined,
334
+ }));
335
+ }
336
+ const modelOptions = deriveSelectorOptions(configOptions, "model");
337
+ return modelOptions.map((option) => ({
338
+ provider,
339
+ id: option.id,
340
+ label: option.label,
341
+ description: option.description,
342
+ isDefault: option.isDefault,
343
+ thinkingOptions: thinkingOptions.length > 0 ? thinkingOptions : undefined,
344
+ defaultThinkingOptionId: defaultThinkingOptionId ?? undefined,
345
+ metadata: option.metadata,
346
+ }));
347
+ }
348
+ export function deriveFeaturesFromACP(configOptions, featureOptions) {
349
+ return featureOptions.flatMap((featureOption) => {
350
+ const option = findSelectConfigFeatureOption(configOptions, featureOption);
351
+ if (!option) {
352
+ return [];
353
+ }
354
+ return [
355
+ {
356
+ type: "select",
357
+ id: featureOption.id,
358
+ label: featureOption.label,
359
+ description: featureOption.description,
360
+ tooltip: featureOption.tooltip,
361
+ icon: featureOption.icon,
362
+ value: option.currentValue ?? null,
363
+ options: deriveConfigFeatureSelectOptions(option, featureOption),
364
+ },
365
+ ];
366
+ });
367
+ }
368
+ function isACPAutoAcceptEnabled(config) {
369
+ return config.featureValues?.[ACP_AUTO_ACCEPT_FEATURE_ID] === true;
370
+ }
371
+ function buildACPAutoAcceptFeature(config) {
372
+ return {
373
+ type: "toggle",
374
+ id: ACP_AUTO_ACCEPT_FEATURE_ID,
375
+ label: "Auto Accept",
376
+ description: "Automatically approves ACP permission prompts.",
377
+ tooltip: "Auto accept permission prompts",
378
+ icon: "shield-check",
379
+ value: isACPAutoAcceptEnabled(config),
380
+ };
381
+ }
382
+ function resolveACPCreateConfig(input) {
383
+ const isUnattendedCreate = input.unattended || input.parent?.isUnattended === true;
384
+ const featureValues = isUnattendedCreate && input.featureValues?.[ACP_AUTO_ACCEPT_FEATURE_ID] === undefined
385
+ ? { ...input.featureValues, [ACP_AUTO_ACCEPT_FEATURE_ID]: true }
386
+ : input.featureValues;
387
+ if (input.requestedMode === undefined &&
388
+ isUnattendedCreate &&
389
+ input.parent !== null &&
390
+ input.parent.provider !== input.provider) {
391
+ return { modeId: undefined, featureValues };
392
+ }
393
+ return resolveDefaultAgentCreateConfig({ ...input, featureValues });
394
+ }
395
+ function isACPCreateConfigUnattended(input) {
396
+ return (isDefaultAgentCreateConfigUnattended(input) ||
397
+ input.config.featureValues?.[ACP_AUTO_ACCEPT_FEATURE_ID] === true ||
398
+ input.features?.some((feature) => feature.id === ACP_AUTO_ACCEPT_FEATURE_ID &&
399
+ feature.type === "toggle" &&
400
+ feature.value === true) === true);
401
+ }
402
+ export class ACPAgentClient {
403
+ constructor(options) {
404
+ this.resolveCreateConfig = resolveACPCreateConfig;
405
+ this.isCreateConfigUnattended = isACPCreateConfigUnattended;
406
+ this.importPromptCache = new Map();
407
+ this.provider = options.provider;
408
+ this.terminateProcess = options.terminateProcess ?? terminateWithTreeKill;
409
+ this.capabilities = options.capabilities ?? DEFAULT_ACP_CAPABILITIES;
410
+ this.logger = options.logger.child({
411
+ module: "agent",
412
+ provider: options.provider,
413
+ });
414
+ this.runtimeSettings = options.runtimeSettings;
415
+ this.defaultCommand = options.defaultCommand;
416
+ this.defaultModes = options.defaultModes ?? [];
417
+ this.catalogModelResolver = options.catalogModelResolver;
418
+ this.modelTransformer = options.modelTransformer;
419
+ this.sessionResponseTransformer = options.sessionResponseTransformer;
420
+ this.configOptionsTransformer = options.configOptionsTransformer;
421
+ this.configFeatureOptions = options.configFeatureOptions ?? [];
422
+ this.clientCapabilities = options.clientCapabilities;
423
+ this.clientCapabilityMeta = options.clientCapabilityMeta;
424
+ this.modeIdTransformer = options.modeIdTransformer;
425
+ this.toolSnapshotTransformer = options.toolSnapshotTransformer;
426
+ this.providerModeWriter = options.providerModeWriter;
427
+ this.beforeModeWriter = options.beforeModeWriter;
428
+ this.thinkingOptionWriter = options.thinkingOptionWriter;
429
+ this.waitForInitialCommands = options.waitForInitialCommands ?? false;
430
+ this.initialCommandsWaitTimeoutMs = options.initialCommandsWaitTimeoutMs ?? 1500;
431
+ this.extensionCommandsParser = options.extensionCommandsParser;
432
+ this.now = options.now ?? Date.now;
433
+ }
434
+ async createSession(config, launchContext) {
435
+ this.assertProvider(config);
436
+ const session = this.createAgentSession({ ...config, provider: this.provider }, {
437
+ provider: this.provider,
438
+ logger: this.logger,
439
+ runtimeSettings: this.runtimeSettings,
440
+ defaultCommand: this.defaultCommand,
441
+ defaultModes: this.defaultModes,
442
+ modelTransformer: this.modelTransformer,
443
+ sessionResponseTransformer: this.sessionResponseTransformer,
444
+ configOptionsTransformer: this.configOptionsTransformer,
445
+ configFeatureOptions: this.configFeatureOptions,
446
+ clientCapabilities: this.clientCapabilities,
447
+ clientCapabilityMeta: this.clientCapabilityMeta,
448
+ modeIdTransformer: this.modeIdTransformer,
449
+ toolSnapshotTransformer: this.toolSnapshotTransformer,
450
+ providerModeWriter: this.providerModeWriter,
451
+ beforeModeWriter: this.beforeModeWriter,
452
+ thinkingOptionWriter: this.thinkingOptionWriter,
453
+ capabilities: this.capabilities,
454
+ agentId: launchContext?.agentId,
455
+ launchEnv: launchContext?.env,
456
+ extensionCommandsParser: this.extensionCommandsParser,
457
+ waitForInitialCommands: this.waitForInitialCommands,
458
+ initialCommandsWaitTimeoutMs: this.initialCommandsWaitTimeoutMs,
459
+ });
460
+ await session.initializeNewSession();
461
+ return session;
462
+ }
463
+ /**
464
+ * Builds the session instance behind `createSession`/`resumeSession`. A fork
465
+ * provider overrides this to substitute its own session subclass while
466
+ * keeping the shared launch, transform, and capability plumbing.
467
+ */
468
+ createAgentSession(config, options) {
469
+ return new ACPAgentSession(config, options);
470
+ }
471
+ async resumeSession(handle, overrides, launchContext) {
472
+ if (handle.provider !== this.provider) {
473
+ throw new Error(`Cannot resume ${handle.provider} handle with ${this.provider} provider`);
474
+ }
475
+ const storedConfig = coerceSessionConfigMetadata(handle.metadata);
476
+ const cwd = overrides?.cwd ?? storedConfig.cwd;
477
+ if (!cwd) {
478
+ throw new Error(`${this.provider} resume requires the original working directory`);
479
+ }
480
+ const mergedConfig = {
481
+ ...storedConfig,
482
+ ...overrides,
483
+ provider: this.provider,
484
+ cwd,
485
+ };
486
+ const session = this.createAgentSession(mergedConfig, {
487
+ provider: this.provider,
488
+ logger: this.logger,
489
+ runtimeSettings: this.runtimeSettings,
490
+ defaultCommand: this.defaultCommand,
491
+ defaultModes: this.defaultModes,
492
+ modelTransformer: this.modelTransformer,
493
+ sessionResponseTransformer: this.sessionResponseTransformer,
494
+ configOptionsTransformer: this.configOptionsTransformer,
495
+ configFeatureOptions: this.configFeatureOptions,
496
+ clientCapabilities: this.clientCapabilities,
497
+ clientCapabilityMeta: this.clientCapabilityMeta,
498
+ modeIdTransformer: this.modeIdTransformer,
499
+ toolSnapshotTransformer: this.toolSnapshotTransformer,
500
+ providerModeWriter: this.providerModeWriter,
501
+ beforeModeWriter: this.beforeModeWriter,
502
+ thinkingOptionWriter: this.thinkingOptionWriter,
503
+ capabilities: this.capabilities,
504
+ handle,
505
+ agentId: launchContext?.agentId,
506
+ launchEnv: launchContext?.env,
507
+ extensionCommandsParser: this.extensionCommandsParser,
508
+ waitForInitialCommands: this.waitForInitialCommands,
509
+ initialCommandsWaitTimeoutMs: this.initialCommandsWaitTimeoutMs,
510
+ });
511
+ await session.initializeResumedSession();
512
+ return session;
513
+ }
514
+ async fetchCatalog(options, context) {
515
+ const cwd = options.scope === "global" ? homedir() : options.cwd;
516
+ let probe = null;
517
+ let probeSessionId = null;
518
+ let probeSessionPromise = null;
519
+ let closePromise = null;
520
+ const closeProbe = () => {
521
+ if (!probe)
522
+ return Promise.resolve();
523
+ closePromise ?? (closePromise = (async () => {
524
+ if (!probeSessionId && probeSessionPromise) {
525
+ try {
526
+ probeSessionId = (await withTimeout(probeSessionPromise, ACP_PROBE_CLOSE_TIMEOUT_MS, `ACP probe session/new cleanup timed out after ${ACP_PROBE_CLOSE_TIMEOUT_MS}ms`)).sessionId;
527
+ }
528
+ catch (error) {
529
+ this.logger.debug({ err: error }, "ACP probe session/new did not finish during cleanup");
530
+ }
531
+ }
532
+ await this.closeProbe(probe, probeSessionId);
533
+ })());
534
+ return closePromise;
535
+ };
536
+ const handleAbort = () => void closeProbe().catch(() => undefined);
537
+ context?.signal.addEventListener("abort", handleAbort, { once: true });
538
+ try {
539
+ const initializedProbe = await runProviderRefreshActivity(context, "initialize", () => raceProviderRefreshAbort(context?.signal, this.spawnProcess(PROBE_ENV, {
540
+ onSpawned: (spawned) => {
541
+ probe = spawned;
542
+ if (context?.signal.aborted)
543
+ void closeProbe().catch(() => undefined);
544
+ },
545
+ })));
546
+ probe = initializedProbe;
547
+ probeSessionPromise = this.runACPRequest(() => initializedProbe.connection.newSession({
548
+ cwd,
549
+ mcpServers: [],
550
+ }));
551
+ const response = await runProviderRefreshActivity(context, "session/new", () => raceProviderRefreshAbort(context?.signal, probeSessionPromise));
552
+ probeSessionId = response.sessionId;
553
+ const transformed = this.transformSessionResponse(response);
554
+ const derivedModels = deriveModelDefinitionsFromACP(this.provider, transformed.models, transformed.configOptions);
555
+ const models = this.catalogModelResolver
556
+ ? await runProviderRefreshActivity(context, "catalog.resolve", () => raceProviderRefreshAbort(context?.signal, this.catalogModelResolver?.({
557
+ connection: initializedProbe.connection,
558
+ sessionId: response.sessionId,
559
+ models: derivedModels,
560
+ configOptions: transformed.configOptions,
561
+ runRequest: (request) => this.runACPRequest(request),
562
+ transformConfigOptions: (configOptions) => this.configOptionsTransformer
563
+ ? this.configOptionsTransformer(configOptions)
564
+ : configOptions,
565
+ logger: this.logger,
566
+ provider: this.provider,
567
+ }) ?? Promise.resolve(derivedModels)))
568
+ : derivedModels;
569
+ const modeInfo = deriveModesFromACP(this.defaultModes, transformed.modes, transformed.configOptions);
570
+ return {
571
+ models: this.modelTransformer ? this.modelTransformer(models) : models,
572
+ modes: modeInfo.modes,
573
+ };
574
+ }
575
+ finally {
576
+ context?.signal.removeEventListener("abort", handleAbort);
577
+ await closeProbe();
578
+ }
579
+ }
580
+ async listFeatures(config) {
581
+ const autoAcceptFeature = buildACPAutoAcceptFeature(config);
582
+ if (this.configFeatureOptions.length === 0) {
583
+ return [autoAcceptFeature];
584
+ }
585
+ this.assertProvider(config);
586
+ const probe = await this.spawnProcess(PROBE_ENV);
587
+ let probeSessionId = null;
588
+ try {
589
+ const response = await this.runACPRequest(() => probe.connection.newSession({
590
+ cwd: config.cwd,
591
+ mcpServers: [],
592
+ }));
593
+ probeSessionId = response.sessionId;
594
+ const transformed = this.transformSessionResponse(response);
595
+ return [
596
+ autoAcceptFeature,
597
+ ...deriveFeaturesFromACP(transformed.configOptions, this.configFeatureOptions),
598
+ ];
599
+ }
600
+ finally {
601
+ await this.closeProbe(probe, probeSessionId);
602
+ }
603
+ }
604
+ async listImportableSessions(options) {
605
+ const history = new ACPImportHistoryCollector();
606
+ const probe = await this.spawnProcess(PROBE_ENV, {
607
+ client: this.buildProbeClient((params) => history.accept(params)),
608
+ });
609
+ try {
610
+ if (!probe.initialize.agentCapabilities?.sessionCapabilities?.list) {
611
+ return [];
612
+ }
613
+ const sessions = [];
614
+ const resultLimit = options?.limit ?? Number.POSITIVE_INFINITY;
615
+ const scanLimit = Math.min(options?.scanLimit ?? 500, 500);
616
+ const canLoadHistory = probe.initialize.agentCapabilities.loadSession === true;
617
+ const historyDeadline = this.now() + ACP_IMPORT_HISTORY_BUDGET_MS;
618
+ let scanned = 0;
619
+ let cursor;
620
+ for (;;) {
621
+ const page = await this.runACPRequest(() => probe.connection.listSessions(acpSessionListRequest(cursor, options?.cwd)));
622
+ for (const session of page.sessions) {
623
+ if (scanned >= scanLimit || sessions.length >= resultLimit)
624
+ break;
625
+ scanned += 1;
626
+ const descriptor = await this.describeImportableSession(probe, history, session, canLoadHistory, historyDeadline);
627
+ if (descriptor)
628
+ sessions.push(descriptor);
629
+ }
630
+ cursor = page.nextCursor ?? null;
631
+ if (!cursor)
632
+ break;
633
+ if (scanned >= scanLimit || sessions.length >= resultLimit)
634
+ break;
635
+ }
636
+ return sessions;
637
+ }
638
+ finally {
639
+ await this.closeProbe(probe);
640
+ }
641
+ }
642
+ async describeImportableSession(probe, history, session, canLoadHistory, historyDeadline) {
643
+ const loadedPreviews = canLoadHistory
644
+ ? await this.loadImportPromptPreviews(probe, history, session, historyDeadline)
645
+ : null;
646
+ if (loadedPreviews?.hasConversation === false)
647
+ return null;
648
+ return {
649
+ providerHandleId: session.sessionId,
650
+ cwd: session.cwd,
651
+ title: session.title ?? null,
652
+ firstPromptPreview: loadedPreviews?.firstPromptPreview ?? null,
653
+ lastPromptPreview: loadedPreviews?.lastPromptPreview ?? null,
654
+ lastActivityAt: session.updatedAt ? new Date(session.updatedAt) : new Date(0),
655
+ };
656
+ }
657
+ async loadImportPromptPreviews(probe, history, session, historyDeadline) {
658
+ const updatedAt = session.updatedAt ?? null;
659
+ const cached = this.importPromptCache.get(session.sessionId);
660
+ if (updatedAt !== null && cached?.updatedAt === updatedAt) {
661
+ return {
662
+ firstPromptPreview: cached.firstPromptPreview,
663
+ lastPromptPreview: cached.lastPromptPreview,
664
+ hasConversation: cached.hasConversation,
665
+ };
666
+ }
667
+ const remainingMs = historyDeadline - this.now();
668
+ if (remainingMs <= 0)
669
+ return null;
670
+ const loadTimeoutMs = Math.min(ACP_IMPORT_HISTORY_LOAD_TIMEOUT_MS, remainingMs);
671
+ history.begin(session.sessionId);
672
+ try {
673
+ await withTimeout(this.runACPRequest(() => probe.connection.loadSession({
674
+ sessionId: session.sessionId,
675
+ cwd: session.cwd,
676
+ mcpServers: [],
677
+ })), loadTimeoutMs, `ACP import history load timed out after ${loadTimeoutMs}ms`);
678
+ const previews = history.finish(session.sessionId);
679
+ if (updatedAt !== null) {
680
+ this.importPromptCache.set(session.sessionId, { updatedAt, ...previews });
681
+ }
682
+ return previews;
683
+ }
684
+ catch (error) {
685
+ history.discard(session.sessionId);
686
+ this.logger.debug({ err: error, sessionId: session.sessionId }, "ACP import history load failed; keeping the session visible");
687
+ return null;
688
+ }
689
+ finally {
690
+ await this.closeLoadedSession(probe, session.sessionId, historyDeadline);
691
+ }
692
+ }
693
+ async closeLoadedSession(probe, sessionId, historyDeadline) {
694
+ if (!probe.initialize.agentCapabilities?.sessionCapabilities?.close)
695
+ return;
696
+ const remainingMs = historyDeadline - this.now();
697
+ if (remainingMs <= 0)
698
+ return;
699
+ const closeTimeoutMs = Math.min(ACP_PROBE_CLOSE_TIMEOUT_MS, remainingMs);
700
+ try {
701
+ await withTimeout(probe.connection.unstable_closeSession({ sessionId }), closeTimeoutMs, `ACP loaded session/close timed out after ${closeTimeoutMs}ms`);
702
+ }
703
+ catch (error) {
704
+ this.logger.debug({ err: error, sessionId }, "ACP loaded session close failed");
705
+ }
706
+ }
707
+ async importSession(input, context) {
708
+ return importSessionFromPersistence({
709
+ provider: this.provider,
710
+ request: input,
711
+ context,
712
+ resumeSession: this.resumeSession.bind(this),
713
+ });
714
+ }
715
+ async isAvailable() {
716
+ try {
717
+ await this.resolveLaunchCommand();
718
+ return true;
719
+ }
720
+ catch {
721
+ return false;
722
+ }
723
+ }
724
+ async spawnProcess(launchEnv, options) {
725
+ const transport = await this.spawnTransport(launchEnv, options?.client);
726
+ const probe = {
727
+ child: transport.child,
728
+ connection: transport.connection,
729
+ stderrChunks: transport.stderrChunks,
730
+ };
731
+ options?.onSpawned?.(probe);
732
+ try {
733
+ const initialize = await this.initializeTransport(transport, options?.initializeTimeoutMs);
734
+ const initializedProbe = {
735
+ ...probe,
736
+ initialize,
737
+ };
738
+ probe.initialize = initialize;
739
+ return initializedProbe;
740
+ }
741
+ catch (error) {
742
+ await terminateChildProcess(transport.child, 2000, this.terminateProcess);
743
+ throw error;
744
+ }
745
+ }
746
+ async spawnTransport(launchEnv, client = this.buildProbeClient()) {
747
+ const { command, args } = await this.resolveLaunchCommand();
748
+ const child = spawnProcess(command, args, {
749
+ cwd: process.cwd(),
750
+ ...createProviderEnvSpec({
751
+ runtimeSettings: this.runtimeSettings,
752
+ overlays: [launchEnv],
753
+ }),
754
+ stdio: ["pipe", "pipe", "pipe"],
755
+ });
756
+ assertChildWithPipes(child);
757
+ const stderrChunks = [];
758
+ child.stderr.on("data", (chunk) => {
759
+ stderrChunks.push(chunk.toString());
760
+ });
761
+ const spawnErrorPromise = new Promise((_, reject) => {
762
+ child.once("error", (error) => {
763
+ const stderr = stderrChunks.join("").trim();
764
+ reject(new Error(stderr ? `${String(error)}\n${stderr}` : String(error)));
765
+ });
766
+ });
767
+ const spawnReadyPromise = new Promise((resolve) => {
768
+ child.once("spawn", () => {
769
+ resolve();
770
+ });
771
+ });
772
+ const stream = createLoggedNdJsonStream(Writable.toWeb(child.stdin), Readable.toWeb(child.stdout), { logger: this.logger, provider: this.provider });
773
+ const connection = new ClientSideConnection(() => client, stream);
774
+ return {
775
+ child,
776
+ connection,
777
+ stderrChunks,
778
+ spawnReady: spawnReadyPromise,
779
+ spawnError: spawnErrorPromise,
780
+ };
781
+ }
782
+ async initializeTransport(transport, initializeTimeoutMs) {
783
+ let timeout = null;
784
+ const initializeTimeoutPromise = initializeTimeoutMs
785
+ ? new Promise((_, reject) => {
786
+ timeout = setTimeout(() => {
787
+ reject(new Error(`ACP initialize timed out after ${initializeTimeoutMs}ms`));
788
+ }, initializeTimeoutMs);
789
+ })
790
+ : null;
791
+ try {
792
+ return await this.runACPRequest(() => Promise.race([
793
+ transport.connection.initialize({
794
+ protocolVersion: PROTOCOL_VERSION,
795
+ clientCapabilities: buildACPClientCapabilities(this.clientCapabilityMeta, this.clientCapabilities),
796
+ clientInfo: { name: "Paseo", version: "dev" },
797
+ }),
798
+ transport.spawnError,
799
+ ...(initializeTimeoutPromise ? [initializeTimeoutPromise] : []),
800
+ ]));
801
+ }
802
+ finally {
803
+ if (timeout) {
804
+ clearTimeout(timeout);
805
+ }
806
+ }
807
+ }
808
+ buildProbeClient(onSessionUpdate) {
809
+ return {
810
+ async requestPermission() {
811
+ return { outcome: { outcome: "cancelled" } };
812
+ },
813
+ async sessionUpdate(params) {
814
+ await onSessionUpdate?.(params);
815
+ },
816
+ async readTextFile(params) {
817
+ const content = await fs.readFile(params.path, "utf8");
818
+ return { content };
819
+ },
820
+ async writeTextFile(params) {
821
+ await fs.mkdir(path.dirname(params.path), { recursive: true });
822
+ await fs.writeFile(params.path, params.content, "utf8");
823
+ return {};
824
+ },
825
+ async createTerminal() {
826
+ throw new Error("ACP model probe does not support terminal execution");
827
+ },
828
+ };
829
+ }
830
+ async closeProbe(probe, sessionId = null) {
831
+ try {
832
+ if (sessionId && probe.initialize?.agentCapabilities?.sessionCapabilities?.close) {
833
+ await withTimeout(probe.connection.unstable_closeSession({ sessionId }), ACP_PROBE_CLOSE_TIMEOUT_MS, `ACP probe session/close timed out after ${ACP_PROBE_CLOSE_TIMEOUT_MS}ms`);
834
+ }
835
+ }
836
+ catch (error) {
837
+ this.logger.debug({ err: error, sessionId }, "ACP probe closeSession failed during cleanup");
838
+ }
839
+ finally {
840
+ await terminateChildProcess(probe.child, 2000, this.terminateProcess);
841
+ }
842
+ }
843
+ async runACPRequest(request) {
844
+ try {
845
+ return await request();
846
+ }
847
+ catch (error) {
848
+ throw toACPRequestError(error);
849
+ }
850
+ }
851
+ async buildACPProbeDiagnosticRows(options = {}) {
852
+ const rows = [];
853
+ const phaseTimeoutMs = options.phaseTimeoutMs ?? ACP_DIAGNOSTIC_PHASE_TIMEOUT_MS;
854
+ const cwd = options.cwd ?? homedir();
855
+ let transport = null;
856
+ let initialize = null;
857
+ let probeSessionId = null;
858
+ try {
859
+ const spawnStartedAt = Date.now();
860
+ try {
861
+ transport = await this.spawnTransport(PROBE_ENV);
862
+ await withTimeout(Promise.race([transport.spawnReady, transport.spawnError]), phaseTimeoutMs, `ACP spawn timed out after ${phaseTimeoutMs}ms`);
863
+ rows.push({
864
+ label: "ACP spawn",
865
+ value: `ok (${formatDurationMs(spawnStartedAt)})`,
866
+ });
867
+ }
868
+ catch (error) {
869
+ rows.push({
870
+ label: "ACP spawn",
871
+ value: `error: ${toDiagnosticErrorMessage(error)}`,
872
+ });
873
+ return rows;
874
+ }
875
+ const activeTransport = transport;
876
+ const initializeStartedAt = Date.now();
877
+ try {
878
+ initialize = await this.initializeTransport(activeTransport, phaseTimeoutMs);
879
+ rows.push({
880
+ label: "ACP initialize",
881
+ value: `ok (${formatDurationMs(initializeStartedAt)})`,
882
+ });
883
+ }
884
+ catch (error) {
885
+ rows.push({
886
+ label: "ACP initialize",
887
+ value: `error: ${toDiagnosticErrorMessage(error)}`,
888
+ });
889
+ pushACPStderrRow(rows, activeTransport.stderrChunks);
890
+ return rows;
891
+ }
892
+ const sessionStartedAt = Date.now();
893
+ try {
894
+ const response = await withTimeout(this.runACPRequest(() => activeTransport.connection.newSession({
895
+ cwd,
896
+ mcpServers: [],
897
+ })), phaseTimeoutMs, `ACP session/new timed out after ${phaseTimeoutMs}ms`);
898
+ probeSessionId = response.sessionId;
899
+ const transformed = this.transformSessionResponse(response);
900
+ const models = deriveModelDefinitionsFromACP(this.provider, transformed.models, transformed.configOptions);
901
+ const modeInfo = deriveModesFromACP(this.defaultModes, transformed.modes, transformed.configOptions);
902
+ rows.push({
903
+ label: "ACP session/new",
904
+ value: `ok (${formatDurationMs(sessionStartedAt)}; models=${models.length}; modes=${modeInfo.modes.length})`,
905
+ });
906
+ }
907
+ catch (error) {
908
+ rows.push({
909
+ label: "ACP session/new",
910
+ value: `error: ${toDiagnosticErrorMessage(error)}`,
911
+ });
912
+ pushACPStderrRow(rows, activeTransport.stderrChunks);
913
+ return rows;
914
+ }
915
+ pushACPStderrRow(rows, activeTransport.stderrChunks);
916
+ return rows;
917
+ }
918
+ finally {
919
+ if (transport) {
920
+ const cleanupStartedAt = Date.now();
921
+ try {
922
+ await this.closeProbe({
923
+ child: transport.child,
924
+ connection: transport.connection,
925
+ stderrChunks: transport.stderrChunks,
926
+ ...(initialize ? { initialize } : {}),
927
+ }, probeSessionId);
928
+ rows.push({
929
+ label: "ACP cleanup",
930
+ value: `ok (${formatDurationMs(cleanupStartedAt)})`,
931
+ });
932
+ }
933
+ catch (error) {
934
+ rows.push({
935
+ label: "ACP cleanup",
936
+ value: `error: ${toDiagnosticErrorMessage(error)}`,
937
+ });
938
+ }
939
+ }
940
+ }
941
+ }
942
+ async resolveLaunchCommand() {
943
+ const prefix = await resolveProviderLaunch({
944
+ commandConfig: this.runtimeSettings?.command,
945
+ defaultBinary: this.defaultCommand[0],
946
+ });
947
+ const availability = await checkProviderLaunchAvailable(prefix);
948
+ if (!availability.available) {
949
+ throw new Error(`${this.provider} command '${this.defaultCommand[0]}' not found`);
950
+ }
951
+ return {
952
+ command: prefix.command,
953
+ args: [...prefix.args, ...this.defaultCommand.slice(1)],
954
+ };
955
+ }
956
+ assertProvider(config) {
957
+ if (config.provider !== this.provider) {
958
+ throw new Error(`Expected ${this.provider} config, received ${config.provider}`);
959
+ }
960
+ }
961
+ transformSessionResponse(response) {
962
+ const transformed = this.sessionResponseTransformer
963
+ ? this.sessionResponseTransformer(response)
964
+ : response;
965
+ if (!this.configOptionsTransformer || !transformed.configOptions) {
966
+ return transformed;
967
+ }
968
+ return {
969
+ ...transformed,
970
+ configOptions: this.configOptionsTransformer(transformed.configOptions),
971
+ };
972
+ }
973
+ }
974
+ /**
975
+ * Fail-closed ceiling on how long a staged replacement may wait for the stop
976
+ * boundary in front of it. Follows the OpenCode pending-abort deadline: it
977
+ * bounds the caller's wait, it never manufactures provider readiness. Expiry
978
+ * rejects only the queued replacement and leaves the session stopping.
979
+ */
980
+ export const ACP_STOPPED_TURN_ADMISSION_TIMEOUT_MS = 10000;
981
+ const ACP_FOREGROUND_ACTIVE_ERROR = "A foreground turn is already active";
982
+ function createDeferred() {
983
+ let resolve;
984
+ let reject;
985
+ const promise = new Promise((res, rej) => {
986
+ resolve = res;
987
+ reject = rej;
988
+ });
989
+ return { promise, resolve, reject };
990
+ }
991
+ export class ACPAgentSession {
992
+ constructor(config, options) {
993
+ this.subscribers = new Set();
994
+ this.pendingPermissions = new Map();
995
+ this.pendingUserMessage = null;
996
+ this.submittedUserMessageTurnId = null;
997
+ this.toolCalls = new Map();
998
+ this.terminalEntries = new Map();
999
+ this.persistedHistory = [];
1000
+ this.child = null;
1001
+ this.connection = null;
1002
+ this.agentCapabilities = null;
1003
+ this.sessionId = null;
1004
+ this.currentMode = null;
1005
+ this.currentModel = null;
1006
+ this.availableModels = null;
1007
+ this.thinkingOptionId = null;
1008
+ this.currentTitle = null;
1009
+ this.lastActivityAt = null;
1010
+ this.configOptions = [];
1011
+ this.cachedCommands = [];
1012
+ this.commandsReadyDeferred = null;
1013
+ this.commandsReadySettled = false;
1014
+ this.activeForegroundTurnId = null;
1015
+ /**
1016
+ * Foreground admission state and the stop boundary in front of it. See
1017
+ * {@link ACPAdmissionState} for the phases and their transitions. Both move
1018
+ * only inside synchronous sections: a reservation is never split across an
1019
+ * `await`, so no event, echo, turn id, or prompt can escape before ownership
1020
+ * is taken.
1021
+ */
1022
+ this.admissionState = "idle";
1023
+ this.stop = null;
1024
+ this.connectionRevision = 0;
1025
+ this.connectionDeathSignal = null;
1026
+ this.fallbackAssistantMessageId = null;
1027
+ this.closed = false;
1028
+ this.historyPending = false;
1029
+ this.replayingHistory = false;
1030
+ this.bootstrapThreadEventPending = false;
1031
+ this.provider = options.provider;
1032
+ this.terminateProcess = options.terminateProcess ?? terminateWithTreeKill;
1033
+ this.capabilities = options.capabilities;
1034
+ this.logger = options.logger.child({ module: "agent", provider: options.provider });
1035
+ this.runtimeSettings = options.runtimeSettings;
1036
+ this.defaultCommand = options.defaultCommand;
1037
+ this.defaultModes = options.defaultModes;
1038
+ this.modelTransformer = options.modelTransformer;
1039
+ this.sessionResponseTransformer = options.sessionResponseTransformer;
1040
+ this.configOptionsTransformer = options.configOptionsTransformer;
1041
+ this.configFeatureOptions = options.configFeatureOptions ?? [];
1042
+ this.clientCapabilities = options.clientCapabilities;
1043
+ this.clientCapabilityMeta = options.clientCapabilityMeta;
1044
+ this.modeIdTransformer = options.modeIdTransformer;
1045
+ this.toolSnapshotTransformer = options.toolSnapshotTransformer;
1046
+ this.providerModeWriter = options.providerModeWriter;
1047
+ this.beforeModeWriter = options.beforeModeWriter;
1048
+ this.thinkingOptionWriter = options.thinkingOptionWriter;
1049
+ this.availableModes = options.defaultModes;
1050
+ this.agentId = options.agentId;
1051
+ this.launchEnv = options.launchEnv;
1052
+ this.initialHandle = options.handle;
1053
+ this.config = { ...config, provider: options.provider };
1054
+ this.currentMode = config.modeId ?? null;
1055
+ this.currentModel = config.model ?? null;
1056
+ this.thinkingOptionId = config.thinkingOptionId ?? null;
1057
+ this.currentTitle = config.title ?? null;
1058
+ this.waitForInitialCommands = options.waitForInitialCommands ?? false;
1059
+ this.initialCommandsWaitTimeoutMs = options.initialCommandsWaitTimeoutMs ?? 1500;
1060
+ this.extensionCommandsParser = options.extensionCommandsParser;
1061
+ }
1062
+ // ── Provider-neutral extension seams ────────────────────────────────────
1063
+ // A provider subclass builds on this session without reaching into private
1064
+ // state. Everything below is read-only unless named explicitly; none of it
1065
+ // hands out the mutable connection, environment, or stop internals in a way
1066
+ // that would let a subclass bypass the admission boundary.
1067
+ getAcpSessionId() {
1068
+ return this.sessionId;
1069
+ }
1070
+ getAcpConnection() {
1071
+ return this.connection;
1072
+ }
1073
+ getForegroundTurnId() {
1074
+ return this.activeForegroundTurnId;
1075
+ }
1076
+ getAdmissionState() {
1077
+ return this.admissionState;
1078
+ }
1079
+ getCurrentStop() {
1080
+ return this.stop;
1081
+ }
1082
+ /** One-key read-only view of the launch environment. Never exposes the object. */
1083
+ getLaunchEnv(name) {
1084
+ return this.launchEnv?.[name];
1085
+ }
1086
+ get id() {
1087
+ return this.sessionId;
1088
+ }
1089
+ async initializeNewSession() {
1090
+ try {
1091
+ const spawned = await this.spawnProcess();
1092
+ this.child = spawned.child;
1093
+ this.connection = spawned.connection;
1094
+ this.agentCapabilities = spawned.initialize.agentCapabilities ?? null;
1095
+ const response = await this.runACPRequest(() => this.connection.newSession({
1096
+ cwd: this.config.cwd,
1097
+ mcpServers: this.acpMcpServers(),
1098
+ }));
1099
+ this.sessionId = response.sessionId;
1100
+ this.bootstrapThreadEventPending = true;
1101
+ this.applySessionState(response);
1102
+ await this.applyConfiguredOverrides();
1103
+ }
1104
+ catch (error) {
1105
+ await this.closeAfterInitializationFailure(error);
1106
+ }
1107
+ }
1108
+ /**
1109
+ * IMPORTANT: Some ACP providers (e.g., Devin CLI) require all three params
1110
+ * (sessionId, cwd, mcpServers) to be present in session/load or
1111
+ * unstable_resumeSession — even when mcpServers is an empty array — and
1112
+ * return "Invalid params" if any are omitted. Never drop cwd or mcpServers
1113
+ * from these calls regardless of capabilities.
1114
+ */
1115
+ async initializeResumedSession() {
1116
+ try {
1117
+ const handle = this.initialHandle;
1118
+ if (!handle) {
1119
+ throw new Error("Resume requested without persistence handle");
1120
+ }
1121
+ const spawned = await this.spawnProcess();
1122
+ this.child = spawned.child;
1123
+ this.connection = spawned.connection;
1124
+ this.agentCapabilities = spawned.initialize.agentCapabilities ?? null;
1125
+ this.sessionId = handle.sessionId;
1126
+ this.bootstrapThreadEventPending = true;
1127
+ const sessionCapabilities = this.agentCapabilities?.sessionCapabilities;
1128
+ if (this.agentCapabilities?.loadSession) {
1129
+ this.replayingHistory = true;
1130
+ const response = await this.runACPRequest(() => this.connection.loadSession({
1131
+ sessionId: handle.sessionId,
1132
+ cwd: this.config.cwd,
1133
+ mcpServers: this.acpMcpServers(),
1134
+ }));
1135
+ this.deliverTranslatedEvents(this.flushPendingUserMessage());
1136
+ this.replayingHistory = false;
1137
+ this.historyPending = this.persistedHistory.length > 0;
1138
+ this.applySessionState(response);
1139
+ }
1140
+ else if (sessionCapabilities?.resume) {
1141
+ const response = await this.runACPRequest(() => this.connection.unstable_resumeSession({
1142
+ sessionId: handle.sessionId,
1143
+ cwd: this.config.cwd,
1144
+ mcpServers: this.acpMcpServers(),
1145
+ }));
1146
+ this.applySessionState(response);
1147
+ }
1148
+ else {
1149
+ throw new Error(`${this.provider} does not support ACP session resume`);
1150
+ }
1151
+ await this.applyConfiguredOverrides();
1152
+ }
1153
+ catch (error) {
1154
+ await this.closeAfterInitializationFailure(error);
1155
+ }
1156
+ }
1157
+ async closeAfterInitializationFailure(error) {
1158
+ try {
1159
+ await this.close();
1160
+ }
1161
+ catch (closeError) {
1162
+ this.logger.warn({ err: closeError, initializationError: error }, "Failed to close ACP process after session initialization failure");
1163
+ }
1164
+ throw error;
1165
+ }
1166
+ async run(prompt, options) {
1167
+ const result = await runProviderTurn({
1168
+ prompt,
1169
+ runOptions: options,
1170
+ startTurn: (p, o) => this.startTurn(p, o),
1171
+ subscribe: (callback) => this.subscribe(callback),
1172
+ getSessionId: () => this.sessionId ?? "",
1173
+ reduceFinalText: appendOrReplaceGrowingAssistantMessage,
1174
+ });
1175
+ if (!this.sessionId) {
1176
+ throw new Error("ACP session did not expose a session id");
1177
+ }
1178
+ return result;
1179
+ }
1180
+ async startTurn(prompt, options) {
1181
+ return this.startTurnWithAdmission(prompt, options);
1182
+ }
1183
+ /**
1184
+ * The single admission path for every foreground prompt, ordinary or staged
1185
+ * behind a stop.
1186
+ *
1187
+ * 1. A call that arrives while a stop is installed becomes that stop's staged
1188
+ * successor — at most one per stop; a second concurrent call throws the
1189
+ * foreground-active error instead of displacing the first.
1190
+ * 2. It then waits for the stop's gates (authoritative terminal, settled and
1191
+ * successful cancellation writes, provider proof) inside
1192
+ * {@link ACP_STOPPED_TURN_ADMISSION_TIMEOUT_MS}. The deadline rejects only
1193
+ * this waiter; it never sends a prompt and never opens readiness.
1194
+ * 3. {@link reserveForegroundSlot} rechecks every fact and reserves the
1195
+ * foreground slot with no `await` in between.
1196
+ * 4. Only after the reservation are the turn id and the start-side effects
1197
+ * produced, in the order ACP always used them.
1198
+ */
1199
+ async startTurnWithAdmission(prompt, options) {
1200
+ if (this.closed) {
1201
+ throw new Error(`${this.provider} session is closed`);
1202
+ }
1203
+ if (!this.connection || !this.sessionId) {
1204
+ throw new Error(`${this.provider} session is not initialized`);
1205
+ }
1206
+ const staging = this.stageAdmission();
1207
+ if (staging.kind === "queued") {
1208
+ // Rejects on invalidation, deadline expiry, or close; resolves only when
1209
+ // the stop's gates are satisfied. The reservation rechecks everything.
1210
+ await staging.release.promise;
1211
+ }
1212
+ // ── Synchronous commit section ────────────────────────────────────────
1213
+ // No `await` may appear between the checks in reserveForegroundSlot and the
1214
+ // reservation it performs, and no successor side effect may run before it.
1215
+ const detachedStop = this.reserveForegroundSlot(staging);
1216
+ let turnId = null;
1217
+ try {
1218
+ this.deliverTranslatedEvents(this.flushPendingUserMessage());
1219
+ turnId = randomUUID();
1220
+ const foregroundTurnId = turnId;
1221
+ const messageId = options?.clientMessageId ?? randomUUID();
1222
+ this.activeForegroundTurnId = foregroundTurnId;
1223
+ this.fallbackAssistantMessageId = null;
1224
+ this.submittedUserMessageTurnId = null;
1225
+ this.emitBootstrapThreadEvent();
1226
+ this.pushEvent({ type: "turn_started", provider: this.provider, turnId: foregroundTurnId });
1227
+ this.emitSubmittedUserMessage(prompt, messageId, foregroundTurnId, options?.clientMessageId);
1228
+ // reserved → running happens before the prompt write: from this line the
1229
+ // foreground slot belongs to `foregroundTurnId` for admission purposes.
1230
+ this.admissionState = "running";
1231
+ const connection = this.connection;
1232
+ const sessionId = this.sessionId;
1233
+ void connection
1234
+ .prompt({
1235
+ sessionId,
1236
+ messageId,
1237
+ prompt: toACPContentBlocks(prompt),
1238
+ })
1239
+ .then((response) => {
1240
+ this.handlePromptResponse(response, foregroundTurnId);
1241
+ return;
1242
+ })
1243
+ .catch((error) => {
1244
+ const summary = summarizeACPRequestError(error);
1245
+ this.finishTurn(foregroundTurnId, {
1246
+ type: "turn_failed",
1247
+ provider: this.provider,
1248
+ error: summary.message,
1249
+ code: summary.code,
1250
+ diagnostic: this.collectDiagnostic(summary.diagnostic ?? summary.message),
1251
+ turnId: foregroundTurnId,
1252
+ });
1253
+ });
1254
+ }
1255
+ catch (error) {
1256
+ // Roll back only this reservation. A stop that was in front of it keeps
1257
+ // every fact it earned; it is never reopened by a failed send.
1258
+ this.rollbackReservation(detachedStop, turnId);
1259
+ throw error;
1260
+ }
1261
+ return { turnId };
1262
+ }
1263
+ /**
1264
+ * Registers the caller as a stop's sole staged successor. A call with no stop
1265
+ * in front of it commits immediately; a call while the foreground slot is held
1266
+ * throws, exactly as it always has.
1267
+ */
1268
+ stageAdmission() {
1269
+ const stop = this.stop;
1270
+ if (!stop) {
1271
+ if (this.admissionState !== "idle") {
1272
+ throw new Error(ACP_FOREGROUND_ACTIVE_ERROR);
1273
+ }
1274
+ return { kind: "immediate" };
1275
+ }
1276
+ if (stop.stagedSuccessor) {
1277
+ throw new Error(ACP_FOREGROUND_ACTIVE_ERROR);
1278
+ }
1279
+ const token = randomUUID();
1280
+ const release = createDeferred();
1281
+ const staged = {
1282
+ token,
1283
+ release,
1284
+ deadline: setTimeout(() => this.expireStagedSuccessor(stop, token), ACP_STOPPED_TURN_ADMISSION_TIMEOUT_MS),
1285
+ };
1286
+ stop.stagedSuccessor = staged;
1287
+ // Newest-wins across the one-microtask window between gate release and
1288
+ // reserveForegroundSlot: staging a new successor clears the released token,
1289
+ // so a released-but-uncommitted caller loses the slot and throws the
1290
+ // foreground-active error. Exactly one caller ever commits.
1291
+ stop.releasedSuccessorToken = null;
1292
+ this.logger.info({
1293
+ stopId: stop.stopId,
1294
+ stoppedTurnId: stop.stoppedTurnId,
1295
+ token,
1296
+ kind: stop.kind,
1297
+ sessionId: stop.sessionId,
1298
+ timeoutMs: ACP_STOPPED_TURN_ADMISSION_TIMEOUT_MS,
1299
+ }, "provider.acp.successor_staged");
1300
+ // The stop's facts may already be complete, in which case the waiter is
1301
+ // released before the first await and the commit recheck decides.
1302
+ this.evaluateStopGate(stop);
1303
+ return { kind: "queued", stop, token, release };
1304
+ }
1305
+ /**
1306
+ * Deadline expiry rejects the queued replacement and nothing else: no prompt,
1307
+ * no turn event, no user echo, no turn id. The stop stays installed, so a
1308
+ * later request can still be evaluated on its own facts.
1309
+ */
1310
+ expireStagedSuccessor(stop, token) {
1311
+ if (this.stop !== stop) {
1312
+ return;
1313
+ }
1314
+ const staged = stop.stagedSuccessor;
1315
+ if (!staged || staged.token !== token) {
1316
+ return;
1317
+ }
1318
+ const unresolved = {
1319
+ terminal: !stop.terminalObserved,
1320
+ cancelWrites: !this.isCancelLedgerSatisfied(stop),
1321
+ providerGate: !this.isProviderStopGateSatisfied(stop),
1322
+ providerGateFacts: this.describeProviderStopGate(stop),
1323
+ };
1324
+ this.takeStagedSuccessor(stop);
1325
+ this.logger.info({
1326
+ stopId: stop.stopId,
1327
+ token,
1328
+ stoppedTurnId: stop.stoppedTurnId,
1329
+ timeoutMs: ACP_STOPPED_TURN_ADMISSION_TIMEOUT_MS,
1330
+ unresolved,
1331
+ }, "provider.acp.admission_deadline");
1332
+ staged.release.reject(new Error(`${this.provider} replacement turn was not admitted within ${ACP_STOPPED_TURN_ADMISSION_TIMEOUT_MS}ms; the previous turn is still being stopped`));
1333
+ }
1334
+ /**
1335
+ * Detaches and disarms the stop's staged successor, clearing the deadline and
1336
+ * the token slot together. This is the whole of successor cleanup, so close and
1337
+ * supersession can call it without touching stop state.
1338
+ */
1339
+ takeStagedSuccessor(stop) {
1340
+ const staged = stop.stagedSuccessor;
1341
+ if (!staged) {
1342
+ return null;
1343
+ }
1344
+ stop.stagedSuccessor = null;
1345
+ stop.releasedSuccessorToken = null;
1346
+ clearTimeout(staged.deadline);
1347
+ return staged;
1348
+ }
1349
+ /** Invalidates the queued replacement without touching the stop identity. */
1350
+ invalidateStagedSuccessor(stop, reason) {
1351
+ const staged = this.takeStagedSuccessor(stop);
1352
+ if (!staged) {
1353
+ return;
1354
+ }
1355
+ this.logger.info({ stopId: stop.stopId, token: staged.token, reason, stoppedTurnId: stop.stoppedTurnId }, "provider.acp.successor_invalidated");
1356
+ staged.release.reject(new Error(`${this.provider} staged replacement was invalidated (${reason})`));
1357
+ }
1358
+ /**
1359
+ * The one death path for the stop boundary, invoked by every way the session
1360
+ * observes its process or transport died: the child exit handler, the
1361
+ * connection close signal, and close. The SDK delivers `cancel()` as a
1362
+ * notification whose write errors are swallowed, so on a dead pipe an
1363
+ * undelivered cancel resolves as a settled success — death therefore settles
1364
+ * EVERY attempt, including recorded successes, as rejected, records provider
1365
+ * death proof, and rejects the staged successor immediately instead of
1366
+ * leaving it to the admission deadline. Idempotent: the first observation
1367
+ * wins and later ones (a signal abort after the exit handler, or close) are
1368
+ * no-ops. Gated on the stop's captured identity, so a stop captured on an
1369
+ * older connection stays untouched.
1370
+ */
1371
+ settleStopOnObservedDeath(reason) {
1372
+ const stop = this.stop;
1373
+ if (!stop || stop.deathSettled || !this.stopIdentityMatches(stop)) {
1374
+ return;
1375
+ }
1376
+ stop.deathSettled = true;
1377
+ for (const attempt of stop.cancelAttempts) {
1378
+ attempt.settled = true;
1379
+ attempt.outcome = "rejected";
1380
+ }
1381
+ stop.cancelSettledRevision = Math.max(stop.cancelSettledRevision, stop.cancelIssuedRevision);
1382
+ stop.newestCancelSucceeded = false;
1383
+ this.logger.info({
1384
+ stopId: stop.stopId,
1385
+ stoppedTurnId: stop.stoppedTurnId,
1386
+ attempts: stop.cancelAttempts.length,
1387
+ reason,
1388
+ }, "provider.acp.stop_death_settled");
1389
+ this.recordProviderStopDeath(stop, reason);
1390
+ this.invalidateStagedSuccessor(stop, reason);
1391
+ }
1392
+ /**
1393
+ * Opens the staged successor only when every fact the stop owes is present:
1394
+ * the session identity it captured, terminal proof for the turn it stopped, a
1395
+ * fully settled and successful cancellation ledger, and provider proof. Any
1396
+ * gap keeps the session stopping — nothing infers readiness here.
1397
+ */
1398
+ evaluateStopGate(stop) {
1399
+ if (this.closed || this.stop !== stop || !this.stopIdentityMatches(stop)) {
1400
+ return;
1401
+ }
1402
+ if (!stop.terminalObserved || !this.isCancelLedgerSatisfied(stop)) {
1403
+ return;
1404
+ }
1405
+ if (!this.isProviderStopGateSatisfied(stop)) {
1406
+ return;
1407
+ }
1408
+ const staged = this.takeStagedSuccessor(stop);
1409
+ if (!staged) {
1410
+ return;
1411
+ }
1412
+ stop.releasedSuccessorToken = staged.token;
1413
+ this.logger.info({
1414
+ stopId: stop.stopId,
1415
+ token: staged.token,
1416
+ stoppedTurnId: stop.stoppedTurnId,
1417
+ satisfiedGates: ["terminal", "cancelWrites", "providerGate"],
1418
+ }, "provider.acp.admission_released");
1419
+ staged.release.resolve();
1420
+ }
1421
+ /**
1422
+ * The cancellation ledger: every cancellation write issued for the stop must
1423
+ * have settled, and the newest must have succeeded. An older rejected write is
1424
+ * recovered only by a newer successful one after everything has settled, so no
1425
+ * unresolved write can trail behind a committed successor. A stop that never
1426
+ * issued a write owes the ledger nothing — foreground stops always issue their
1427
+ * first write synchronously after install, and a write that throws before it is
1428
+ * sent is recorded as rejected.
1429
+ */
1430
+ isCancelLedgerSatisfied(stop) {
1431
+ if (stop.cancelAttempts.length === 0) {
1432
+ return true;
1433
+ }
1434
+ const newest = stop.cancelAttempts[stop.cancelAttempts.length - 1];
1435
+ return (newest.revision === stop.cancelIssuedRevision &&
1436
+ stop.cancelAttempts.every((attempt) => attempt.settled) &&
1437
+ newest.outcome === "success");
1438
+ }
1439
+ /** The stop's captured identity must still be the live one. */
1440
+ stopIdentityMatches(stop) {
1441
+ return (this.connection === stop.connection &&
1442
+ this.connectionRevision === stop.connectionRevision &&
1443
+ this.sessionId === stop.sessionId);
1444
+ }
1445
+ /**
1446
+ * Reserves the foreground slot. Every check re-verifies a fact the release
1447
+ * already proved; any mismatch fails closed and leaves the stop installed.
1448
+ */
1449
+ reserveForegroundSlot(staging) {
1450
+ if (this.closed) {
1451
+ throw new Error(`${this.provider} session is closed`);
1452
+ }
1453
+ if (!this.connection || !this.sessionId) {
1454
+ throw new Error(`${this.provider} session is not initialized`);
1455
+ }
1456
+ const stop = this.stop;
1457
+ if (stop) {
1458
+ if (staging.kind !== "queued" || stop.releasedSuccessorToken !== staging.token) {
1459
+ throw new Error(ACP_FOREGROUND_ACTIVE_ERROR);
1460
+ }
1461
+ if (stop.stagedSuccessor) {
1462
+ throw new Error(ACP_FOREGROUND_ACTIVE_ERROR);
1463
+ }
1464
+ if (!this.stopIdentityMatches(stop)) {
1465
+ throw new Error(`${this.provider} session identity changed while a stop boundary was installed`);
1466
+ }
1467
+ if (!stop.terminalObserved) {
1468
+ throw new Error(`${this.provider} stop boundary is missing terminal proof`);
1469
+ }
1470
+ if (!this.isCancelLedgerSatisfied(stop)) {
1471
+ throw new Error(`${this.provider} stop boundary still has unresolved cancellation writes`);
1472
+ }
1473
+ if (!this.isProviderStopGateSatisfied(stop)) {
1474
+ throw new Error(`${this.provider} stop boundary is missing provider stop proof`);
1475
+ }
1476
+ this.stop = null;
1477
+ this.admissionState = "reserved";
1478
+ return stop;
1479
+ }
1480
+ if (this.admissionState !== "idle") {
1481
+ throw new Error(ACP_FOREGROUND_ACTIVE_ERROR);
1482
+ }
1483
+ this.admissionState = "reserved";
1484
+ return null;
1485
+ }
1486
+ rollbackReservation(stop, turnId) {
1487
+ if (this.activeForegroundTurnId && this.activeForegroundTurnId === turnId) {
1488
+ this.activeForegroundTurnId = null;
1489
+ }
1490
+ if (stop) {
1491
+ this.stop = stop;
1492
+ this.admissionState = "stopping";
1493
+ return;
1494
+ }
1495
+ this.admissionState = "idle";
1496
+ }
1497
+ /**
1498
+ * Installs a stop boundary. Must run synchronously before the first
1499
+ * cancellation write it is followed by, so admission closes before any
1500
+ * asynchronous cancellation work begins.
1501
+ */
1502
+ installStop(input) {
1503
+ if (!this.connection || !this.sessionId) {
1504
+ throw new Error(`${this.provider} session is not initialized`);
1505
+ }
1506
+ const stop = {
1507
+ stopId: randomUUID(),
1508
+ stoppedTurnId: input.stoppedTurnId,
1509
+ sessionId: this.sessionId,
1510
+ connection: this.connection,
1511
+ connectionRevision: this.connectionRevision,
1512
+ kind: input.kind,
1513
+ terminalObserved: false,
1514
+ terminalDelivered: false,
1515
+ cancelAttempts: [],
1516
+ cancelIssuedRevision: 0,
1517
+ cancelSettledRevision: 0,
1518
+ newestCancelSucceeded: false,
1519
+ deathSettled: false,
1520
+ stagedSuccessor: null,
1521
+ releasedSuccessorToken: null,
1522
+ providerGateSatisfied: true,
1523
+ };
1524
+ this.stop = stop;
1525
+ this.admissionState = "stopping";
1526
+ this.logger.info({
1527
+ stopId: stop.stopId,
1528
+ stoppedTurnId: stop.stoppedTurnId,
1529
+ kind: stop.kind,
1530
+ reason: input.reason,
1531
+ sessionId: stop.sessionId,
1532
+ connectionRevision: stop.connectionRevision,
1533
+ }, "provider.acp.stop_installed");
1534
+ return stop;
1535
+ }
1536
+ /**
1537
+ * The one foreground stop operation. Interrupt, permission denial, and a
1538
+ * repeated Stop all land here: it installs the boundary, or reuses the one
1539
+ * installed, and returns when the cancellation write it issued settles.
1540
+ * Settling a write proves transport completion only — the stop stays installed
1541
+ * until terminal proof and a fully settled ledger arrive.
1542
+ *
1543
+ * With no stop-able turn the cancellation write is suppressed entirely (AC13):
1544
+ * no stop is installed and admission state is untouched. A denial caller
1545
+ * passes `correlation`, and the suppression logs
1546
+ * `provider.acp.deny_cancel_suppressed` with a `reason` that separates the
1547
+ * not-initialized session from the no-active-turn case — review finding 3.
1548
+ */
1549
+ async stopForegroundTurn(input) {
1550
+ if (this.closed) {
1551
+ return;
1552
+ }
1553
+ const existing = this.stop;
1554
+ if (existing) {
1555
+ // Repeated Stop keeps stop identity and retries the same stop: the queued
1556
+ // successor is invalidated and a fresh attempt revision is issued.
1557
+ this.invalidateStagedSuccessor(existing, input.reason);
1558
+ await this.issueCancelWrite(existing);
1559
+ return;
1560
+ }
1561
+ const turnId = this.activeForegroundTurnId;
1562
+ if (!turnId || !this.connection || !this.sessionId) {
1563
+ // Deliberate delta from pre-stop-boundary behavior (AC13): a permission
1564
+ // denial arriving with no foreground turn and no installed stop sends no
1565
+ // cancellation. An untracked session-scoped cancel write is exactly what
1566
+ // the ledger exists to prevent. The suppressed write is still a fact
1567
+ // worth seeing: one event, with the deny correlation and a reason that
1568
+ // distinguishes an uninitialized session from a session with no
1569
+ // stop-able turn.
1570
+ if (input.correlation) {
1571
+ this.logger.info({
1572
+ permissionRequestId: input.correlation.permissionRequestId,
1573
+ ...(input.correlation.turnId ? { turnId: input.correlation.turnId } : {}),
1574
+ ...(this.sessionId ? { sessionId: this.sessionId } : {}),
1575
+ reason: this.connection && this.sessionId ? "no_active_turn" : "session_not_initialized",
1576
+ }, "provider.acp.deny_cancel_suppressed");
1577
+ }
1578
+ return;
1579
+ }
1580
+ const stop = this.installStop({
1581
+ kind: "foreground",
1582
+ stoppedTurnId: turnId,
1583
+ reason: input.reason,
1584
+ });
1585
+ await this.issueCancelWrite(stop);
1586
+ }
1587
+ /**
1588
+ * Issues one cancellation write on the connection the stop captured and tracks
1589
+ * its promise in that stop's ledger. A write that rejects — or throws before it
1590
+ * is sent — is recorded as rejected, which keeps the boundary closed.
1591
+ */
1592
+ issueCancelWrite(stop) {
1593
+ if (!this.stopIdentityMatches(stop)) {
1594
+ return Promise.reject(new Error(`${this.provider} cannot cancel a stopped turn on a replaced session or connection`));
1595
+ }
1596
+ const revision = stop.cancelIssuedRevision + 1;
1597
+ stop.cancelIssuedRevision = revision;
1598
+ const attempt = { revision, settled: false, outcome: "pending" };
1599
+ stop.cancelAttempts.push(attempt);
1600
+ this.logger.info({ stopId: stop.stopId, revision, sessionId: stop.sessionId }, "provider.acp.cancel_attempt_started");
1601
+ let write;
1602
+ try {
1603
+ write = stop.connection.cancel({ sessionId: stop.sessionId }).then(() => {
1604
+ this.settleCancelAttempt(stop, attempt, "success");
1605
+ return undefined;
1606
+ }, (error) => {
1607
+ this.settleCancelAttempt(stop, attempt, "rejected");
1608
+ throw error;
1609
+ });
1610
+ }
1611
+ catch (error) {
1612
+ this.settleCancelAttempt(stop, attempt, "rejected");
1613
+ throw error;
1614
+ }
1615
+ return write;
1616
+ }
1617
+ settleCancelAttempt(stop, attempt, outcome) {
1618
+ if (stop.deathSettled) {
1619
+ // Death closed this ledger; a resolution that lands after the transport
1620
+ // died is not delivery proof and cannot reopen the boundary.
1621
+ return;
1622
+ }
1623
+ attempt.settled = true;
1624
+ attempt.outcome = outcome;
1625
+ stop.cancelSettledRevision = Math.max(stop.cancelSettledRevision, attempt.revision);
1626
+ const newest = stop.cancelAttempts[stop.cancelAttempts.length - 1];
1627
+ stop.newestCancelSucceeded = newest.settled && newest.outcome === "success";
1628
+ this.logger.info({ stopId: stop.stopId, revision: attempt.revision, outcome }, "provider.acp.cancel_attempt_settled");
1629
+ // A rejected newest write keeps the session stopping; only a newer
1630
+ // successful retry on the same connection can recover it.
1631
+ this.evaluateStopGate(stop);
1632
+ }
1633
+ /** Provider-specific stop proof. The generic boundary needs none of it. */
1634
+ isProviderStopGateSatisfied(stop) {
1635
+ return stop.providerGateSatisfied;
1636
+ }
1637
+ /** Records provider stop proof and re-evaluates admission. */
1638
+ markProviderStopGateSatisfied(stop) {
1639
+ stop.providerGateSatisfied = true;
1640
+ this.evaluateStopGate(stop);
1641
+ }
1642
+ /**
1643
+ * Names the provider facts a stop is still waiting on, empty once the gate is
1644
+ * satisfied. The generic boundary has one opaque gate; a provider subclass
1645
+ * overrides this so an admission deadline names what it is missing instead of
1646
+ * only reporting a boolean.
1647
+ */
1648
+ describeProviderStopGate(stop) {
1649
+ return this.isProviderStopGateSatisfied(stop) ? [] : ["provider_gate"];
1650
+ }
1651
+ /**
1652
+ * Provider-specific proof for a stop settled by the death path, recorded
1653
+ * after the ledger is closed and before the staged successor is rejected.
1654
+ * The generic boundary records none; a subclass records what its own stop
1655
+ * gate still owes (a GJC ownerless abort settles its pending attempt as a
1656
+ * reject so the gate names the real reason).
1657
+ */
1658
+ recordProviderStopDeath(stop, reason) {
1659
+ void stop;
1660
+ void reason;
1661
+ }
1662
+ subscribe(callback) {
1663
+ this.subscribers.add(callback);
1664
+ if (this.sessionId) {
1665
+ callback({
1666
+ type: "thread_started",
1667
+ provider: this.provider,
1668
+ sessionId: this.sessionId,
1669
+ });
1670
+ }
1671
+ return () => {
1672
+ this.subscribers.delete(callback);
1673
+ };
1674
+ }
1675
+ async *streamHistory() {
1676
+ if (!this.historyPending || this.persistedHistory.length === 0) {
1677
+ return;
1678
+ }
1679
+ const history = [...this.persistedHistory];
1680
+ this.persistedHistory.length = 0;
1681
+ this.historyPending = false;
1682
+ for (const item of history) {
1683
+ yield { type: "timeline", provider: this.provider, item };
1684
+ }
1685
+ }
1686
+ async getRuntimeInfo() {
1687
+ return this.runtimeInfo();
1688
+ }
1689
+ async getAvailableModes() {
1690
+ return [...this.availableModes];
1691
+ }
1692
+ async getCurrentMode() {
1693
+ return this.currentMode;
1694
+ }
1695
+ get features() {
1696
+ return [
1697
+ buildACPAutoAcceptFeature(this.config),
1698
+ ...deriveFeaturesFromACP(this.configOptions, this.configFeatureOptions),
1699
+ ];
1700
+ }
1701
+ ensureCommandsReadyDeferred() {
1702
+ if (this.commandsReadyDeferred || this.commandsReadySettled || this.cachedCommands.length > 0) {
1703
+ return;
1704
+ }
1705
+ let resolve;
1706
+ const promise = new Promise((r) => {
1707
+ resolve = r;
1708
+ });
1709
+ this.commandsReadyDeferred = { promise, resolve };
1710
+ }
1711
+ settleCommandsReady() {
1712
+ if (this.commandsReadySettled) {
1713
+ return;
1714
+ }
1715
+ this.commandsReadySettled = true;
1716
+ this.commandsReadyDeferred?.resolve();
1717
+ this.commandsReadyDeferred = null;
1718
+ }
1719
+ async waitForCommandsReady() {
1720
+ const deferred = this.commandsReadyDeferred;
1721
+ if (!deferred) {
1722
+ return;
1723
+ }
1724
+ let timer = null;
1725
+ try {
1726
+ await Promise.race([
1727
+ deferred.promise,
1728
+ new Promise((resolve) => {
1729
+ timer = setTimeout(resolve, this.initialCommandsWaitTimeoutMs);
1730
+ }),
1731
+ ]);
1732
+ }
1733
+ finally {
1734
+ if (timer) {
1735
+ clearTimeout(timer);
1736
+ }
1737
+ }
1738
+ }
1739
+ async listCommands() {
1740
+ if (this.cachedCommands.length > 0) {
1741
+ return this.cachedCommands;
1742
+ }
1743
+ if (!this.waitForInitialCommands || this.closed) {
1744
+ return this.cachedCommands;
1745
+ }
1746
+ this.ensureCommandsReadyDeferred();
1747
+ await this.waitForCommandsReady();
1748
+ this.settleCommandsReady();
1749
+ return this.cachedCommands;
1750
+ }
1751
+ async setMode(modeId) {
1752
+ if (!this.connection || !this.sessionId) {
1753
+ throw new Error("ACP session not initialized");
1754
+ }
1755
+ const selection = resolveACPModeSelection({
1756
+ modeId,
1757
+ availableModes: this.availableModes,
1758
+ configOptions: this.configOptions,
1759
+ });
1760
+ await this.setModeWithSelection({ modeId, selection });
1761
+ }
1762
+ // Mode/model selection updates stay after ACP RPC success; this intentionally diverges from Zed's optimistic rollback path (acp.rs:3080-3104).
1763
+ async setModeWithSelection({ modeId, selection, }) {
1764
+ if (!this.connection || !this.sessionId) {
1765
+ throw new Error("ACP session not initialized");
1766
+ }
1767
+ const context = this.createProviderModeWriterContext(modeId, selection);
1768
+ const providerResult = this.providerModeWriter
1769
+ ? await this.providerModeWriter(context)
1770
+ : { handled: false };
1771
+ if (providerResult.handled) {
1772
+ this.currentMode = providerResult.currentModeId ?? modeId;
1773
+ if (providerResult.configOptions) {
1774
+ this.configOptions = this.transformConfigOptions(providerResult.configOptions);
1775
+ }
1776
+ this.availableModes = deriveModesFromACP(this.defaultModes, null, this.configOptions).modes;
1777
+ this.pushEvent({
1778
+ type: "mode_changed",
1779
+ provider: this.provider,
1780
+ currentModeId: this.currentMode,
1781
+ availableModes: [...this.availableModes],
1782
+ });
1783
+ return;
1784
+ }
1785
+ if (selection.hasAvailableModes) {
1786
+ if (!selection.availableMode) {
1787
+ this.warnInvalidSelection(modeId, `is not valid ${this.provider} mode. Available options: ${this.availableModes
1788
+ .map((mode) => mode.id)
1789
+ .join(", ")}`);
1790
+ return;
1791
+ }
1792
+ }
1793
+ else {
1794
+ const modeOption = selection.configOption;
1795
+ if (!modeOption) {
1796
+ throw new Error(`${this.provider} does not expose ACP mode switching`);
1797
+ }
1798
+ if (!selection.configChoice) {
1799
+ this.warnInvalidSelection(modeId, `is not valid ${this.provider} mode config option. Available options: ${flattenSelectOptions(modeOption.options)
1800
+ .map((option) => option.value)
1801
+ .join(", ")}`);
1802
+ return;
1803
+ }
1804
+ }
1805
+ if (this.beforeModeWriter) {
1806
+ const beforeResult = await this.beforeModeWriter(context);
1807
+ if (beforeResult?.configOptions) {
1808
+ this.configOptions = this.transformConfigOptions(beforeResult.configOptions);
1809
+ }
1810
+ }
1811
+ if (selection.hasAvailableModes) {
1812
+ await this.connection.setSessionMode({ sessionId: this.sessionId, modeId });
1813
+ this.currentMode = modeId;
1814
+ this.pushEvent({
1815
+ type: "mode_changed",
1816
+ provider: this.provider,
1817
+ currentModeId: this.currentMode,
1818
+ availableModes: [...this.availableModes],
1819
+ });
1820
+ return;
1821
+ }
1822
+ const modeOption = selection.configOption;
1823
+ if (!modeOption) {
1824
+ throw new Error(`${this.provider} does not expose ACP mode switching`);
1825
+ }
1826
+ const response = await this.connection.setSessionConfigOption({
1827
+ sessionId: this.sessionId,
1828
+ configId: modeOption.id,
1829
+ value: modeId,
1830
+ });
1831
+ this.currentMode = this.applyConfigOptionResponse({
1832
+ response,
1833
+ configId: modeOption.id,
1834
+ category: "mode",
1835
+ requestedValue: modeId,
1836
+ label: "mode",
1837
+ });
1838
+ this.availableModes = deriveModesFromACP(this.defaultModes, null, this.configOptions).modes;
1839
+ this.pushEvent({
1840
+ type: "mode_changed",
1841
+ provider: this.provider,
1842
+ currentModeId: this.currentMode,
1843
+ availableModes: [...this.availableModes],
1844
+ });
1845
+ }
1846
+ createProviderModeWriterContext(requestedModeId, selection) {
1847
+ if (!this.connection || !this.sessionId) {
1848
+ throw new Error("ACP session not initialized");
1849
+ }
1850
+ return {
1851
+ connection: this.connection,
1852
+ sessionId: this.sessionId,
1853
+ requestedModeId,
1854
+ currentModeId: this.currentMode,
1855
+ selection,
1856
+ configOptions: this.configOptions,
1857
+ logger: this.logger,
1858
+ };
1859
+ }
1860
+ async setModel(modelId) {
1861
+ if (!this.connection || !this.sessionId) {
1862
+ throw new Error("ACP session not initialized");
1863
+ }
1864
+ if (!modelId) {
1865
+ this.currentModel = null;
1866
+ return;
1867
+ }
1868
+ const selection = resolveACPModelSelection({
1869
+ modelId,
1870
+ availableModels: this.availableModels,
1871
+ configOptions: this.configOptions,
1872
+ });
1873
+ await this.setModelWithSelection({ modelId, selection });
1874
+ }
1875
+ async setModelWithSelection({ modelId, selection, }) {
1876
+ if (!this.connection || !this.sessionId) {
1877
+ throw new Error("ACP session not initialized");
1878
+ }
1879
+ if (selection.hasAvailableModels) {
1880
+ if (!selection.availableModel) {
1881
+ this.warnInvalidSelection(modelId, `is not a valid ${this.provider} model. Available options: ${this.availableModels
1882
+ ?.map((model) => model.modelId)
1883
+ .join(", ")}`);
1884
+ return;
1885
+ }
1886
+ if (typeof this.connection.unstable_setSessionModel !== "function") {
1887
+ throw new Error(this.modelSelectionUnavailableMessage());
1888
+ }
1889
+ try {
1890
+ await this.connection.unstable_setSessionModel({
1891
+ sessionId: this.sessionId,
1892
+ modelId,
1893
+ });
1894
+ this.currentModel = modelId;
1895
+ this.pushEvent({
1896
+ type: "model_changed",
1897
+ provider: this.provider,
1898
+ runtimeInfo: this.runtimeInfo(),
1899
+ });
1900
+ return;
1901
+ }
1902
+ catch {
1903
+ // Fall through to config option path.
1904
+ }
1905
+ }
1906
+ const modelOption = selection.configOption;
1907
+ if (!modelOption) {
1908
+ throw new Error(this.modelSelectionUnavailableMessage());
1909
+ }
1910
+ if (!selection.configChoice) {
1911
+ this.warnInvalidSelection(modelId, `is not a valid ${this.provider} model config option. Available options: ${flattenSelectOptions(modelOption.options)
1912
+ .map((option) => option.value)
1913
+ .join(", ")}`);
1914
+ return;
1915
+ }
1916
+ const response = await this.connection.setSessionConfigOption({
1917
+ sessionId: this.sessionId,
1918
+ configId: modelOption.id,
1919
+ value: modelId,
1920
+ });
1921
+ this.currentModel = this.applyConfigOptionResponse({
1922
+ response,
1923
+ configId: modelOption.id,
1924
+ category: "model",
1925
+ requestedValue: modelId,
1926
+ label: "model",
1927
+ });
1928
+ this.pushEvent({
1929
+ type: "model_changed",
1930
+ provider: this.provider,
1931
+ runtimeInfo: this.runtimeInfo(),
1932
+ });
1933
+ }
1934
+ async setThinkingOption(thinkingOptionId) {
1935
+ if (!this.connection || !this.sessionId) {
1936
+ throw new Error("ACP session not initialized");
1937
+ }
1938
+ if (!thinkingOptionId) {
1939
+ this.thinkingOptionId = null;
1940
+ return;
1941
+ }
1942
+ if (this.thinkingOptionWriter) {
1943
+ await this.thinkingOptionWriter(this.connection, this.sessionId, thinkingOptionId);
1944
+ this.thinkingOptionId = thinkingOptionId;
1945
+ this.pushEvent({
1946
+ type: "thinking_option_changed",
1947
+ provider: this.provider,
1948
+ thinkingOptionId: this.thinkingOptionId,
1949
+ });
1950
+ return;
1951
+ }
1952
+ const option = findSelectConfigOption({
1953
+ configOptions: this.configOptions,
1954
+ category: "thought_level",
1955
+ });
1956
+ if (!option) {
1957
+ throw new Error(`${this.provider} does not expose ACP thought-level selection`);
1958
+ }
1959
+ const response = await this.connection.setSessionConfigOption({
1960
+ sessionId: this.sessionId,
1961
+ configId: option.id,
1962
+ value: thinkingOptionId,
1963
+ });
1964
+ this.thinkingOptionId = this.applyConfigOptionResponse({
1965
+ response,
1966
+ configId: option.id,
1967
+ category: "thought_level",
1968
+ requestedValue: thinkingOptionId,
1969
+ label: "thought-level",
1970
+ });
1971
+ this.pushEvent({
1972
+ type: "thinking_option_changed",
1973
+ provider: this.provider,
1974
+ thinkingOptionId: this.thinkingOptionId,
1975
+ });
1976
+ }
1977
+ async setFeature(featureId, value) {
1978
+ if (!this.connection || !this.sessionId) {
1979
+ throw new Error("ACP session not initialized");
1980
+ }
1981
+ if (featureId === ACP_AUTO_ACCEPT_FEATURE_ID) {
1982
+ this.config.featureValues = {
1983
+ ...this.config.featureValues,
1984
+ [ACP_AUTO_ACCEPT_FEATURE_ID]: value === true,
1985
+ };
1986
+ return;
1987
+ }
1988
+ const featureOption = this.configFeatureOptions.find((option) => option.id === featureId);
1989
+ if (!featureOption) {
1990
+ throw new Error(`Unknown ${this.provider} feature: ${featureId}`);
1991
+ }
1992
+ const option = findSelectConfigFeatureOption(this.configOptions, featureOption);
1993
+ if (!option) {
1994
+ throw new Error(`${this.provider} does not expose ACP feature '${featureId}'`);
1995
+ }
1996
+ const requestedValue = normalizeConfigFeatureValue(value);
1997
+ const choice = findSelectConfigChoice({ option, value: requestedValue });
1998
+ if (!choice) {
1999
+ throw new Error(`${this.provider} feature '${featureId}' does not include option '${requestedValue}'`);
2000
+ }
2001
+ const response = await this.connection.setSessionConfigOption({
2002
+ sessionId: this.sessionId,
2003
+ configId: option.id,
2004
+ value: requestedValue,
2005
+ });
2006
+ const currentValue = this.applyConfigOptionResponse({
2007
+ response,
2008
+ configId: option.id,
2009
+ category: featureOption.category,
2010
+ requestedValue,
2011
+ label: featureOption.label,
2012
+ });
2013
+ this.config.featureValues = { ...this.config.featureValues, [featureId]: currentValue };
2014
+ }
2015
+ applyConfigOptionResponse({ response, configId, category, requestedValue, label, }) {
2016
+ this.configOptions = this.transformConfigOptions(response.configOptions);
2017
+ const responseOption = category === undefined
2018
+ ? findSelectConfigOptionById({ configOptions: this.configOptions, id: configId })
2019
+ : findSelectConfigOption({
2020
+ configOptions: this.configOptions,
2021
+ category,
2022
+ id: configId,
2023
+ });
2024
+ if (responseOption?.currentValue != null) {
2025
+ return responseOption.currentValue;
2026
+ }
2027
+ this.logger.warn({ configId, value: requestedValue }, `ACP setSessionConfigOption response did not include the requested ${label} option currentValue; using requested value`);
2028
+ return requestedValue;
2029
+ }
2030
+ getPendingPermissions() {
2031
+ return Array.from(this.pendingPermissions.values(), (entry) => entry.request);
2032
+ }
2033
+ async respondToPermission(requestId, response) {
2034
+ const pending = this.pendingPermissions.get(requestId);
2035
+ if (!pending) {
2036
+ throw new Error(`No pending permission request with id '${requestId}'`);
2037
+ }
2038
+ const selectedOption = selectPermissionOption(pending.options, response);
2039
+ if (response.selectedActionId !== undefined && !selectedOption) {
2040
+ throw new Error(`ACP permission action '${response.selectedActionId}' does not exist or does not match '${response.behavior}' behavior`);
2041
+ }
2042
+ this.pendingPermissions.delete(requestId);
2043
+ pending.resolve(selectedOption
2044
+ ? {
2045
+ outcome: {
2046
+ outcome: "selected",
2047
+ optionId: selectedOption.optionId,
2048
+ },
2049
+ }
2050
+ : { outcome: { outcome: "cancelled" } });
2051
+ this.pushEvent({
2052
+ type: "permission_resolved",
2053
+ provider: this.provider,
2054
+ requestId,
2055
+ resolution: response,
2056
+ turnId: pending.turnId ?? undefined,
2057
+ });
2058
+ // A denied prompt is stopped through the same boundary as Stop: the boundary
2059
+ // closes admission before the cancellation write, so no replacement can
2060
+ // cross the denied turn before its terminal and cancellation are settled.
2061
+ if (response.behavior === "deny" && response.interrupt) {
2062
+ await this.stopTurnOnPermissionDenial({
2063
+ permissionRequestId: requestId,
2064
+ ...(pending.turnId ? { turnId: pending.turnId } : {}),
2065
+ });
2066
+ }
2067
+ }
2068
+ /**
2069
+ * Routes a deny+interrupt by stop kind. The generic router knows two kinds: a
2070
+ * foreground turn gets the ordinary foreground stop plus its cancellation
2071
+ * ledger, and no stop-able turn suppresses the write with an observable log.
2072
+ * A subclass with another stop kind overrides this; the base deliberately
2073
+ * carries no subclass-specific stop identity or routing knowledge.
2074
+ */
2075
+ async stopTurnOnPermissionDenial(correlation) {
2076
+ await this.stopForegroundTurn({ reason: "permission-denied", correlation });
2077
+ }
2078
+ describePersistence() {
2079
+ if (!this.sessionId) {
2080
+ return null;
2081
+ }
2082
+ return {
2083
+ provider: this.provider,
2084
+ sessionId: this.sessionId,
2085
+ nativeHandle: this.sessionId,
2086
+ metadata: {
2087
+ ...this.config,
2088
+ title: this.currentTitle,
2089
+ },
2090
+ };
2091
+ }
2092
+ /**
2093
+ * Cancels the current foreground turn through the stop boundary. Returning
2094
+ * means the cancellation notification write settled — nothing more. It does not
2095
+ * clear the stop, does not terminalize the turn, and does not make the session
2096
+ * ready for a replacement.
2097
+ */
2098
+ async interrupt() {
2099
+ for (const pending of this.pendingPermissions.values()) {
2100
+ pending.resolve({ outcome: { outcome: "cancelled" } });
2101
+ }
2102
+ this.pendingPermissions.clear();
2103
+ await this.stopForegroundTurn({ reason: "interrupt" });
2104
+ }
2105
+ async close() {
2106
+ if (this.closed) {
2107
+ return;
2108
+ }
2109
+ // Marked closed before any asynchronous teardown: from here no new
2110
+ // reservation is possible and no late settlement, control result, phase
2111
+ // update, or terminal can touch admission state again.
2112
+ this.closed = true;
2113
+ const stop = this.stop;
2114
+ if (stop) {
2115
+ // One death path: the record being dropped settles exactly like an
2116
+ // observed death. The staged successor keeps its "closed" rejection, and
2117
+ // the closed ledger can no longer be reopened by a late settlement.
2118
+ this.settleStopOnObservedDeath("closed");
2119
+ }
2120
+ this.stop = null;
2121
+ this.admissionState = "idle";
2122
+ this.deliverTranslatedEvents(this.flushPendingUserMessage());
2123
+ this.settleCommandsReady();
2124
+ for (const pending of this.pendingPermissions.values()) {
2125
+ pending.resolve({ outcome: { outcome: "cancelled" } });
2126
+ }
2127
+ this.pendingPermissions.clear();
2128
+ if (this.connection && this.sessionId) {
2129
+ try {
2130
+ if (this.activeForegroundTurnId) {
2131
+ await this.connection.cancel({ sessionId: this.sessionId });
2132
+ }
2133
+ }
2134
+ catch { }
2135
+ try {
2136
+ if (this.agentCapabilities?.sessionCapabilities?.close) {
2137
+ await this.connection.unstable_closeSession({ sessionId: this.sessionId });
2138
+ }
2139
+ }
2140
+ catch (error) {
2141
+ this.logger.debug({ err: error }, "ACP closeSession failed during shutdown");
2142
+ }
2143
+ }
2144
+ const terminalTerminations = Array.from(this.terminalEntries.values(), (terminal) => this.terminateProcess(terminal.child, {
2145
+ gracefulTimeoutMs: 2000,
2146
+ forceTimeoutMs: 2000,
2147
+ }));
2148
+ await Promise.all(terminalTerminations);
2149
+ this.terminalEntries.clear();
2150
+ if (this.child) {
2151
+ await this.terminateProcess(this.child, { gracefulTimeoutMs: 2000, forceTimeoutMs: 2000 });
2152
+ }
2153
+ this.subscribers.clear();
2154
+ this.connection = null;
2155
+ this.child = null;
2156
+ this.activeForegroundTurnId = null;
2157
+ }
2158
+ async requestPermission(params) {
2159
+ const canAutoAccept = isACPAutoAcceptEnabled(this.config) && !isACPChooserRequest(params.options);
2160
+ if (canAutoAccept) {
2161
+ const allowOption = selectPermissionOption(params.options, { behavior: "allow" });
2162
+ if (allowOption) {
2163
+ this.logger.info({ toolCallId: params.toolCall.toolCallId, optionId: allowOption.optionId }, "Auto-accepting ACP permission request");
2164
+ return {
2165
+ outcome: { outcome: "selected", optionId: allowOption.optionId },
2166
+ };
2167
+ }
2168
+ }
2169
+ // Match Zed acp.rs:3189-3220 when Paseo is not handling the request locally.
2170
+ const requestId = randomUUID();
2171
+ let toolSnapshot = this.toolCalls.get(params.toolCall.toolCallId) ??
2172
+ mergeToolSnapshot(params.toolCall.toolCallId, params.toolCall);
2173
+ if (this.toolSnapshotTransformer) {
2174
+ toolSnapshot = this.toolSnapshotTransformer(toolSnapshot);
2175
+ }
2176
+ const request = mapPermissionRequest(this.provider, requestId, params, toolSnapshot);
2177
+ const promise = new Promise((resolve, reject) => {
2178
+ this.pendingPermissions.set(requestId, {
2179
+ request,
2180
+ options: params.options,
2181
+ resolve,
2182
+ reject,
2183
+ turnId: this.activeForegroundTurnId,
2184
+ });
2185
+ });
2186
+ this.pushEvent({
2187
+ type: "permission_requested",
2188
+ provider: this.provider,
2189
+ request,
2190
+ turnId: this.activeForegroundTurnId ?? undefined,
2191
+ });
2192
+ return promise;
2193
+ }
2194
+ async sessionUpdate(params) {
2195
+ this.logger.trace({
2196
+ agentId: this.agentId,
2197
+ provider: this.provider,
2198
+ sessionId: params.sessionId,
2199
+ rawEvent: params,
2200
+ }, "provider.acp.raw_event");
2201
+ if (params.sessionId !== this.sessionId) {
2202
+ return;
2203
+ }
2204
+ const events = this.translateSessionUpdate(params.update);
2205
+ this.logger.trace({
2206
+ agentId: this.agentId,
2207
+ provider: this.provider,
2208
+ sessionId: this.sessionId,
2209
+ turnId: this.activeForegroundTurnId ?? undefined,
2210
+ rawEvent: params,
2211
+ events,
2212
+ }, "provider.acp.parsed_event");
2213
+ this.deliverTranslatedEvents(events);
2214
+ }
2215
+ deliverTranslatedEvents(events) {
2216
+ if (this.replayingHistory) {
2217
+ for (const event of events) {
2218
+ if (event.type === "timeline") {
2219
+ this.persistedHistory.push(event.item);
2220
+ }
2221
+ }
2222
+ return;
2223
+ }
2224
+ for (const event of events) {
2225
+ this.pushEvent(event);
2226
+ }
2227
+ }
2228
+ async extNotification(method, params) {
2229
+ this.logger.trace({
2230
+ agentId: this.agentId,
2231
+ provider: this.provider,
2232
+ sessionId: typeof params.sessionId === "string" ? params.sessionId : undefined,
2233
+ method,
2234
+ rawEvent: params,
2235
+ }, "provider.acp.extension_notification");
2236
+ const parsedCommands = this.extensionCommandsParser?.(method, params);
2237
+ if (parsedCommands) {
2238
+ this.applyResolvedCommands(parsedCommands, {
2239
+ sessionId: typeof params.sessionId === "string" ? params.sessionId : undefined,
2240
+ });
2241
+ }
2242
+ }
2243
+ // Cache an asynchronously-delivered slash-command batch and unblock any
2244
+ // listCommands() call that is waiting on the initial batch. Used when a
2245
+ // provider supplies an extensionCommandsParser whose result arrives after
2246
+ // session/new (e.g. via a vendor extension notification). The ready gate is
2247
+ // always settled — even for an empty batch — so a provider that legitimately
2248
+ // reports no commands does not leave listCommands() blocked for the full
2249
+ // initial-commands timeout. An optional sessionId scopes the batch to this
2250
+ // session; notifications addressed to a different session are ignored.
2251
+ applyResolvedCommands(commands, options) {
2252
+ if (options?.sessionId !== undefined &&
2253
+ this.sessionId !== null &&
2254
+ options.sessionId !== this.sessionId) {
2255
+ return;
2256
+ }
2257
+ if (commands.length > 0) {
2258
+ this.cachedCommands = commands;
2259
+ }
2260
+ this.settleCommandsReady();
2261
+ }
2262
+ async readTextFile(params) {
2263
+ const raw = await fs.readFile(params.path, "utf8");
2264
+ if (!params.line && !params.limit) {
2265
+ return { content: raw };
2266
+ }
2267
+ const lines = raw.split(/\r?\n/);
2268
+ const start = Math.max((params.line ?? 1) - 1, 0);
2269
+ const end = params.limit ? start + params.limit : undefined;
2270
+ return { content: lines.slice(start, end).join("\n") };
2271
+ }
2272
+ async writeTextFile(params) {
2273
+ await fs.mkdir(path.dirname(params.path), { recursive: true });
2274
+ await fs.writeFile(params.path, params.content, "utf8");
2275
+ return {};
2276
+ }
2277
+ async createTerminal(params) {
2278
+ const terminalId = randomUUID();
2279
+ const env = Object.fromEntries((params.env ?? []).map((entry) => [entry.name, entry.value]));
2280
+ const terminalCommand = resolveTerminalCommand(params.command, params.args);
2281
+ const commandEnvOverlays = terminalCommand.shell === false ? [env, createStringCommandShellEnvOverlay()] : [env];
2282
+ const child = spawnProcess(terminalCommand.command, terminalCommand.args, {
2283
+ cwd: params.cwd ?? this.config.cwd,
2284
+ ...createProviderEnvSpec({
2285
+ runtimeSettings: this.runtimeSettings,
2286
+ overlays: commandEnvOverlays,
2287
+ }),
2288
+ shell: terminalCommand.shell,
2289
+ stdio: ["ignore", "pipe", "pipe"],
2290
+ });
2291
+ let resolveExit;
2292
+ let rejectExit;
2293
+ const waitForExit = new Promise((resolve, reject) => {
2294
+ resolveExit = resolve;
2295
+ rejectExit = reject;
2296
+ });
2297
+ waitForExit.catch(() => undefined);
2298
+ const entry = {
2299
+ id: terminalId,
2300
+ child,
2301
+ output: "",
2302
+ truncated: false,
2303
+ outputByteLimit: params.outputByteLimit ?? null,
2304
+ exit: null,
2305
+ waitForExit,
2306
+ resolveExit,
2307
+ rejectExit,
2308
+ };
2309
+ child.stdout.on("data", (chunk) => appendTerminalOutput(entry, chunk.toString()));
2310
+ child.stderr.on("data", (chunk) => appendTerminalOutput(entry, chunk.toString()));
2311
+ child.once("error", (error) => {
2312
+ const spawnError = error instanceof Error ? error : new Error(String(error));
2313
+ appendTerminalOutput(entry, `${spawnError.message}\n`);
2314
+ rejectExit(spawnError);
2315
+ });
2316
+ child.once("exit", (code, signal) => {
2317
+ const exit = { exitCode: code, signal };
2318
+ entry.exit = exit;
2319
+ resolveExit(exit);
2320
+ });
2321
+ this.terminalEntries.set(terminalId, entry);
2322
+ return { terminalId };
2323
+ }
2324
+ async terminalOutput(params) {
2325
+ const entry = this.getTerminalEntry(params.terminalId);
2326
+ return {
2327
+ output: entry.output,
2328
+ truncated: entry.truncated,
2329
+ exitStatus: entry.exit ?? undefined,
2330
+ };
2331
+ }
2332
+ async waitForTerminalExit(params) {
2333
+ const entry = this.getTerminalEntry(params.terminalId);
2334
+ return entry.waitForExit;
2335
+ }
2336
+ async releaseTerminal(params) {
2337
+ const entry = this.getTerminalEntry(params.terminalId);
2338
+ if (!entry.exit) {
2339
+ await this.terminateProcess(entry.child, { gracefulTimeoutMs: 2000, forceTimeoutMs: 2000 });
2340
+ }
2341
+ this.terminalEntries.delete(params.terminalId);
2342
+ }
2343
+ async killTerminal(params) {
2344
+ const entry = this.getTerminalEntry(params.terminalId);
2345
+ if (!entry.exit) {
2346
+ await this.terminateProcess(entry.child, { gracefulTimeoutMs: 2000, forceTimeoutMs: 2000 });
2347
+ }
2348
+ return {};
2349
+ }
2350
+ /**
2351
+ * Subscribes the one death path to the connection's close signal, covering
2352
+ * transport death that no process exit event reports. The SDK aborts
2353
+ * `signal` when the connection's stream ends; test connections without one,
2354
+ * and already-subscribed signals, are skipped.
2355
+ */
2356
+ observeConnectionDeath(connection) {
2357
+ const signal = connection.signal;
2358
+ if (!(signal instanceof AbortSignal) || this.connectionDeathSignal === signal) {
2359
+ return;
2360
+ }
2361
+ this.connectionDeathSignal = signal;
2362
+ signal.addEventListener("abort", () => {
2363
+ // A replaced connection's signal says nothing about the live one.
2364
+ if (this.closed || this.connection !== connection) {
2365
+ return;
2366
+ }
2367
+ this.settleStopOnObservedDeath("connection-aborted");
2368
+ }, { once: true });
2369
+ }
2370
+ async spawnProcess() {
2371
+ const prefix = await resolveProviderLaunch({
2372
+ commandConfig: this.runtimeSettings?.command,
2373
+ defaultBinary: this.defaultCommand[0],
2374
+ });
2375
+ const availability = await checkProviderLaunchAvailable(prefix);
2376
+ if (!availability.available) {
2377
+ throw new Error(`${this.provider} command '${this.defaultCommand[0]}' not found`);
2378
+ }
2379
+ const command = prefix.command;
2380
+ const args = [...prefix.args, ...this.defaultCommand.slice(1)];
2381
+ const child = spawnProcess(command, args, {
2382
+ cwd: this.config.cwd,
2383
+ ...createProviderEnvSpec({
2384
+ runtimeSettings: this.runtimeSettings,
2385
+ overlays: [this.launchEnv],
2386
+ }),
2387
+ stdio: ["pipe", "pipe", "pipe"],
2388
+ });
2389
+ assertChildWithPipes(child);
2390
+ const stderrChunks = [];
2391
+ child.stderr.on("data", (chunk) => {
2392
+ stderrChunks.push(chunk.toString());
2393
+ });
2394
+ child.once("exit", (code, signal) => {
2395
+ if (this.closed) {
2396
+ return;
2397
+ }
2398
+ const foregroundTurnId = this.activeForegroundTurnId;
2399
+ if (foregroundTurnId) {
2400
+ this.synthesizeCanceledToolCalls();
2401
+ this.finishTurn(foregroundTurnId, {
2402
+ type: "turn_failed",
2403
+ provider: this.provider,
2404
+ error: `ACP agent exited unexpectedly (${code ?? "null"}${signal ? `, ${signal}` : ""})`,
2405
+ diagnostic: stderrChunks.join("").trim() || undefined,
2406
+ turnId: foregroundTurnId,
2407
+ });
2408
+ }
2409
+ // Terminal first, then settlement: the death path runs after the
2410
+ // synthesized foreground terminal, and also runs when there is none (an
2411
+ // ownerless stop has no foreground turn to terminalize).
2412
+ this.settleStopOnObservedDeath("agent-exited");
2413
+ });
2414
+ const stream = createLoggedNdJsonStream(Writable.toWeb(child.stdin), Readable.toWeb(child.stdout), { logger: this.logger, provider: this.provider });
2415
+ const connection = new ClientSideConnection(() => this, stream);
2416
+ // Take ownership before initialize so the outer initialization guard can
2417
+ // close the process even when the ACP handshake itself rejects. The revision
2418
+ // identifies this connection: stop boundaries capture it at install so a
2419
+ // replacement connection can never be opened by an older stop's writes.
2420
+ this.child = child;
2421
+ this.connection = connection;
2422
+ this.connectionRevision += 1;
2423
+ this.observeConnectionDeath(connection);
2424
+ const initialize = await this.runACPRequest(() => connection.initialize({
2425
+ protocolVersion: PROTOCOL_VERSION,
2426
+ clientCapabilities: buildACPClientCapabilities(this.clientCapabilityMeta, this.clientCapabilities),
2427
+ clientInfo: { name: "Paseo", version: "dev" },
2428
+ }));
2429
+ return { child, connection, initialize };
2430
+ }
2431
+ async runACPRequest(request) {
2432
+ try {
2433
+ return await request();
2434
+ }
2435
+ catch (error) {
2436
+ throw toACPRequestError(error);
2437
+ }
2438
+ }
2439
+ acpMcpServers() {
2440
+ return this.capabilities.supportsMcpServers ? normalizeMcpServers(this.config.mcpServers) : [];
2441
+ }
2442
+ applySessionState(response) {
2443
+ const transformed = this.sessionResponseTransformer
2444
+ ? this.sessionResponseTransformer(response)
2445
+ : response;
2446
+ this.configOptions = this.transformConfigOptions(transformed.configOptions ?? []);
2447
+ const modeInfo = deriveModesFromACP(this.defaultModes, transformed.modes, this.configOptions);
2448
+ this.availableModes = modeInfo.modes;
2449
+ this.currentMode = modeInfo.currentModeId ?? this.currentMode;
2450
+ this.availableModels = transformed.models?.availableModels ?? null;
2451
+ this.currentModel =
2452
+ transformed.models?.currentModelId ?? deriveCurrentConfigValue(this.configOptions, "model");
2453
+ this.thinkingOptionId =
2454
+ deriveCurrentConfigValue(this.configOptions, "thought_level") ?? this.thinkingOptionId;
2455
+ }
2456
+ transformConfigOptions(configOptions) {
2457
+ return this.configOptionsTransformer
2458
+ ? this.configOptionsTransformer(configOptions)
2459
+ : configOptions;
2460
+ }
2461
+ transformModeId(modeId) {
2462
+ return this.modeIdTransformer ? this.modeIdTransformer(modeId) : modeId;
2463
+ }
2464
+ async applyConfiguredOverrides() {
2465
+ const configuredModeId = this.config.modeId;
2466
+ if (configuredModeId && configuredModeId !== this.currentMode) {
2467
+ const selection = resolveACPModeSelection({
2468
+ modeId: configuredModeId,
2469
+ availableModes: this.availableModes,
2470
+ configOptions: this.configOptions,
2471
+ });
2472
+ await this.setModeWithSelection({ modeId: configuredModeId, selection });
2473
+ }
2474
+ const configuredModelId = this.config.model;
2475
+ if (configuredModelId && configuredModelId !== this.currentModel) {
2476
+ const selection = resolveACPModelSelection({
2477
+ modelId: configuredModelId,
2478
+ availableModels: this.availableModels,
2479
+ configOptions: this.configOptions,
2480
+ });
2481
+ try {
2482
+ await this.setModelWithSelection({ modelId: configuredModelId, selection });
2483
+ }
2484
+ catch (error) {
2485
+ if (!this.isModelSelectionUnavailableError(error)) {
2486
+ throw error;
2487
+ }
2488
+ this.logger.warn({ value: configuredModelId }, `${this.provider} does not expose ACP model selection; using provider default model`);
2489
+ }
2490
+ }
2491
+ if (this.config.thinkingOptionId && this.config.thinkingOptionId !== this.thinkingOptionId) {
2492
+ await this.setThinkingOption(this.config.thinkingOptionId);
2493
+ }
2494
+ const configuredFeatureValues = this.config.featureValues ?? {};
2495
+ for (const featureOption of this.configFeatureOptions) {
2496
+ if (!Object.prototype.hasOwnProperty.call(configuredFeatureValues, featureOption.id)) {
2497
+ continue;
2498
+ }
2499
+ await this.setFeature(featureOption.id, configuredFeatureValues[featureOption.id]);
2500
+ }
2501
+ }
2502
+ warnInvalidSelection(value, message) {
2503
+ this.logger.warn({ value }, message);
2504
+ }
2505
+ modelSelectionUnavailableMessage() {
2506
+ return `${this.provider} does not expose ACP model selection`;
2507
+ }
2508
+ isModelSelectionUnavailableError(error) {
2509
+ return error instanceof Error && error.message === this.modelSelectionUnavailableMessage();
2510
+ }
2511
+ translateSessionUpdate(update) {
2512
+ if (update.sessionUpdate === "user_message_chunk") {
2513
+ return this.handleUserMessageChunk(update);
2514
+ }
2515
+ const pendingUserEvents = this.flushPendingUserMessage();
2516
+ switch (update.sessionUpdate) {
2517
+ case "agent_message_chunk": {
2518
+ const item = this.createMessageTimelineItem("assistant_message", update);
2519
+ return item ? [...pendingUserEvents, this.wrapTimeline(item)] : pendingUserEvents;
2520
+ }
2521
+ case "agent_thought_chunk": {
2522
+ this.fallbackAssistantMessageId = null;
2523
+ const item = this.createMessageTimelineItem("reasoning", update);
2524
+ return item ? [...pendingUserEvents, this.wrapTimeline(item)] : pendingUserEvents;
2525
+ }
2526
+ case "tool_call":
2527
+ this.fallbackAssistantMessageId = null;
2528
+ return [
2529
+ ...pendingUserEvents,
2530
+ ...this.handleToolCallUpdate(update.toolCallId, update, undefined),
2531
+ ];
2532
+ case "tool_call_update":
2533
+ return [
2534
+ ...pendingUserEvents,
2535
+ ...this.handleToolCallUpdate(update.toolCallId, update, this.toolCalls.get(update.toolCallId)),
2536
+ ];
2537
+ case "plan":
2538
+ this.fallbackAssistantMessageId = null;
2539
+ return [...pendingUserEvents, this.wrapTimeline(mapPlanToTimeline(update))];
2540
+ case "current_mode_update":
2541
+ this.handleCurrentModeUpdate(update);
2542
+ return [
2543
+ ...pendingUserEvents,
2544
+ {
2545
+ type: "mode_changed",
2546
+ provider: this.provider,
2547
+ currentModeId: this.currentMode,
2548
+ availableModes: [...this.availableModes],
2549
+ },
2550
+ ];
2551
+ case "config_option_update":
2552
+ return [...pendingUserEvents, ...this.handleConfigOptionUpdate(update)];
2553
+ case "session_info_update":
2554
+ this.handleSessionInfoUpdate(update);
2555
+ return pendingUserEvents;
2556
+ case "usage_update":
2557
+ this.handleUsageUpdate(update);
2558
+ return pendingUserEvents;
2559
+ case "available_commands_update":
2560
+ this.cachedCommands = update.availableCommands.map((command) => ({
2561
+ name: command.name,
2562
+ description: command.description,
2563
+ argumentHint: command.input?.hint ?? "",
2564
+ kind: "command",
2565
+ }));
2566
+ this.settleCommandsReady();
2567
+ return pendingUserEvents;
2568
+ default:
2569
+ return pendingUserEvents;
2570
+ }
2571
+ }
2572
+ handleUserMessageChunk(update) {
2573
+ this.fallbackAssistantMessageId = null;
2574
+ if (this.activeForegroundTurnId &&
2575
+ this.submittedUserMessageTurnId === this.activeForegroundTurnId) {
2576
+ return [];
2577
+ }
2578
+ const chunkText = contentBlockToText(update.content);
2579
+ if (!chunkText) {
2580
+ return [];
2581
+ }
2582
+ const messageId = update.messageId ?? undefined;
2583
+ const pending = this.pendingUserMessage;
2584
+ const startsNewMessage = Boolean(pending?.messageId && messageId && pending.messageId !== messageId);
2585
+ const events = startsNewMessage ? this.flushPendingUserMessage() : [];
2586
+ this.pendingUserMessage ?? (this.pendingUserMessage = {
2587
+ text: "",
2588
+ ...(messageId ? { messageId } : {}),
2589
+ });
2590
+ if (!this.pendingUserMessage.messageId && messageId) {
2591
+ this.pendingUserMessage.messageId = messageId;
2592
+ }
2593
+ this.pendingUserMessage.text += chunkText;
2594
+ return events;
2595
+ }
2596
+ flushPendingUserMessage() {
2597
+ const pending = this.pendingUserMessage;
2598
+ if (!pending) {
2599
+ return [];
2600
+ }
2601
+ this.pendingUserMessage = null;
2602
+ return [
2603
+ this.wrapTimeline({
2604
+ type: "user_message",
2605
+ text: pending.text,
2606
+ ...(pending.messageId ? { messageId: pending.messageId } : {}),
2607
+ }),
2608
+ ];
2609
+ }
2610
+ handleToolCallUpdate(toolCallId, update, previous) {
2611
+ let snapshot = mergeToolSnapshot(toolCallId, update, previous);
2612
+ if (this.toolSnapshotTransformer) {
2613
+ snapshot = this.toolSnapshotTransformer(snapshot);
2614
+ }
2615
+ this.toolCalls.set(toolCallId, snapshot);
2616
+ return [this.wrapTimeline(mapToolSnapshotToTimeline(snapshot, this.terminalEntries))];
2617
+ }
2618
+ createMessageTimelineItem(type, update) {
2619
+ const chunkText = contentBlockToText(update.content);
2620
+ if (!chunkText) {
2621
+ return null;
2622
+ }
2623
+ if (type === "assistant_message") {
2624
+ return {
2625
+ type: "assistant_message",
2626
+ text: chunkText,
2627
+ messageId: this.resolveAssistantMessageId(update.messageId),
2628
+ };
2629
+ }
2630
+ return { type: "reasoning", text: chunkText };
2631
+ }
2632
+ resolveAssistantMessageId(messageId) {
2633
+ if (messageId) {
2634
+ this.fallbackAssistantMessageId = null;
2635
+ return messageId;
2636
+ }
2637
+ this.fallbackAssistantMessageId ?? (this.fallbackAssistantMessageId = randomUUID());
2638
+ return this.fallbackAssistantMessageId;
2639
+ }
2640
+ handleCurrentModeUpdate(update) {
2641
+ this.currentMode = this.transformModeId(update.currentModeId);
2642
+ }
2643
+ handleConfigOptionUpdate(update) {
2644
+ this.configOptions = this.transformConfigOptions(update.configOptions);
2645
+ const modeInfo = deriveModesFromACP(this.defaultModes, null, this.configOptions);
2646
+ const nextMode = modeInfo.currentModeId;
2647
+ const nextModel = deriveCurrentConfigValue(this.configOptions, "model");
2648
+ const nextThinkingOptionId = deriveCurrentConfigValue(this.configOptions, "thought_level");
2649
+ this.availableModes = modeInfo.modes;
2650
+ this.currentMode = nextMode ?? this.currentMode;
2651
+ this.currentModel = nextModel ?? this.currentModel;
2652
+ this.thinkingOptionId = nextThinkingOptionId ?? this.thinkingOptionId;
2653
+ const events = [];
2654
+ if (nextMode !== null) {
2655
+ events.push({
2656
+ type: "mode_changed",
2657
+ provider: this.provider,
2658
+ currentModeId: this.currentMode,
2659
+ availableModes: [...this.availableModes],
2660
+ });
2661
+ }
2662
+ if (nextModel !== null) {
2663
+ events.push({
2664
+ type: "model_changed",
2665
+ provider: this.provider,
2666
+ runtimeInfo: this.runtimeInfo(),
2667
+ });
2668
+ }
2669
+ if (nextThinkingOptionId !== null) {
2670
+ events.push({
2671
+ type: "thinking_option_changed",
2672
+ provider: this.provider,
2673
+ thinkingOptionId: this.thinkingOptionId,
2674
+ });
2675
+ }
2676
+ return events;
2677
+ }
2678
+ handleSessionInfoUpdate(update) {
2679
+ if ("title" in update) {
2680
+ this.currentTitle = update.title ?? null;
2681
+ }
2682
+ if ("updatedAt" in update) {
2683
+ this.lastActivityAt = update.updatedAt ?? null;
2684
+ }
2685
+ }
2686
+ handleUsageUpdate(update) {
2687
+ void update;
2688
+ }
2689
+ handlePromptResponse(response, turnId) {
2690
+ this.currentTurnUsage = mapACPUsage(response.usage) ?? this.currentTurnUsage;
2691
+ switch (response.stopReason) {
2692
+ case "cancelled":
2693
+ this.synthesizeCanceledToolCalls();
2694
+ this.finishTurn(turnId, {
2695
+ type: "turn_canceled",
2696
+ provider: this.provider,
2697
+ reason: "Interrupted",
2698
+ turnId,
2699
+ });
2700
+ break;
2701
+ case "end_turn":
2702
+ case "max_tokens":
2703
+ case "max_turn_requests":
2704
+ case "refusal":
2705
+ default:
2706
+ this.finishTurn(turnId, {
2707
+ type: "turn_completed",
2708
+ provider: this.provider,
2709
+ usage: this.currentTurnUsage,
2710
+ turnId,
2711
+ });
2712
+ break;
2713
+ }
2714
+ }
2715
+ wrapTimeline(item) {
2716
+ return {
2717
+ type: "timeline",
2718
+ provider: this.provider,
2719
+ item,
2720
+ turnId: this.activeForegroundTurnId ?? undefined,
2721
+ };
2722
+ }
2723
+ pushEvent(event) {
2724
+ this.logger.trace({
2725
+ agentId: this.agentId,
2726
+ provider: this.provider,
2727
+ sessionId: this.sessionId,
2728
+ turnId: getAgentStreamEventTurnId(event) ?? this.activeForegroundTurnId ?? undefined,
2729
+ event,
2730
+ }, "provider.acp.event_emit");
2731
+ for (const subscriber of this.subscribers) {
2732
+ subscriber(event);
2733
+ }
2734
+ }
2735
+ emitSubmittedUserMessage(prompt, messageId, turnId, clientMessageId) {
2736
+ const text = extractPromptText(prompt);
2737
+ if (text.trim().length === 0) {
2738
+ return;
2739
+ }
2740
+ this.submittedUserMessageTurnId = turnId;
2741
+ this.pushEvent({
2742
+ type: "timeline",
2743
+ provider: this.provider,
2744
+ turnId,
2745
+ item: {
2746
+ type: "user_message",
2747
+ text,
2748
+ messageId,
2749
+ ...(clientMessageId ? { clientMessageId } : {}),
2750
+ },
2751
+ });
2752
+ }
2753
+ runtimeInfo() {
2754
+ return {
2755
+ provider: this.provider,
2756
+ sessionId: this.sessionId,
2757
+ model: this.currentModel,
2758
+ thinkingOptionId: this.thinkingOptionId,
2759
+ modeId: this.currentMode,
2760
+ extra: {
2761
+ title: this.currentTitle,
2762
+ updatedAt: this.lastActivityAt,
2763
+ },
2764
+ };
2765
+ }
2766
+ /**
2767
+ * Settles a foreground turn. `turnId` is checked against live state before
2768
+ * anything moves:
2769
+ *
2770
+ * - the stopped turn of the installed boundary records terminal proof (once)
2771
+ * and releases the gate, without leaving the stopping phase while
2772
+ * cancellation writes are still unresolved or failed;
2773
+ * - the current foreground turn settles ordinarily and hands the slot back;
2774
+ * - anything else is a terminal from an earlier generation and is dropped
2775
+ * instead of clearing a reserved or running successor.
2776
+ *
2777
+ * After close nothing is emitted and no state moves.
2778
+ */
2779
+ finishTurn(turnId, event) {
2780
+ if (this.closed) {
2781
+ return;
2782
+ }
2783
+ const stop = this.stop;
2784
+ if (stop && turnId === stop.stoppedTurnId) {
2785
+ if (!this.stopIdentityMatches(stop)) {
2786
+ this.logger.warn({ stopId: stop.stopId, turnId, sessionId: stop.sessionId }, "Ignored ACP terminal for the stopped turn: session identity changed");
2787
+ return;
2788
+ }
2789
+ stop.terminalObserved = true;
2790
+ this.logger.info({ stopId: stop.stopId, turnId, kind: stop.kind }, "provider.acp.stop_terminal_observed");
2791
+ if (!stop.terminalDelivered) {
2792
+ stop.terminalDelivered = true;
2793
+ this.deliverTerminal(event);
2794
+ }
2795
+ this.evaluateStopGate(stop);
2796
+ return;
2797
+ }
2798
+ if (turnId !== this.activeForegroundTurnId) {
2799
+ this.logger.warn({ turnId, activeTurnId: this.activeForegroundTurnId ?? undefined }, "Ignored ACP terminal for a turn that no longer owns the foreground");
2800
+ return;
2801
+ }
2802
+ this.deliverTerminal(event);
2803
+ this.activeForegroundTurnId = null;
2804
+ this.admissionState = "idle";
2805
+ }
2806
+ /** Emits a terminal event once, after the buffered provider echo is flushed. */
2807
+ deliverTerminal(event) {
2808
+ this.deliverTranslatedEvents(this.flushPendingUserMessage());
2809
+ this.fallbackAssistantMessageId = null;
2810
+ if (this.submittedUserMessageTurnId === event.turnId) {
2811
+ this.submittedUserMessageTurnId = null;
2812
+ }
2813
+ this.pushEvent(event);
2814
+ }
2815
+ emitBootstrapThreadEvent() {
2816
+ if (!this.bootstrapThreadEventPending || !this.sessionId) {
2817
+ return;
2818
+ }
2819
+ this.bootstrapThreadEventPending = false;
2820
+ this.pushEvent({
2821
+ type: "thread_started",
2822
+ provider: this.provider,
2823
+ sessionId: this.sessionId,
2824
+ });
2825
+ }
2826
+ synthesizeCanceledToolCalls() {
2827
+ for (const snapshot of this.toolCalls.values()) {
2828
+ const mapped = mapToolSnapshotToTimeline(snapshot, this.terminalEntries);
2829
+ if (mapped.status === "running") {
2830
+ this.pushEvent(this.wrapTimeline({
2831
+ ...mapped,
2832
+ status: "canceled",
2833
+ error: null,
2834
+ }));
2835
+ }
2836
+ }
2837
+ }
2838
+ collectDiagnostic(message) {
2839
+ const parts = [message];
2840
+ if (this.child?.exitCode != null) {
2841
+ parts.push(`exitCode=${this.child.exitCode}`);
2842
+ }
2843
+ if (this.child?.signalCode) {
2844
+ parts.push(`signal=${this.child.signalCode}`);
2845
+ }
2846
+ return parts.length > 0 ? parts.join(" | ") : undefined;
2847
+ }
2848
+ getTerminalEntry(terminalId) {
2849
+ const entry = this.terminalEntries.get(terminalId);
2850
+ if (!entry) {
2851
+ throw new Error(`Unknown terminal '${terminalId}'`);
2852
+ }
2853
+ return entry;
2854
+ }
2855
+ }
2856
+ export function findSelectConfigOption({ configOptions, category, id, }) {
2857
+ const option = configOptions?.find((entry) => entry.type === "select" && entry.category === category && (!id || entry.id === id));
2858
+ return option ?? null;
2859
+ }
2860
+ function findSelectConfigOptionById({ configOptions, id, }) {
2861
+ const option = configOptions?.find((entry) => entry.type === "select" && entry.id === id);
2862
+ return option ?? null;
2863
+ }
2864
+ function findSelectConfigFeatureOption(configOptions, featureOption) {
2865
+ const option = configOptions?.find((entry) => entry.type === "select" &&
2866
+ entry.id === featureOption.configId &&
2867
+ (featureOption.category === undefined || entry.category === featureOption.category));
2868
+ return option ?? null;
2869
+ }
2870
+ function findSelectConfigChoice({ option, value, }) {
2871
+ if (!option) {
2872
+ return null;
2873
+ }
2874
+ return flattenSelectOptions(option.options).find((choice) => choice.value === value) ?? null;
2875
+ }
2876
+ function flattenSelectOptions(options) {
2877
+ const flattened = [];
2878
+ for (const option of options) {
2879
+ if ("value" in option) {
2880
+ flattened.push(option);
2881
+ continue;
2882
+ }
2883
+ for (const groupOption of option.options) {
2884
+ flattened.push({ ...groupOption, group: option.group });
2885
+ }
2886
+ }
2887
+ return flattened;
2888
+ }
2889
+ function deriveConfigFeatureSelectOptions(option, featureOption) {
2890
+ return flattenSelectOptions(option.options).map((choice) => ({
2891
+ id: choice.value,
2892
+ label: normalizeConfigFeatureOptionLabel(choice, featureOption),
2893
+ description: choice.description ?? undefined,
2894
+ isDefault: choice.value === option.currentValue,
2895
+ metadata: choice.group ? { group: choice.group } : undefined,
2896
+ }));
2897
+ }
2898
+ function normalizeConfigFeatureOptionLabel(choice, featureOption) {
2899
+ const name = choice.name.trim();
2900
+ if (name) {
2901
+ return name;
2902
+ }
2903
+ if (choice.value === "" && featureOption.emptyOptionLabel) {
2904
+ return featureOption.emptyOptionLabel;
2905
+ }
2906
+ return choice.value;
2907
+ }
2908
+ function normalizeConfigFeatureValue(value) {
2909
+ if (typeof value === "string") {
2910
+ return value;
2911
+ }
2912
+ if (value === null) {
2913
+ return "";
2914
+ }
2915
+ throw new Error(`ACP feature value must be a string`);
2916
+ }
2917
+ export function deriveSelectorOptions(configOptions, category) {
2918
+ const option = findSelectConfigOption({ configOptions, category });
2919
+ if (!option) {
2920
+ return [];
2921
+ }
2922
+ return flattenSelectOptions(option.options).map((value) => ({
2923
+ id: value.value,
2924
+ label: value.name,
2925
+ description: value.description ?? undefined,
2926
+ isDefault: value.value === option.currentValue,
2927
+ metadata: value.group ? { group: value.group } : undefined,
2928
+ }));
2929
+ }
2930
+ function deriveCurrentConfigValue(configOptions, category) {
2931
+ const option = configOptions?.find((entry) => entry.type === "select" && entry.category === category);
2932
+ return option?.currentValue ?? null;
2933
+ }
2934
+ function normalizeMcpServers(servers) {
2935
+ if (!servers) {
2936
+ return [];
2937
+ }
2938
+ return Object.entries(servers).map(([name, config]) => {
2939
+ if (config.type === "stdio") {
2940
+ return {
2941
+ name,
2942
+ command: config.command,
2943
+ args: config.args ?? [],
2944
+ env: Object.entries(config.env ?? {}).map(([envName, value]) => ({
2945
+ name: envName,
2946
+ value,
2947
+ })),
2948
+ };
2949
+ }
2950
+ if (config.type === "http") {
2951
+ return {
2952
+ type: "http",
2953
+ name,
2954
+ url: config.url,
2955
+ headers: Object.entries(config.headers ?? {}).map(([headerName, value]) => ({
2956
+ name: headerName,
2957
+ value,
2958
+ })),
2959
+ };
2960
+ }
2961
+ return {
2962
+ type: "sse",
2963
+ name,
2964
+ url: config.url,
2965
+ headers: Object.entries(config.headers ?? {}).map(([headerName, value]) => ({
2966
+ name: headerName,
2967
+ value,
2968
+ })),
2969
+ };
2970
+ });
2971
+ }
2972
+ function toACPContentBlocks(prompt) {
2973
+ if (typeof prompt === "string") {
2974
+ return [{ type: "text", text: prompt }];
2975
+ }
2976
+ const contentBlocks = [];
2977
+ for (const block of prompt) {
2978
+ switch (block.type) {
2979
+ case "text":
2980
+ contentBlocks.push({ type: "text", text: block.text });
2981
+ break;
2982
+ case "image":
2983
+ contentBlocks.push({ type: "image", data: block.data, mimeType: block.mimeType });
2984
+ break;
2985
+ default:
2986
+ contentBlocks.push({ type: "text", text: renderPromptAttachmentAsText(block) });
2987
+ break;
2988
+ }
2989
+ }
2990
+ return contentBlocks;
2991
+ }
2992
+ function extractPromptText(prompt) {
2993
+ if (typeof prompt === "string") {
2994
+ return prompt;
2995
+ }
2996
+ return prompt
2997
+ .filter((block) => block.type === "text")
2998
+ .map((block) => block.text)
2999
+ .join("");
3000
+ }
3001
+ function contentBlockToText(content) {
3002
+ switch (content.type) {
3003
+ case "text":
3004
+ return content.text;
3005
+ case "resource_link":
3006
+ return content.title ?? content.uri;
3007
+ case "resource":
3008
+ return "text" in content.resource
3009
+ ? content.resource.text
3010
+ : `[resource:${content.resource.mimeType ?? "binary"}]`;
3011
+ case "image":
3012
+ return "[image]";
3013
+ case "audio":
3014
+ return "[audio]";
3015
+ default:
3016
+ return "";
3017
+ }
3018
+ }
3019
+ function normalizeACPImportPromptPreview(text) {
3020
+ const normalized = text?.trim().replace(/\s+/g, " ") ?? "";
3021
+ if (!normalized)
3022
+ return null;
3023
+ return normalized.length > 160 ? normalized.slice(0, 160) : normalized;
3024
+ }
3025
+ function isACPConversationUpdate(update) {
3026
+ return (update.sessionUpdate === "user_message_chunk" ||
3027
+ update.sessionUpdate === "agent_message_chunk" ||
3028
+ update.sessionUpdate === "agent_thought_chunk" ||
3029
+ update.sessionUpdate === "tool_call" ||
3030
+ update.sessionUpdate === "tool_call_update" ||
3031
+ update.sessionUpdate === "plan");
3032
+ }
3033
+ function coalesceDefined(next, previous, fallback) {
3034
+ if (next !== undefined) {
3035
+ return next;
3036
+ }
3037
+ if (previous !== undefined) {
3038
+ return previous;
3039
+ }
3040
+ return fallback;
3041
+ }
3042
+ function mergeToolSnapshot(toolCallId, update, previous) {
3043
+ return {
3044
+ toolCallId,
3045
+ title: update.title ?? previous?.title ?? toolCallId,
3046
+ kind: update.kind ?? previous?.kind ?? null,
3047
+ status: update.status ?? previous?.status ?? null,
3048
+ content: coalesceDefined(update.content, previous?.content, null),
3049
+ locations: coalesceDefined(update.locations, previous?.locations, null),
3050
+ rawInput: update.rawInput !== undefined ? update.rawInput : previous?.rawInput,
3051
+ rawOutput: update.rawOutput !== undefined ? update.rawOutput : previous?.rawOutput,
3052
+ };
3053
+ }
3054
+ function mapPlanToTimeline(plan) {
3055
+ return {
3056
+ type: "todo",
3057
+ items: plan.entries.map((entry) => ({
3058
+ text: entry.content,
3059
+ completed: entry.status === "completed",
3060
+ })),
3061
+ };
3062
+ }
3063
+ function mapToolSnapshotToTimeline(snapshot, terminals) {
3064
+ const status = mapToolStatus(snapshot.status);
3065
+ const detail = mapToolDetail(snapshot, terminals);
3066
+ const base = {
3067
+ type: "tool_call",
3068
+ callId: snapshot.toolCallId,
3069
+ name: snapshot.kind ?? snapshot.title,
3070
+ detail,
3071
+ metadata: {
3072
+ kind: snapshot.kind ?? undefined,
3073
+ title: snapshot.title,
3074
+ },
3075
+ };
3076
+ if (status === "failed") {
3077
+ return {
3078
+ ...base,
3079
+ status: "failed",
3080
+ error: { message: readErrorMessage(snapshot.rawOutput) },
3081
+ };
3082
+ }
3083
+ if (status === "completed") {
3084
+ return {
3085
+ ...base,
3086
+ status: "completed",
3087
+ error: null,
3088
+ };
3089
+ }
3090
+ return {
3091
+ ...base,
3092
+ status: "running",
3093
+ error: null,
3094
+ };
3095
+ }
3096
+ function mapToolStatus(status) {
3097
+ switch (status) {
3098
+ case "completed":
3099
+ return "completed";
3100
+ case "failed":
3101
+ return "failed";
3102
+ case "pending":
3103
+ case "in_progress":
3104
+ default:
3105
+ return "running";
3106
+ }
3107
+ }
3108
+ function mapToolDetail(snapshot, terminals) {
3109
+ const context = {
3110
+ snapshot,
3111
+ firstLocation: snapshot.locations?.[0]?.path,
3112
+ textContent: extractToolText(snapshot.content),
3113
+ diffContent: extractDiffContent(snapshot.content),
3114
+ terminalContent: extractTerminalContent(snapshot.content, terminals),
3115
+ rawInput: readRecord(snapshot.rawInput),
3116
+ rawOutput: readRecord(snapshot.rawOutput),
3117
+ };
3118
+ switch (snapshot.kind) {
3119
+ case "read":
3120
+ return buildReadToolDetail(context);
3121
+ case "edit":
3122
+ case "delete":
3123
+ return buildEditToolDetail(context);
3124
+ case "search":
3125
+ return buildSearchAcpToolDetail(context);
3126
+ case "execute":
3127
+ return buildShellToolDetail(context);
3128
+ case "fetch":
3129
+ return buildFetchToolDetail(context);
3130
+ case "think":
3131
+ return {
3132
+ type: "plain_text",
3133
+ label: snapshot.title,
3134
+ icon: "brain",
3135
+ text: context.textContent ?? stringifyUnknown(snapshot.rawOutput),
3136
+ };
3137
+ case "switch_mode":
3138
+ return {
3139
+ type: "plain_text",
3140
+ label: snapshot.title,
3141
+ icon: "sparkles",
3142
+ text: context.textContent ?? stringifyUnknown(snapshot.rawInput),
3143
+ };
3144
+ default:
3145
+ return buildDefaultToolDetail(context);
3146
+ }
3147
+ }
3148
+ function buildReadToolDetail(context) {
3149
+ const { snapshot, firstLocation, textContent, rawInput, rawOutput } = context;
3150
+ return {
3151
+ type: "read",
3152
+ filePath: firstLocation ?? readString(rawInput, ["path", "filePath", "file"]) ?? snapshot.title,
3153
+ content: textContent ?? readString(rawOutput, ["content", "text"]),
3154
+ offset: readNumber(rawInput, ["offset", "line"]),
3155
+ limit: readNumber(rawInput, ["limit"]),
3156
+ };
3157
+ }
3158
+ function buildEditToolDetail(context) {
3159
+ const { snapshot, firstLocation, textContent, diffContent, rawInput } = context;
3160
+ return {
3161
+ type: "edit",
3162
+ filePath: firstLocation ?? readString(rawInput, ["path", "filePath", "file"]) ?? snapshot.title,
3163
+ oldString: diffContent?.oldText ?? readString(rawInput, ["oldText", "oldString"]),
3164
+ newString: snapshot.kind === "delete"
3165
+ ? ""
3166
+ : (diffContent?.newText ?? readString(rawInput, ["newText", "newString"])),
3167
+ unifiedDiff: textContent ?? undefined,
3168
+ };
3169
+ }
3170
+ function buildSearchAcpToolDetail(context) {
3171
+ const { snapshot, textContent, rawInput, rawOutput } = context;
3172
+ return {
3173
+ type: "search",
3174
+ query: readString(rawInput, ["query", "pattern"]) ?? snapshot.title,
3175
+ toolName: "search",
3176
+ content: textContent ?? readString(rawOutput, ["content", "text"]),
3177
+ filePaths: snapshot.locations?.map((location) => location.path),
3178
+ };
3179
+ }
3180
+ function buildShellToolDetail(context) {
3181
+ const { snapshot, textContent, terminalContent, rawInput, rawOutput } = context;
3182
+ return {
3183
+ type: "shell",
3184
+ command: terminalContent?.command ??
3185
+ buildShellCommand(rawInput) ??
3186
+ readString(rawInput, ["command"]) ??
3187
+ snapshot.title,
3188
+ cwd: terminalContent?.cwd ?? readString(rawInput, ["cwd"]),
3189
+ output: terminalContent?.output ?? textContent ?? readString(rawOutput, ["output", "text"]),
3190
+ exitCode: terminalContent?.exitCode ?? readNumber(rawOutput, ["exitCode"]),
3191
+ };
3192
+ }
3193
+ function buildFetchToolDetail(context) {
3194
+ const { snapshot, textContent, rawInput, rawOutput } = context;
3195
+ return {
3196
+ type: "fetch",
3197
+ url: readString(rawInput, ["url"]) ?? snapshot.title,
3198
+ prompt: readString(rawInput, ["prompt"]),
3199
+ result: textContent ?? readString(rawOutput, ["result", "text", "content"]),
3200
+ code: readNumber(rawOutput, ["status", "code"]),
3201
+ };
3202
+ }
3203
+ function buildDefaultToolDetail(context) {
3204
+ const { snapshot, textContent, terminalContent } = context;
3205
+ if (terminalContent) {
3206
+ return {
3207
+ type: "shell",
3208
+ command: terminalContent.command ?? snapshot.title,
3209
+ cwd: terminalContent.cwd,
3210
+ output: terminalContent.output,
3211
+ exitCode: terminalContent.exitCode,
3212
+ };
3213
+ }
3214
+ if (textContent) {
3215
+ return {
3216
+ type: "plain_text",
3217
+ label: snapshot.title,
3218
+ text: textContent,
3219
+ icon: "wrench",
3220
+ };
3221
+ }
3222
+ return {
3223
+ type: "unknown",
3224
+ input: snapshot.rawInput ?? null,
3225
+ output: snapshot.rawOutput ?? null,
3226
+ };
3227
+ }
3228
+ function extractToolText(content) {
3229
+ if (!content) {
3230
+ return undefined;
3231
+ }
3232
+ const parts = [];
3233
+ for (const item of content) {
3234
+ if (item.type === "content") {
3235
+ const text = contentBlockToText(item.content);
3236
+ if (text) {
3237
+ parts.push(text);
3238
+ }
3239
+ }
3240
+ }
3241
+ return parts.length > 0 ? parts.join("\n") : undefined;
3242
+ }
3243
+ function extractDiffContent(content) {
3244
+ const diff = content?.find((item) => item.type === "diff");
3245
+ return diff ? { oldText: diff.oldText ?? undefined, newText: diff.newText } : null;
3246
+ }
3247
+ function extractTerminalContent(content, terminals) {
3248
+ const terminal = content?.find((item) => item.type === "terminal");
3249
+ if (!terminal) {
3250
+ return undefined;
3251
+ }
3252
+ const entry = terminals.get(terminal.terminalId);
3253
+ if (!entry) {
3254
+ return undefined;
3255
+ }
3256
+ return {
3257
+ output: entry.output,
3258
+ exitCode: entry.exit?.exitCode ?? null,
3259
+ };
3260
+ }
3261
+ function mapPermissionRequest(provider, requestId, params, snapshot) {
3262
+ const kind = snapshot.kind === "switch_mode" ? "mode" : "tool";
3263
+ const chooserText = isACPChooserRequest(params.options)
3264
+ ? extractToolText(params.toolCall.content)
3265
+ : undefined;
3266
+ return {
3267
+ id: requestId,
3268
+ provider,
3269
+ name: snapshot.kind ?? snapshot.title,
3270
+ kind,
3271
+ title: params.toolCall.title ?? snapshot.title,
3272
+ detail: chooserText
3273
+ ? {
3274
+ type: "plain_text",
3275
+ label: params.toolCall.title ?? snapshot.title,
3276
+ text: chooserText,
3277
+ icon: "wrench",
3278
+ }
3279
+ : mapToolDetail(snapshot, new Map()),
3280
+ actions: params.options.map((option) => ({
3281
+ id: option.optionId,
3282
+ label: option.name,
3283
+ behavior: option.kind.startsWith("allow") ? "allow" : "deny",
3284
+ })),
3285
+ metadata: {
3286
+ toolCallId: params.toolCall.toolCallId,
3287
+ rawRequest: params,
3288
+ options: params.options,
3289
+ },
3290
+ };
3291
+ }
3292
+ function selectPermissionOption(options, response) {
3293
+ if (response.selectedActionId !== undefined) {
3294
+ const selectedOption = options.find((option) => option.optionId === response.selectedActionId);
3295
+ if (!selectedOption)
3296
+ return null;
3297
+ const selectedBehavior = selectedOption.kind.startsWith("allow") ? "allow" : "deny";
3298
+ return selectedBehavior === response.behavior ? selectedOption : null;
3299
+ }
3300
+ const order = response.behavior === "allow"
3301
+ ? ["allow_once", "allow_always"]
3302
+ : ["reject_once", "reject_always"];
3303
+ for (const kind of order) {
3304
+ const match = options.find((option) => option.kind === kind);
3305
+ if (match) {
3306
+ return match;
3307
+ }
3308
+ }
3309
+ return null;
3310
+ }
3311
+ function isACPChooserRequest(options) {
3312
+ const allowKinds = new Set();
3313
+ for (const option of options) {
3314
+ if (!option.kind.startsWith("allow")) {
3315
+ continue;
3316
+ }
3317
+ if (allowKinds.has(option.kind)) {
3318
+ return true;
3319
+ }
3320
+ allowKinds.add(option.kind);
3321
+ }
3322
+ return false;
3323
+ }
3324
+ function appendTerminalOutput(entry, chunk) {
3325
+ entry.output += chunk;
3326
+ const limit = entry.outputByteLimit;
3327
+ if (!limit) {
3328
+ return;
3329
+ }
3330
+ while (Buffer.byteLength(entry.output, "utf8") > limit && entry.output.length > 0) {
3331
+ entry.output = entry.output.slice(1);
3332
+ entry.truncated = true;
3333
+ }
3334
+ }
3335
+ function readRecord(value) {
3336
+ return isRecord(value) ? value : null;
3337
+ }
3338
+ function readString(record, keys) {
3339
+ if (!record) {
3340
+ return undefined;
3341
+ }
3342
+ for (const key of keys) {
3343
+ const value = record[key];
3344
+ if (typeof value === "string" && value.trim().length > 0) {
3345
+ return value;
3346
+ }
3347
+ }
3348
+ return undefined;
3349
+ }
3350
+ function readNumber(record, keys) {
3351
+ if (!record) {
3352
+ return undefined;
3353
+ }
3354
+ for (const key of keys) {
3355
+ const value = record[key];
3356
+ if (typeof value === "number" && Number.isFinite(value)) {
3357
+ return value;
3358
+ }
3359
+ }
3360
+ return undefined;
3361
+ }
3362
+ function buildShellCommand(record) {
3363
+ if (!record) {
3364
+ return undefined;
3365
+ }
3366
+ const command = readString(record, ["command"]);
3367
+ const args = Array.isArray(record["args"])
3368
+ ? record["args"].filter((value) => typeof value === "string")
3369
+ : [];
3370
+ if (!command) {
3371
+ return undefined;
3372
+ }
3373
+ return args.length > 0 ? `${command} ${args.join(" ")}` : command;
3374
+ }
3375
+ function readErrorMessage(value) {
3376
+ if (typeof value === "string") {
3377
+ return value;
3378
+ }
3379
+ const record = readRecord(value);
3380
+ return readString(record, ["message", "error"]) ?? "Tool call failed";
3381
+ }
3382
+ function stringifyUnknown(value) {
3383
+ if (value == null) {
3384
+ return undefined;
3385
+ }
3386
+ if (typeof value === "string") {
3387
+ return value;
3388
+ }
3389
+ try {
3390
+ return JSON.stringify(value);
3391
+ }
3392
+ catch {
3393
+ return typeof value === "bigint" ? String(value) : "[unserializable]";
3394
+ }
3395
+ }
3396
+ function coerceSessionConfigMetadata(metadata) {
3397
+ if (!metadata || typeof metadata !== "object") {
3398
+ return {};
3399
+ }
3400
+ return metadata;
3401
+ }
3402
+ async function terminateChildProcess(child, timeoutMs, terminate) {
3403
+ try {
3404
+ await terminate(child, { gracefulTimeoutMs: timeoutMs, forceTimeoutMs: timeoutMs });
3405
+ }
3406
+ finally {
3407
+ child.stdin.destroy();
3408
+ child.stdout.destroy();
3409
+ child.stderr.destroy();
3410
+ }
3411
+ }
3412
+ //# sourceMappingURL=acp-agent.js.map