@getpaseo/server 0.1.62 → 0.1.65

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 (590) hide show
  1. package/README.md +4 -0
  2. package/dist/server/client/daemon-client-runtime-metrics.d.ts +6 -6
  3. package/dist/server/client/daemon-client-runtime-metrics.d.ts.map +1 -1
  4. package/dist/server/client/daemon-client-transport-types.d.ts +15 -13
  5. package/dist/server/client/daemon-client-transport-types.d.ts.map +1 -1
  6. package/dist/server/client/daemon-client-websocket-transport.d.ts +3 -2
  7. package/dist/server/client/daemon-client-websocket-transport.d.ts.map +1 -1
  8. package/dist/server/client/daemon-client-websocket-transport.js +9 -8
  9. package/dist/server/client/daemon-client-websocket-transport.js.map +1 -1
  10. package/dist/server/client/daemon-client.d.ts +88 -56
  11. package/dist/server/client/daemon-client.d.ts.map +1 -1
  12. package/dist/server/client/daemon-client.js +264 -111
  13. package/dist/server/client/daemon-client.js.map +1 -1
  14. package/dist/server/client/terminal-stream-router.d.ts +24 -0
  15. package/dist/server/client/terminal-stream-router.d.ts.map +1 -0
  16. package/dist/server/client/terminal-stream-router.js +100 -0
  17. package/dist/server/client/terminal-stream-router.js.map +1 -0
  18. package/dist/server/server/agent/activity-curator.d.ts +6 -3
  19. package/dist/server/server/agent/activity-curator.d.ts.map +1 -1
  20. package/dist/server/server/agent/activity-curator.js +45 -138
  21. package/dist/server/server/agent/activity-curator.js.map +1 -1
  22. package/dist/server/server/agent/agent-loading.d.ts.map +1 -1
  23. package/dist/server/server/agent/agent-loading.js +5 -3
  24. package/dist/server/server/agent/agent-loading.js.map +1 -1
  25. package/dist/server/server/agent/agent-manager.d.ts +46 -31
  26. package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
  27. package/dist/server/server/agent/agent-manager.js +457 -419
  28. package/dist/server/server/agent/agent-manager.js.map +1 -1
  29. package/dist/server/server/agent/agent-metadata-generator.d.ts +6 -11
  30. package/dist/server/server/agent/agent-metadata-generator.d.ts.map +1 -1
  31. package/dist/server/server/agent/agent-metadata-generator.js +3 -85
  32. package/dist/server/server/agent/agent-metadata-generator.js.map +1 -1
  33. package/dist/server/server/agent/agent-projections.d.ts +4 -6
  34. package/dist/server/server/agent/agent-projections.d.ts.map +1 -1
  35. package/dist/server/server/agent/agent-projections.js +59 -65
  36. package/dist/server/server/agent/agent-projections.js.map +1 -1
  37. package/dist/server/server/agent/agent-response-loop.d.ts +4 -4
  38. package/dist/server/server/agent/agent-response-loop.d.ts.map +1 -1
  39. package/dist/server/server/agent/agent-response-loop.js +58 -45
  40. package/dist/server/server/agent/agent-response-loop.js.map +1 -1
  41. package/dist/server/server/agent/agent-sdk-types.d.ts +58 -41
  42. package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -1
  43. package/dist/server/server/agent/agent-sdk-types.js.map +1 -1
  44. package/dist/server/server/agent/agent-storage.d.ts +2 -2
  45. package/dist/server/server/agent/agent-storage.d.ts.map +1 -1
  46. package/dist/server/server/agent/agent-storage.js +29 -36
  47. package/dist/server/server/agent/agent-storage.js.map +1 -1
  48. package/dist/server/server/agent/agent-stream-coalescer.d.ts +7 -7
  49. package/dist/server/server/agent/agent-stream-coalescer.d.ts.map +1 -1
  50. package/dist/server/server/agent/agent-stream-coalescer.js +1 -1
  51. package/dist/server/server/agent/agent-stream-coalescer.js.map +1 -1
  52. package/dist/server/server/agent/agent-timeline-store-types.d.ts +10 -10
  53. package/dist/server/server/agent/agent-timeline-store-types.d.ts.map +1 -1
  54. package/dist/server/server/agent/agent-timeline-store.d.ts +2 -2
  55. package/dist/server/server/agent/agent-timeline-store.d.ts.map +1 -1
  56. package/dist/server/server/agent/agent-timeline-store.js +103 -85
  57. package/dist/server/server/agent/agent-timeline-store.js.map +1 -1
  58. package/dist/server/server/agent/foreground-run-state.d.ts +50 -0
  59. package/dist/server/server/agent/foreground-run-state.d.ts.map +1 -0
  60. package/dist/server/server/agent/foreground-run-state.js +162 -0
  61. package/dist/server/server/agent/foreground-run-state.js.map +1 -0
  62. package/dist/server/server/agent/mcp-server.d.ts +5 -3
  63. package/dist/server/server/agent/mcp-server.d.ts.map +1 -1
  64. package/dist/server/server/agent/mcp-server.js +282 -234
  65. package/dist/server/server/agent/mcp-server.js.map +1 -1
  66. package/dist/server/server/agent/mcp-shared.d.ts +9 -2
  67. package/dist/server/server/agent/mcp-shared.d.ts.map +1 -1
  68. package/dist/server/server/agent/mcp-shared.js +9 -1
  69. package/dist/server/server/agent/mcp-shared.js.map +1 -1
  70. package/dist/server/server/agent/model-resolver.d.ts +2 -2
  71. package/dist/server/server/agent/model-resolver.d.ts.map +1 -1
  72. package/dist/server/server/agent/model-resolver.js +9 -5
  73. package/dist/server/server/agent/model-resolver.js.map +1 -1
  74. package/dist/server/server/agent/prompt-attachments.d.ts +4 -3
  75. package/dist/server/server/agent/prompt-attachments.d.ts.map +1 -1
  76. package/dist/server/server/agent/prompt-attachments.js +43 -4
  77. package/dist/server/server/agent/prompt-attachments.js.map +1 -1
  78. package/dist/server/server/agent/provider-launch-config.d.ts +28 -17
  79. package/dist/server/server/agent/provider-launch-config.d.ts.map +1 -1
  80. package/dist/server/server/agent/provider-launch-config.js +20 -9
  81. package/dist/server/server/agent/provider-launch-config.js.map +1 -1
  82. package/dist/server/server/agent/provider-manifest.d.ts.map +1 -1
  83. package/dist/server/server/agent/provider-manifest.js +7 -0
  84. package/dist/server/server/agent/provider-manifest.js.map +1 -1
  85. package/dist/server/server/agent/provider-registry.d.ts +4 -2
  86. package/dist/server/server/agent/provider-registry.d.ts.map +1 -1
  87. package/dist/server/server/agent/provider-registry.js +24 -21
  88. package/dist/server/server/agent/provider-registry.js.map +1 -1
  89. package/dist/server/server/agent/provider-snapshot-manager.d.ts +6 -5
  90. package/dist/server/server/agent/provider-snapshot-manager.d.ts.map +1 -1
  91. package/dist/server/server/agent/provider-snapshot-manager.js +40 -31
  92. package/dist/server/server/agent/provider-snapshot-manager.js.map +1 -1
  93. package/dist/server/server/agent/providers/acp-agent.d.ts +49 -13
  94. package/dist/server/server/agent/providers/acp-agent.d.ts.map +1 -1
  95. package/dist/server/server/agent/providers/acp-agent.js +404 -261
  96. package/dist/server/server/agent/providers/acp-agent.js.map +1 -1
  97. package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts +2 -0
  98. package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts.map +1 -1
  99. package/dist/server/server/agent/providers/claude/sidechain-tracker.js +47 -45
  100. package/dist/server/server/agent/providers/claude/sidechain-tracker.js.map +1 -1
  101. package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts +2 -2
  102. package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts.map +1 -1
  103. package/dist/server/server/agent/providers/claude/task-notification-tool-call.js +10 -5
  104. package/dist/server/server/agent/providers/claude/task-notification-tool-call.js.map +1 -1
  105. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts.map +1 -1
  106. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js +11 -2
  107. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js.map +1 -1
  108. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts +2 -2
  109. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts.map +1 -1
  110. package/dist/server/server/agent/providers/claude/tool-call-mapper.js +83 -206
  111. package/dist/server/server/agent/providers/claude/tool-call-mapper.js.map +1 -1
  112. package/dist/server/server/agent/providers/claude-agent.d.ts +20 -8
  113. package/dist/server/server/agent/providers/claude-agent.d.ts.map +1 -1
  114. package/dist/server/server/agent/providers/claude-agent.js +654 -554
  115. package/dist/server/server/agent/providers/claude-agent.js.map +1 -1
  116. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts +2 -2
  117. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts.map +1 -1
  118. package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts +2 -2
  119. package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts.map +1 -1
  120. package/dist/server/server/agent/providers/codex/tool-call-mapper.js +174 -185
  121. package/dist/server/server/agent/providers/codex/tool-call-mapper.js.map +1 -1
  122. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +62 -13
  123. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -1
  124. package/dist/server/server/agent/providers/codex-app-server-agent.js +873 -646
  125. package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -1
  126. package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts +2 -2
  127. package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts.map +1 -1
  128. package/dist/server/server/agent/providers/codex-rollout-timeline.js +58 -47
  129. package/dist/server/server/agent/providers/codex-rollout-timeline.js.map +1 -1
  130. package/dist/server/server/agent/providers/copilot-acp-agent.d.ts +2 -2
  131. package/dist/server/server/agent/providers/copilot-acp-agent.d.ts.map +1 -1
  132. package/dist/server/server/agent/providers/diagnostic-utils.d.ts +3 -3
  133. package/dist/server/server/agent/providers/diagnostic-utils.d.ts.map +1 -1
  134. package/dist/server/server/agent/providers/diagnostic-utils.js +82 -9
  135. package/dist/server/server/agent/providers/diagnostic-utils.js.map +1 -1
  136. package/dist/server/server/agent/providers/generic-acp-agent.d.ts +2 -2
  137. package/dist/server/server/agent/providers/generic-acp-agent.d.ts.map +1 -1
  138. package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +6 -2
  139. package/dist/server/server/agent/providers/mock-load-test-agent.d.ts.map +1 -1
  140. package/dist/server/server/agent/providers/mock-load-test-agent.js +294 -113
  141. package/dist/server/server/agent/providers/mock-load-test-agent.js.map +1 -1
  142. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts +1 -1
  143. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts.map +1 -1
  144. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +94 -2
  145. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js.map +1 -1
  146. package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts +2 -2
  147. package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts.map +1 -1
  148. package/dist/server/server/agent/providers/opencode/tool-call-mapper.js +24 -115
  149. package/dist/server/server/agent/providers/opencode/tool-call-mapper.js.map +1 -1
  150. package/dist/server/server/agent/providers/opencode-agent.d.ts +104 -3
  151. package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
  152. package/dist/server/server/agent/providers/opencode-agent.js +786 -503
  153. package/dist/server/server/agent/providers/opencode-agent.js.map +1 -1
  154. package/dist/server/server/agent/providers/pi-direct-agent.d.ts +1 -0
  155. package/dist/server/server/agent/providers/pi-direct-agent.d.ts.map +1 -1
  156. package/dist/server/server/agent/providers/pi-direct-agent.js +109 -140
  157. package/dist/server/server/agent/providers/pi-direct-agent.js.map +1 -1
  158. package/dist/server/server/agent/providers/provider-runner.d.ts +27 -0
  159. package/dist/server/server/agent/providers/provider-runner.d.ts.map +1 -0
  160. package/dist/server/server/agent/providers/provider-runner.js +80 -0
  161. package/dist/server/server/agent/providers/provider-runner.js.map +1 -0
  162. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.d.ts.map +1 -1
  163. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.js +3 -1
  164. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.js.map +1 -1
  165. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +9 -6
  166. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts.map +1 -1
  167. package/dist/server/server/agent/providers/tool-call-detail-primitives.js +102 -73
  168. package/dist/server/server/agent/providers/tool-call-detail-primitives.js.map +1 -1
  169. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +4 -2
  170. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts.map +1 -1
  171. package/dist/server/server/agent/providers/tool-call-mapper-utils.js +31 -0
  172. package/dist/server/server/agent/providers/tool-call-mapper-utils.js.map +1 -1
  173. package/dist/server/server/agent/stt-manager.d.ts.map +1 -1
  174. package/dist/server/server/agent/stt-manager.js +63 -53
  175. package/dist/server/server/agent/stt-manager.js.map +1 -1
  176. package/dist/server/server/agent/timeline-projection.d.ts +27 -11
  177. package/dist/server/server/agent/timeline-projection.d.ts.map +1 -1
  178. package/dist/server/server/agent/timeline-projection.js +70 -15
  179. package/dist/server/server/agent/timeline-projection.js.map +1 -1
  180. package/dist/server/server/agent/tts-manager.d.ts.map +1 -1
  181. package/dist/server/server/agent/tts-manager.js +1 -0
  182. package/dist/server/server/agent/tts-manager.js.map +1 -1
  183. package/dist/server/server/agent-attention-policy.d.ts +2 -2
  184. package/dist/server/server/agent-attention-policy.d.ts.map +1 -1
  185. package/dist/server/server/auth.d.ts +25 -0
  186. package/dist/server/server/auth.d.ts.map +1 -0
  187. package/dist/server/server/auth.js +93 -0
  188. package/dist/server/server/auth.js.map +1 -0
  189. package/dist/server/server/bootstrap.d.ts +7 -5
  190. package/dist/server/server/bootstrap.d.ts.map +1 -1
  191. package/dist/server/server/bootstrap.js +550 -485
  192. package/dist/server/server/bootstrap.js.map +1 -1
  193. package/dist/server/server/chat/chat-service.d.ts +1 -1
  194. package/dist/server/server/chat/chat-service.d.ts.map +1 -1
  195. package/dist/server/server/chat/chat-service.js +3 -3
  196. package/dist/server/server/chat/chat-service.js.map +1 -1
  197. package/dist/server/server/checkout-diff-manager.d.ts +2 -2
  198. package/dist/server/server/checkout-diff-manager.d.ts.map +1 -1
  199. package/dist/server/server/checkout-git-utils.d.ts +5 -3
  200. package/dist/server/server/checkout-git-utils.d.ts.map +1 -1
  201. package/dist/server/server/checkout-git-utils.js +1 -2
  202. package/dist/server/server/checkout-git-utils.js.map +1 -1
  203. package/dist/server/server/config.d.ts.map +1 -1
  204. package/dist/server/server/config.js +79 -39
  205. package/dist/server/server/config.js.map +1 -1
  206. package/dist/server/server/connection-offer.d.ts +2 -2
  207. package/dist/server/server/connection-offer.d.ts.map +1 -1
  208. package/dist/server/server/daemon-config-store.d.ts +5 -3
  209. package/dist/server/server/daemon-config-store.d.ts.map +1 -1
  210. package/dist/server/server/daemon-config-store.js +26 -0
  211. package/dist/server/server/daemon-config-store.js.map +1 -1
  212. package/dist/server/server/daemon-keypair.d.ts +2 -2
  213. package/dist/server/server/daemon-keypair.d.ts.map +1 -1
  214. package/dist/server/server/editor-targets.d.ts +4 -4
  215. package/dist/server/server/editor-targets.d.ts.map +1 -1
  216. package/dist/server/server/editor-targets.js +11 -15
  217. package/dist/server/server/editor-targets.js.map +1 -1
  218. package/dist/server/server/exports.d.ts +10 -4
  219. package/dist/server/server/exports.d.ts.map +1 -1
  220. package/dist/server/server/exports.js +7 -4
  221. package/dist/server/server/exports.js.map +1 -1
  222. package/dist/server/server/file-download/token-store.d.ts +4 -4
  223. package/dist/server/server/file-download/token-store.d.ts.map +1 -1
  224. package/dist/server/server/file-explorer/service.d.ts +10 -0
  225. package/dist/server/server/file-explorer/service.d.ts.map +1 -1
  226. package/dist/server/server/file-explorer/service.js +38 -4
  227. package/dist/server/server/file-explorer/service.js.map +1 -1
  228. package/dist/server/server/index.js +25 -18
  229. package/dist/server/server/index.js.map +1 -1
  230. package/dist/server/server/logger.d.ts +4 -4
  231. package/dist/server/server/logger.d.ts.map +1 -1
  232. package/dist/server/server/logger.js +41 -21
  233. package/dist/server/server/logger.js.map +1 -1
  234. package/dist/server/server/loop/rpc-schemas.d.ts +52 -52
  235. package/dist/server/server/loop-service.d.ts +13 -12
  236. package/dist/server/server/loop-service.d.ts.map +1 -1
  237. package/dist/server/server/loop-service.js +22 -18
  238. package/dist/server/server/loop-service.js.map +1 -1
  239. package/dist/server/server/package-version.d.ts +2 -2
  240. package/dist/server/server/package-version.d.ts.map +1 -1
  241. package/dist/server/server/package-version.js +19 -17
  242. package/dist/server/server/package-version.js.map +1 -1
  243. package/dist/server/server/pagination/cursor.d.ts +16 -0
  244. package/dist/server/server/pagination/cursor.d.ts.map +1 -0
  245. package/dist/server/server/pagination/cursor.js +62 -0
  246. package/dist/server/server/pagination/cursor.js.map +1 -0
  247. package/dist/server/server/pagination/sortable-pager.d.ts +24 -0
  248. package/dist/server/server/pagination/sortable-pager.d.ts.map +1 -0
  249. package/dist/server/server/pagination/sortable-pager.js +68 -0
  250. package/dist/server/server/pagination/sortable-pager.js.map +1 -0
  251. package/dist/server/server/pairing-offer.d.ts +2 -2
  252. package/dist/server/server/pairing-offer.d.ts.map +1 -1
  253. package/dist/server/server/paseo-env.d.ts +9 -0
  254. package/dist/server/server/paseo-env.d.ts.map +1 -0
  255. package/dist/server/server/paseo-env.js +70 -0
  256. package/dist/server/server/paseo-env.js.map +1 -0
  257. package/dist/server/server/paseo-worktree-archive-service.d.ts +7 -5
  258. package/dist/server/server/paseo-worktree-archive-service.d.ts.map +1 -1
  259. package/dist/server/server/paseo-worktree-archive-service.js +70 -62
  260. package/dist/server/server/paseo-worktree-archive-service.js.map +1 -1
  261. package/dist/server/server/paseo-worktree-service.d.ts +13 -0
  262. package/dist/server/server/paseo-worktree-service.d.ts.map +1 -1
  263. package/dist/server/server/paseo-worktree-service.js +72 -3
  264. package/dist/server/server/paseo-worktree-service.js.map +1 -1
  265. package/dist/server/server/persisted-config.d.ts +87 -62
  266. package/dist/server/server/persisted-config.d.ts.map +1 -1
  267. package/dist/server/server/persisted-config.js +13 -4
  268. package/dist/server/server/persisted-config.js.map +1 -1
  269. package/dist/server/server/persistence-hooks.d.ts +8 -9
  270. package/dist/server/server/persistence-hooks.d.ts.map +1 -1
  271. package/dist/server/server/persistence-hooks.js +4 -12
  272. package/dist/server/server/persistence-hooks.js.map +1 -1
  273. package/dist/server/server/pid-lock.js.map +1 -1
  274. package/dist/server/server/push/push-service.d.ts.map +1 -1
  275. package/dist/server/server/push/push-service.js +1 -3
  276. package/dist/server/server/push/push-service.js.map +1 -1
  277. package/dist/server/server/relay-transport.d.ts +8 -8
  278. package/dist/server/server/relay-transport.d.ts.map +1 -1
  279. package/dist/server/server/relay-transport.js +43 -20
  280. package/dist/server/server/relay-transport.js.map +1 -1
  281. package/dist/server/server/resolve-worktree-creation-intent.d.ts +0 -10
  282. package/dist/server/server/resolve-worktree-creation-intent.d.ts.map +1 -1
  283. package/dist/server/server/resolve-worktree-creation-intent.js +1 -45
  284. package/dist/server/server/resolve-worktree-creation-intent.js.map +1 -1
  285. package/dist/server/server/schedule/service.d.ts.map +1 -1
  286. package/dist/server/server/schedule/service.js +2 -2
  287. package/dist/server/server/schedule/service.js.map +1 -1
  288. package/dist/server/server/script-health-monitor.d.ts.map +1 -1
  289. package/dist/server/server/script-health-monitor.js +7 -6
  290. package/dist/server/server/script-health-monitor.js.map +1 -1
  291. package/dist/server/server/script-proxy.js +1 -1
  292. package/dist/server/server/script-proxy.js.map +1 -1
  293. package/dist/server/server/script-status-projection.d.ts +10 -5
  294. package/dist/server/server/script-status-projection.d.ts.map +1 -1
  295. package/dist/server/server/script-status-projection.js +66 -47
  296. package/dist/server/server/script-status-projection.js.map +1 -1
  297. package/dist/server/server/server-id.d.ts +4 -4
  298. package/dist/server/server/server-id.d.ts.map +1 -1
  299. package/dist/server/server/session.d.ts +64 -65
  300. package/dist/server/server/session.d.ts.map +1 -1
  301. package/dist/server/server/session.js +1356 -1734
  302. package/dist/server/server/session.js.map +1 -1
  303. package/dist/server/server/speech/audio.js +1 -1
  304. package/dist/server/server/speech/audio.js.map +1 -1
  305. package/dist/server/server/speech/providers/local/config.d.ts +6 -6
  306. package/dist/server/server/speech/providers/local/config.d.ts.map +1 -1
  307. package/dist/server/server/speech/providers/local/config.js +41 -16
  308. package/dist/server/server/speech/providers/local/config.js.map +1 -1
  309. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.d.ts +2 -2
  310. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.d.ts.map +1 -1
  311. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.js +42 -19
  312. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.js.map +1 -1
  313. package/dist/server/server/speech/providers/local/runtime.d.ts +4 -4
  314. package/dist/server/server/speech/providers/local/runtime.d.ts.map +1 -1
  315. package/dist/server/server/speech/providers/local/runtime.js +108 -77
  316. package/dist/server/server/speech/providers/local/runtime.js.map +1 -1
  317. package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts +2 -2
  318. package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts.map +1 -1
  319. package/dist/server/server/speech/providers/local/sherpa/model-catalog.js +1 -4
  320. package/dist/server/server/speech/providers/local/sherpa/model-catalog.js.map +1 -1
  321. package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts +2 -2
  322. package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts.map +1 -1
  323. package/dist/server/server/speech/providers/local/sherpa/model-downloader.js +19 -19
  324. package/dist/server/server/speech/providers/local/sherpa/model-downloader.js.map +1 -1
  325. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts +28 -7
  326. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts.map +1 -1
  327. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js.map +1 -1
  328. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.d.ts +23 -4
  329. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.d.ts.map +1 -1
  330. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.js +35 -28
  331. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.js.map +1 -1
  332. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.d.ts +5 -5
  333. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.d.ts.map +1 -1
  334. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts +7 -7
  335. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts.map +1 -1
  336. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js +5 -0
  337. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js.map +1 -1
  338. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.d.ts.map +1 -1
  339. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js +3 -1
  340. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js.map +1 -1
  341. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts +2 -2
  342. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts.map +1 -1
  343. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js +3 -1
  344. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js.map +1 -1
  345. package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.d.ts.map +1 -1
  346. package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.js +10 -4
  347. package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.js.map +1 -1
  348. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.d.ts +2 -2
  349. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.d.ts.map +1 -1
  350. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.d.ts +2 -2
  351. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.d.ts.map +1 -1
  352. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.js +4 -1
  353. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.js.map +1 -1
  354. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts +2 -2
  355. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts.map +1 -1
  356. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js +18 -11
  357. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js.map +1 -1
  358. package/dist/server/server/speech/providers/openai/config.d.ts +2 -2
  359. package/dist/server/server/speech/providers/openai/config.d.ts.map +1 -1
  360. package/dist/server/server/speech/providers/openai/config.js +58 -31
  361. package/dist/server/server/speech/providers/openai/config.js.map +1 -1
  362. package/dist/server/server/speech/providers/openai/realtime-transcription-session.d.ts.map +1 -1
  363. package/dist/server/server/speech/providers/openai/realtime-transcription-session.js +2 -2
  364. package/dist/server/server/speech/providers/openai/realtime-transcription-session.js.map +1 -1
  365. package/dist/server/server/speech/providers/openai/runtime.d.ts +4 -4
  366. package/dist/server/server/speech/providers/openai/runtime.d.ts.map +1 -1
  367. package/dist/server/server/speech/providers/openai/runtime.js +37 -32
  368. package/dist/server/server/speech/providers/openai/runtime.js.map +1 -1
  369. package/dist/server/server/speech/providers/openai/stt.d.ts.map +1 -1
  370. package/dist/server/server/speech/providers/openai/stt.js +4 -3
  371. package/dist/server/server/speech/providers/openai/stt.js.map +1 -1
  372. package/dist/server/server/speech/providers/openai/tts.d.ts.map +1 -1
  373. package/dist/server/server/speech/providers/openai/tts.js +3 -2
  374. package/dist/server/server/speech/providers/openai/tts.js.map +1 -1
  375. package/dist/server/server/speech/speech-config-resolver.d.ts.map +1 -1
  376. package/dist/server/server/speech/speech-config-resolver.js +46 -17
  377. package/dist/server/server/speech/speech-config-resolver.js.map +1 -1
  378. package/dist/server/server/speech/speech-provider.d.ts +2 -2
  379. package/dist/server/server/speech/speech-provider.d.ts.map +1 -1
  380. package/dist/server/server/speech/speech-runtime.d.ts +6 -6
  381. package/dist/server/server/speech/speech-runtime.d.ts.map +1 -1
  382. package/dist/server/server/speech/speech-runtime.js +17 -17
  383. package/dist/server/server/speech/speech-runtime.js.map +1 -1
  384. package/dist/server/server/speech/speech-types.d.ts +2 -2
  385. package/dist/server/server/speech/speech-types.d.ts.map +1 -1
  386. package/dist/server/server/speech/turn-detection-provider.d.ts +2 -2
  387. package/dist/server/server/speech/turn-detection-provider.d.ts.map +1 -1
  388. package/dist/server/server/utils/diff-highlighter.d.ts +0 -3
  389. package/dist/server/server/utils/diff-highlighter.d.ts.map +1 -1
  390. package/dist/server/server/utils/diff-highlighter.js +67 -66
  391. package/dist/server/server/utils/diff-highlighter.js.map +1 -1
  392. package/dist/server/server/voice/voice-turn-controller.d.ts.map +1 -1
  393. package/dist/server/server/voice/voice-turn-controller.js +1 -0
  394. package/dist/server/server/voice/voice-turn-controller.js.map +1 -1
  395. package/dist/server/server/voice-types.d.ts +2 -2
  396. package/dist/server/server/voice-types.d.ts.map +1 -1
  397. package/dist/server/server/websocket-server.d.ts +34 -22
  398. package/dist/server/server/websocket-server.d.ts.map +1 -1
  399. package/dist/server/server/websocket-server.js +360 -205
  400. package/dist/server/server/websocket-server.js.map +1 -1
  401. package/dist/server/server/workspace-directory.d.ts +69 -0
  402. package/dist/server/server/workspace-directory.d.ts.map +1 -0
  403. package/dist/server/server/workspace-directory.js +229 -0
  404. package/dist/server/server/workspace-directory.js.map +1 -0
  405. package/dist/server/server/workspace-git-metadata.d.ts +2 -2
  406. package/dist/server/server/workspace-git-metadata.d.ts.map +1 -1
  407. package/dist/server/server/workspace-git-metadata.js +2 -32
  408. package/dist/server/server/workspace-git-metadata.js.map +1 -1
  409. package/dist/server/server/workspace-git-service.d.ts +8 -4
  410. package/dist/server/server/workspace-git-service.d.ts.map +1 -1
  411. package/dist/server/server/workspace-git-service.js +163 -115
  412. package/dist/server/server/workspace-git-service.js.map +1 -1
  413. package/dist/server/server/workspace-reconciliation-service.d.ts +5 -4
  414. package/dist/server/server/workspace-reconciliation-service.d.ts.map +1 -1
  415. package/dist/server/server/workspace-reconciliation-service.js +82 -82
  416. package/dist/server/server/workspace-reconciliation-service.js.map +1 -1
  417. package/dist/server/server/workspace-registry-bootstrap.d.ts.map +1 -1
  418. package/dist/server/server/workspace-registry-bootstrap.js +40 -33
  419. package/dist/server/server/workspace-registry-bootstrap.js.map +1 -1
  420. package/dist/server/server/workspace-registry-model.d.ts +19 -6
  421. package/dist/server/server/workspace-registry-model.d.ts.map +1 -1
  422. package/dist/server/server/workspace-registry-model.js +35 -21
  423. package/dist/server/server/workspace-registry-model.js.map +1 -1
  424. package/dist/server/server/workspace-registry.d.ts +2 -2
  425. package/dist/server/server/workspace-script-runtime-store.d.ts +2 -2
  426. package/dist/server/server/workspace-script-runtime-store.d.ts.map +1 -1
  427. package/dist/server/server/workspace-service-env.js +3 -3
  428. package/dist/server/server/workspace-service-env.js.map +1 -1
  429. package/dist/server/server/worktree-bootstrap.d.ts +4 -4
  430. package/dist/server/server/worktree-bootstrap.d.ts.map +1 -1
  431. package/dist/server/server/worktree-bootstrap.js +101 -69
  432. package/dist/server/server/worktree-bootstrap.js.map +1 -1
  433. package/dist/server/server/worktree-core.d.ts +2 -0
  434. package/dist/server/server/worktree-core.d.ts.map +1 -1
  435. package/dist/server/server/worktree-core.js.map +1 -1
  436. package/dist/server/server/worktree-errors.d.ts +1 -1
  437. package/dist/server/server/worktree-errors.d.ts.map +1 -1
  438. package/dist/server/server/worktree-errors.js +1 -4
  439. package/dist/server/server/worktree-errors.js.map +1 -1
  440. package/dist/server/server/worktree-session.d.ts +54 -27
  441. package/dist/server/server/worktree-session.d.ts.map +1 -1
  442. package/dist/server/server/worktree-session.js +95 -44
  443. package/dist/server/server/worktree-session.js.map +1 -1
  444. package/dist/server/services/github-service.d.ts +1 -7
  445. package/dist/server/services/github-service.d.ts.map +1 -1
  446. package/dist/server/services/github-service.js +123 -143
  447. package/dist/server/services/github-service.js.map +1 -1
  448. package/dist/server/shared/agent-attention-notification.d.ts +9 -8
  449. package/dist/server/shared/agent-attention-notification.d.ts.map +1 -1
  450. package/dist/server/shared/agent-attention-notification.js +27 -17
  451. package/dist/server/shared/agent-attention-notification.js.map +1 -1
  452. package/dist/server/shared/binary-frames/file-transfer.d.ts +56 -0
  453. package/dist/server/shared/binary-frames/file-transfer.d.ts.map +1 -0
  454. package/dist/server/shared/binary-frames/file-transfer.js +108 -0
  455. package/dist/server/shared/binary-frames/file-transfer.js.map +1 -0
  456. package/dist/server/shared/binary-frames/index.d.ts +3 -0
  457. package/dist/server/shared/binary-frames/index.d.ts.map +1 -0
  458. package/dist/server/shared/binary-frames/index.js +3 -0
  459. package/dist/server/shared/binary-frames/index.js.map +1 -0
  460. package/dist/server/shared/{terminal-stream-protocol.d.ts → binary-frames/terminal.d.ts} +4 -4
  461. package/dist/server/shared/binary-frames/terminal.d.ts.map +1 -0
  462. package/dist/server/shared/{terminal-stream-protocol.js → binary-frames/terminal.js} +2 -2
  463. package/dist/server/shared/binary-frames/terminal.js.map +1 -0
  464. package/dist/server/shared/client-capabilities.d.ts +5 -0
  465. package/dist/server/shared/client-capabilities.d.ts.map +1 -0
  466. package/dist/server/shared/client-capabilities.js +4 -0
  467. package/dist/server/shared/client-capabilities.js.map +1 -0
  468. package/dist/server/shared/connection-offer.d.ts +8 -0
  469. package/dist/server/shared/connection-offer.d.ts.map +1 -1
  470. package/dist/server/shared/connection-offer.js +35 -0
  471. package/dist/server/shared/connection-offer.js.map +1 -1
  472. package/dist/server/shared/daemon-endpoints.d.ts +18 -3
  473. package/dist/server/shared/daemon-endpoints.d.ts.map +1 -1
  474. package/dist/server/shared/daemon-endpoints.js +82 -8
  475. package/dist/server/shared/daemon-endpoints.js.map +1 -1
  476. package/dist/server/shared/host-connection-schema.d.ts +23 -0
  477. package/dist/server/shared/host-connection-schema.d.ts.map +1 -0
  478. package/dist/server/shared/host-connection-schema.js +9 -0
  479. package/dist/server/shared/host-connection-schema.js.map +1 -0
  480. package/dist/server/shared/messages.d.ts +25073 -3453
  481. package/dist/server/shared/messages.d.ts.map +1 -1
  482. package/dist/server/shared/messages.js +152 -36
  483. package/dist/server/shared/messages.js.map +1 -1
  484. package/dist/server/shared/tool-call-display.d.ts +2 -2
  485. package/dist/server/shared/tool-call-display.d.ts.map +1 -1
  486. package/dist/server/terminal/terminal-manager-factory.d.ts +7 -0
  487. package/dist/server/terminal/terminal-manager-factory.d.ts.map +1 -0
  488. package/dist/server/terminal/terminal-manager-factory.js +13 -0
  489. package/dist/server/terminal/terminal-manager-factory.js.map +1 -0
  490. package/dist/server/terminal/terminal-manager.d.ts +7 -1
  491. package/dist/server/terminal/terminal-manager.d.ts.map +1 -1
  492. package/dist/server/terminal/terminal-manager.js +15 -4
  493. package/dist/server/terminal/terminal-manager.js.map +1 -1
  494. package/dist/server/terminal/terminal-output-coalescer.d.ts +6 -6
  495. package/dist/server/terminal/terminal-output-coalescer.d.ts.map +1 -1
  496. package/dist/server/terminal/terminal-session-controller.d.ts +63 -0
  497. package/dist/server/terminal/terminal-session-controller.d.ts.map +1 -0
  498. package/dist/server/terminal/terminal-session-controller.js +615 -0
  499. package/dist/server/terminal/terminal-session-controller.js.map +1 -0
  500. package/dist/server/terminal/terminal-ts-loader.mjs +20 -0
  501. package/dist/server/terminal/terminal-worker-process.d.ts +2 -0
  502. package/dist/server/terminal/terminal-worker-process.d.ts.map +1 -0
  503. package/dist/server/terminal/terminal-worker-process.js +221 -0
  504. package/dist/server/terminal/terminal-worker-process.js.map +1 -0
  505. package/dist/server/terminal/terminal-worker-protocol.d.ts +113 -0
  506. package/dist/server/terminal/terminal-worker-protocol.d.ts.map +1 -0
  507. package/dist/server/terminal/terminal-worker-protocol.js +2 -0
  508. package/dist/server/terminal/terminal-worker-protocol.js.map +1 -0
  509. package/dist/server/terminal/terminal.d.ts +10 -2
  510. package/dist/server/terminal/terminal.d.ts.map +1 -1
  511. package/dist/server/terminal/terminal.js +79 -28
  512. package/dist/server/terminal/terminal.js.map +1 -1
  513. package/dist/server/terminal/worker-terminal-manager.d.ts +19 -0
  514. package/dist/server/terminal/worker-terminal-manager.d.ts.map +1 -0
  515. package/dist/server/terminal/worker-terminal-manager.js +466 -0
  516. package/dist/server/terminal/worker-terminal-manager.js.map +1 -0
  517. package/dist/server/utils/checkout-git.d.ts +13 -12
  518. package/dist/server/utils/checkout-git.d.ts.map +1 -1
  519. package/dist/server/utils/checkout-git.js +351 -281
  520. package/dist/server/utils/checkout-git.js.map +1 -1
  521. package/dist/server/utils/directory-suggestions.d.ts.map +1 -1
  522. package/dist/server/utils/directory-suggestions.js +22 -34
  523. package/dist/server/utils/directory-suggestions.js.map +1 -1
  524. package/dist/server/utils/executable.d.ts +1 -14
  525. package/dist/server/utils/executable.d.ts.map +1 -1
  526. package/dist/server/utils/executable.js +13 -49
  527. package/dist/server/utils/executable.js.map +1 -1
  528. package/dist/server/utils/github-remote.d.ts +13 -0
  529. package/dist/server/utils/github-remote.d.ts.map +1 -0
  530. package/dist/server/utils/github-remote.js +128 -0
  531. package/dist/server/utils/github-remote.js.map +1 -0
  532. package/dist/server/utils/paseo-config-file.d.ts +30 -0
  533. package/dist/server/utils/paseo-config-file.d.ts.map +1 -0
  534. package/dist/server/utils/paseo-config-file.js +90 -0
  535. package/dist/server/utils/paseo-config-file.js.map +1 -0
  536. package/dist/server/utils/paseo-config-schema.d.ts +290 -0
  537. package/dist/server/utils/paseo-config-schema.d.ts.map +1 -0
  538. package/dist/server/utils/paseo-config-schema.js +60 -0
  539. package/dist/server/utils/paseo-config-schema.js.map +1 -0
  540. package/dist/server/utils/process-tree.d.ts +25 -0
  541. package/dist/server/utils/process-tree.d.ts.map +1 -0
  542. package/dist/server/utils/process-tree.js +96 -0
  543. package/dist/server/utils/process-tree.js.map +1 -0
  544. package/dist/server/utils/project-icon.d.ts.map +1 -1
  545. package/dist/server/utils/project-icon.js +84 -109
  546. package/dist/server/utils/project-icon.js.map +1 -1
  547. package/dist/server/utils/promise-timeout.d.ts +2 -2
  548. package/dist/server/utils/promise-timeout.d.ts.map +1 -1
  549. package/dist/server/utils/run-git-command.d.ts +3 -1
  550. package/dist/server/utils/run-git-command.d.ts.map +1 -1
  551. package/dist/server/utils/run-git-command.js +10 -1
  552. package/dist/server/utils/run-git-command.js.map +1 -1
  553. package/dist/server/utils/script-hostname.d.ts +2 -2
  554. package/dist/server/utils/script-hostname.d.ts.map +1 -1
  555. package/dist/server/utils/spawn.d.ts +10 -3
  556. package/dist/server/utils/spawn.d.ts.map +1 -1
  557. package/dist/server/utils/spawn.js +30 -5
  558. package/dist/server/utils/spawn.js.map +1 -1
  559. package/dist/server/utils/windows-command.d.ts +15 -0
  560. package/dist/server/utils/windows-command.d.ts.map +1 -0
  561. package/dist/server/utils/windows-command.js +41 -0
  562. package/dist/server/utils/windows-command.js.map +1 -0
  563. package/dist/server/utils/worktree-metadata.d.ts +44 -0
  564. package/dist/server/utils/worktree-metadata.d.ts.map +1 -1
  565. package/dist/server/utils/worktree-metadata.js +58 -0
  566. package/dist/server/utils/worktree-metadata.js.map +1 -1
  567. package/dist/server/utils/worktree.d.ts +23 -8
  568. package/dist/server/utils/worktree.d.ts.map +1 -1
  569. package/dist/server/utils/worktree.js +81 -63
  570. package/dist/server/utils/worktree.js.map +1 -1
  571. package/dist/src/server/pid-lock.js.map +1 -1
  572. package/package.json +17 -21
  573. package/dist/server/server/agent/llm-openai.d.ts +0 -7
  574. package/dist/server/server/agent/llm-openai.d.ts.map +0 -1
  575. package/dist/server/server/agent/llm-openai.js +0 -8
  576. package/dist/server/server/agent/llm-openai.js.map +0 -1
  577. package/dist/server/server/agent/orchestrator.d.ts +0 -12
  578. package/dist/server/server/agent/orchestrator.d.ts.map +0 -1
  579. package/dist/server/server/agent/orchestrator.js +0 -12
  580. package/dist/server/server/agent/orchestrator.js.map +0 -1
  581. package/dist/server/server/types.d.ts +0 -5
  582. package/dist/server/server/types.d.ts.map +0 -1
  583. package/dist/server/server/types.js +0 -3
  584. package/dist/server/server/types.js.map +0 -1
  585. package/dist/server/server/workspace-registry.test-helpers.d.ts +0 -37
  586. package/dist/server/server/workspace-registry.test-helpers.d.ts.map +0 -1
  587. package/dist/server/server/workspace-registry.test-helpers.js +0 -121
  588. package/dist/server/server/workspace-registry.test-helpers.js.map +0 -1
  589. package/dist/server/shared/terminal-stream-protocol.d.ts.map +0 -1
  590. package/dist/server/shared/terminal-stream-protocol.js.map +0 -1
@@ -2,12 +2,15 @@ import { homedir } from "node:os";
2
2
  import { createOpencodeClient, } from "@opencode-ai/sdk/v2/client";
3
3
  import net from "node:net";
4
4
  import { z } from "zod";
5
- import { applyProviderEnv, resolveProviderCommandPrefix, } from "../provider-launch-config.js";
5
+ import { createProviderEnvSpec, resolveProviderCommandPrefix, } from "../provider-launch-config.js";
6
6
  import { findExecutable, isCommandAvailable } from "../../../utils/executable.js";
7
+ import { terminateProcessTree } from "../../../utils/process-tree.js";
7
8
  import { withTimeout } from "../../../utils/promise-timeout.js";
8
9
  import { spawnProcess } from "../../../utils/spawn.js";
10
+ import { buildToolCallDisplayModel } from "../../../shared/tool-call-display.js";
9
11
  import { mapOpencodeToolCall } from "./opencode/tool-call-mapper.js";
10
12
  import { formatDiagnosticStatus, formatProviderDiagnostic, formatProviderDiagnosticError, resolveBinaryVersion, toDiagnosticErrorMessage, } from "./diagnostic-utils.js";
13
+ import { runProviderTurn } from "./provider-runner.js";
11
14
  import { renderPromptAttachmentAsText } from "../prompt-attachments.js";
12
15
  const OPENCODE_CAPABILITIES = {
13
16
  supportsStreaming: true,
@@ -17,9 +20,11 @@ const OPENCODE_CAPABILITIES = {
17
20
  supportsReasoningStream: true,
18
21
  supportsToolInvocations: true,
19
22
  };
23
+ const OPENCODE_BUILD_MODE_ID = "build";
24
+ const OPENCODE_FULL_ACCESS_MODE_ID = "full-access";
20
25
  const DEFAULT_MODES = [
21
26
  {
22
- id: "build",
27
+ id: OPENCODE_BUILD_MODE_ID,
23
28
  label: "Build",
24
29
  description: "Allows edits and tool execution for implementation work",
25
30
  },
@@ -28,9 +33,20 @@ const DEFAULT_MODES = [
28
33
  label: "Plan",
29
34
  description: "Read-only planning mode that avoids file edits",
30
35
  },
36
+ {
37
+ id: OPENCODE_FULL_ACCESS_MODE_ID,
38
+ label: "Full Access",
39
+ description: "Automatically approves all tool permission prompts for the session",
40
+ },
31
41
  ];
32
42
  const MCP_ALREADY_PRESENT_ERROR_TOKENS = ["already", "exists", "connected"];
33
43
  const OPENCODE_PROVIDER_LIST_TIMEOUT_MS = 30000;
44
+ const OPENCODE_SERVER_GRACEFUL_SHUTDOWN_TIMEOUT_MS = 5000;
45
+ const OPENCODE_SERVER_FORCE_SHUTDOWN_TIMEOUT_MS = 1000;
46
+ const OPENCODE_HANDLED_BUILTIN_SLASH_COMMANDS = [
47
+ { name: "compact", description: "Compact the current session", argumentHint: "" },
48
+ { name: "summarize", description: "Compact the current session", argumentHint: "" },
49
+ ];
34
50
  const OPENCODE_FATAL_RETRY_MESSAGE_TOKENS = [
35
51
  "insufficient balance",
36
52
  "no resource package",
@@ -140,20 +156,18 @@ function toOpenCodeMcpConfig(config) {
140
156
  enabled: true,
141
157
  };
142
158
  }
143
- function stringifyUnknownError(error) {
144
- if (typeof error === "string") {
145
- return error;
146
- }
147
- try {
148
- return JSON.stringify(error);
159
+ function toTerminalTurnEvent(event) {
160
+ if (event.type === "turn_failed") {
161
+ return {
162
+ type: "turn_failed",
163
+ provider: "opencode",
164
+ error: toDiagnosticErrorMessage(event.error),
165
+ };
149
166
  }
150
- catch {
151
- return String(error);
167
+ if (event.type === "turn_completed" || event.type === "turn_canceled") {
168
+ return event;
152
169
  }
153
- }
154
- function normalizeTurnFailureError(error) {
155
- const normalized = stringifyUnknownError(error).trim();
156
- return normalized.length > 0 ? normalized : "Unknown error";
170
+ return null;
157
171
  }
158
172
  function isOpenCodeNotFoundError(error) {
159
173
  return (typeof error === "object" &&
@@ -171,14 +185,14 @@ async function reconcileOpenCodeSessionClose(params) {
171
185
  if (response.error && !isOpenCodeNotFoundError(response.error)) {
172
186
  logger.warn({
173
187
  sessionId,
174
- error: normalizeTurnFailureError(response.error),
188
+ error: toDiagnosticErrorMessage(response.error),
175
189
  }, "Failed to abort OpenCode session during close");
176
190
  }
177
191
  }
178
192
  catch (error) {
179
193
  logger.warn({
180
194
  sessionId,
181
- error: normalizeTurnFailureError(error),
195
+ error: toDiagnosticErrorMessage(error),
182
196
  }, "Failed to abort OpenCode session during close");
183
197
  }
184
198
  try {
@@ -190,14 +204,14 @@ async function reconcileOpenCodeSessionClose(params) {
190
204
  if (response.error && !isOpenCodeNotFoundError(response.error)) {
191
205
  logger.warn({
192
206
  sessionId,
193
- error: normalizeTurnFailureError(response.error),
207
+ error: toDiagnosticErrorMessage(response.error),
194
208
  }, "Failed to archive OpenCode session during close");
195
209
  }
196
210
  }
197
211
  catch (error) {
198
212
  logger.warn({
199
213
  sessionId,
200
- error: normalizeTurnFailureError(error),
214
+ error: toDiagnosticErrorMessage(error),
201
215
  }, "Failed to archive OpenCode session during close");
202
216
  }
203
217
  }
@@ -216,18 +230,19 @@ function isOpenCodeHeadersTimeoutFailure(error) {
216
230
  if (!current) {
217
231
  continue;
218
232
  }
219
- const normalized = stringifyUnknownError(current).trim().toLowerCase();
233
+ const normalized = toDiagnosticErrorMessage(current).trim().toLowerCase();
220
234
  if (normalized) {
221
235
  diagnostics.add(normalized);
222
236
  }
223
237
  if (typeof current === "object") {
224
238
  const record = current;
225
239
  for (const value of [record.message, record.code, record.name]) {
226
- if (typeof value === "string") {
227
- const diagnostic = value.trim().toLowerCase();
228
- if (diagnostic) {
229
- diagnostics.add(diagnostic);
230
- }
240
+ if (typeof value !== "string") {
241
+ continue;
242
+ }
243
+ const diagnostic = value.trim().toLowerCase();
244
+ if (diagnostic) {
245
+ diagnostics.add(diagnostic);
231
246
  }
232
247
  }
233
248
  if (record.cause) {
@@ -238,7 +253,7 @@ function isOpenCodeHeadersTimeoutFailure(error) {
238
253
  return [...diagnostics].some((diagnostic) => OPENCODE_HEADERS_TIMEOUT_TOKENS.some((token) => diagnostic.includes(token)));
239
254
  }
240
255
  function isAlreadyPresentMcpError(error) {
241
- const normalized = stringifyUnknownError(error).toLowerCase();
256
+ const normalized = toDiagnosticErrorMessage(error).toLowerCase();
242
257
  return MCP_ALREADY_PRESENT_ERROR_TOKENS.some((token) => normalized.includes(token));
243
258
  }
244
259
  async function findAvailablePort() {
@@ -269,10 +284,26 @@ function resolvePartDedupeKey(part, partType) {
269
284
  function normalizeOpenCodeModeId(modeId) {
270
285
  const trimmed = typeof modeId === "string" ? modeId.trim() : "";
271
286
  if (!trimmed || trimmed === "default") {
272
- return "build";
287
+ return OPENCODE_BUILD_MODE_ID;
273
288
  }
274
289
  return trimmed;
275
290
  }
291
+ function resolveOpenCodeRuntimeAgentId(modeId) {
292
+ const normalizedModeId = normalizeOpenCodeModeId(modeId);
293
+ return normalizedModeId === OPENCODE_FULL_ACCESS_MODE_ID
294
+ ? OPENCODE_BUILD_MODE_ID
295
+ : normalizedModeId;
296
+ }
297
+ function isSelectableOpenCodeAgent(agent) {
298
+ return (agent.mode === "primary" || agent.mode === "all") && agent.hidden !== true;
299
+ }
300
+ function mergeOpenCodeModes(discoveredModes) {
301
+ const modesById = new Map(DEFAULT_MODES.map((mode) => [mode.id, mode]));
302
+ for (const mode of discoveredModes) {
303
+ modesById.set(mode.id, mode);
304
+ }
305
+ return sortOpenCodeModes(Array.from(modesById.values()));
306
+ }
276
307
  function sortOpenCodeModes(modes) {
277
308
  const order = new Map(DEFAULT_MODES.map((mode, index) => [mode.id, index]));
278
309
  return [...modes].sort((left, right) => {
@@ -458,18 +489,18 @@ function buildOpenCodePromptParts(prompt) {
458
489
  output.push({ type: "text", text: part.text });
459
490
  continue;
460
491
  }
461
- if (part.type === "github_pr" || part.type === "github_issue") {
462
- output.push({ type: "text", text: renderPromptAttachmentAsText(part) });
492
+ if (part.type === "image") {
493
+ attachmentOrdinal += 1;
494
+ const normalized = toOpenCodeDataUrl(part.mimeType, part.data);
495
+ output.push({
496
+ type: "file",
497
+ mime: normalized.mimeType,
498
+ filename: `attachment-${attachmentOrdinal}.${getOpenCodeAttachmentExtension(normalized.mimeType)}`,
499
+ url: normalized.url,
500
+ });
463
501
  continue;
464
502
  }
465
- attachmentOrdinal += 1;
466
- const normalized = toOpenCodeDataUrl(part.mimeType, part.data);
467
- output.push({
468
- type: "file",
469
- mime: normalized.mimeType,
470
- filename: `attachment-${attachmentOrdinal}.${getOpenCodeAttachmentExtension(normalized.mimeType)}`,
471
- url: normalized.url,
472
- });
503
+ output.push({ type: "text", text: renderPromptAttachmentAsText(part) });
473
504
  }
474
505
  return output;
475
506
  }
@@ -485,6 +516,10 @@ export const __openCodeInternals = {
485
516
  reconcileOpenCodeSessionClose,
486
517
  resolveOpenCodeModelLookupKeyFromAssistantMessage,
487
518
  resolveOpenCodeSelectedModelContextWindow,
519
+ isSelectableOpenCodeAgent,
520
+ get OpenCodeAgentSession() {
521
+ return OpenCodeAgentSession;
522
+ },
488
523
  };
489
524
  export class OpenCodeServerManager {
490
525
  constructor(logger, runtimeSettings) {
@@ -601,17 +636,41 @@ export class OpenCodeServerManager {
601
636
  const launchPrefix = await resolveProviderCommandPrefix(this.runtimeSettings?.command, resolveOpenCodeBinary);
602
637
  return new Promise((resolve, reject) => {
603
638
  const serverProcess = spawnProcess(launchPrefix.command, [...launchPrefix.args, "serve", "--port", String(port)], {
639
+ detached: process.platform !== "win32",
604
640
  stdio: ["ignore", "pipe", "pipe"],
605
- env: applyProviderEnv(process.env, this.runtimeSettings),
641
+ ...createProviderEnvSpec({ runtimeSettings: this.runtimeSettings }),
606
642
  });
607
643
  let started = false;
644
+ let stderrBuffer = "";
645
+ let stdoutBuffer = "";
646
+ const STARTUP_BUFFER_CAP = 8192;
647
+ const appendCapped = (current, chunk) => {
648
+ if (current.length >= STARTUP_BUFFER_CAP) {
649
+ return current;
650
+ }
651
+ const remaining = STARTUP_BUFFER_CAP - current.length;
652
+ return current + chunk.slice(0, remaining);
653
+ };
654
+ const buildStartupErrorMessage = (headline) => {
655
+ const sections = [headline];
656
+ const stderrTrimmed = stderrBuffer.trim();
657
+ if (stderrTrimmed.length > 0) {
658
+ sections.push(`stderr: ${stderrTrimmed}`);
659
+ }
660
+ const stdoutTrimmed = stdoutBuffer.trim();
661
+ if (stdoutTrimmed.length > 0) {
662
+ sections.push(`stdout: ${stdoutTrimmed}`);
663
+ }
664
+ return sections.join("\n");
665
+ };
608
666
  const timeout = setTimeout(() => {
609
667
  if (!started) {
610
- reject(new Error("OpenCode server startup timeout"));
668
+ reject(new Error(buildStartupErrorMessage("OpenCode server startup timeout")));
611
669
  }
612
670
  }, 30000);
613
671
  serverProcess.stdout?.on("data", (data) => {
614
672
  const output = data.toString();
673
+ stdoutBuffer = appendCapped(stdoutBuffer, output);
615
674
  if (output.includes("listening on") && !started) {
616
675
  started = true;
617
676
  clearTimeout(timeout);
@@ -625,16 +684,19 @@ export class OpenCodeServerManager {
625
684
  }
626
685
  });
627
686
  serverProcess.stderr?.on("data", (data) => {
628
- this.logger.error({ stderr: data.toString().trim() }, "OpenCode server stderr");
687
+ const output = data.toString();
688
+ stderrBuffer = appendCapped(stderrBuffer, output);
689
+ this.logger.error({ stderr: output.trim() }, "OpenCode server stderr");
629
690
  });
630
691
  serverProcess.on("error", (error) => {
631
692
  clearTimeout(timeout);
632
- reject(error);
693
+ const headline = error instanceof Error ? error.message : String(error);
694
+ reject(new Error(buildStartupErrorMessage(headline)));
633
695
  });
634
696
  serverProcess.on("exit", (code) => {
635
697
  if (!started) {
636
698
  clearTimeout(timeout);
637
- reject(new Error(`OpenCode server exited with code ${code}`));
699
+ reject(new Error(buildStartupErrorMessage(`OpenCode server exited with code ${code}`)));
638
700
  }
639
701
  if (this.currentServer?.process === serverProcess) {
640
702
  this.currentServer = null;
@@ -652,9 +714,7 @@ export class OpenCodeServerManager {
652
714
  ...(this.currentServer ? [this.currentServer] : []),
653
715
  ...Array.from(this.retiredServers),
654
716
  ];
655
- for (const server of servers) {
656
- await this.killServer(server);
657
- }
717
+ await Promise.all(servers.map((server) => this.killServer(server)));
658
718
  this.currentServer = null;
659
719
  this.retiredServers.clear();
660
720
  }
@@ -670,17 +730,16 @@ export class OpenCodeServerManager {
670
730
  if (server.process.killed) {
671
731
  return;
672
732
  }
673
- await new Promise((resolve) => {
674
- const timeout = setTimeout(() => {
675
- server.process.kill("SIGKILL");
676
- resolve();
677
- }, 5000);
678
- server.process.on("exit", () => {
679
- clearTimeout(timeout);
680
- resolve();
681
- });
682
- server.process.kill("SIGTERM");
733
+ const result = await terminateProcessTree(server.process, {
734
+ gracefulTimeoutMs: OPENCODE_SERVER_GRACEFUL_SHUTDOWN_TIMEOUT_MS,
735
+ forceTimeoutMs: OPENCODE_SERVER_FORCE_SHUTDOWN_TIMEOUT_MS,
736
+ onForceSignal: () => {
737
+ this.logger.warn({ timeoutMs: OPENCODE_SERVER_GRACEFUL_SHUTDOWN_TIMEOUT_MS }, "OpenCode server did not exit after SIGTERM; sending SIGKILL");
738
+ },
683
739
  });
740
+ if (result === "kill-timeout") {
741
+ this.logger.warn({ timeoutMs: OPENCODE_SERVER_FORCE_SHUTDOWN_TIMEOUT_MS }, "OpenCode server did not report exit after SIGKILL");
742
+ }
684
743
  }
685
744
  }
686
745
  OpenCodeServerManager.instance = null;
@@ -801,16 +860,14 @@ export class OpenCodeAgentClient {
801
860
  if (response.error || !response.data) {
802
861
  return DEFAULT_MODES;
803
862
  }
804
- const discovered = response.data
805
- .filter((agent) => agent.mode === "primary" && agent.hidden !== true)
806
- .map((agent) => ({
863
+ const discovered = response.data.filter(isSelectableOpenCodeAgent).map((agent) => ({
807
864
  id: agent.name,
808
865
  label: agent.name.charAt(0).toUpperCase() + agent.name.slice(1),
809
866
  description: typeof agent.description === "string" && agent.description.trim().length > 0
810
867
  ? agent.description.trim()
811
868
  : DEFAULT_MODES.find((mode) => mode.id === agent.name)?.description,
812
869
  }));
813
- return discovered.length > 0 ? sortOpenCodeModes(discovered) : DEFAULT_MODES;
870
+ return mergeOpenCodeModes(discovered);
814
871
  }
815
872
  finally {
816
873
  acquisition.release();
@@ -839,7 +896,7 @@ export class OpenCodeAgentClient {
839
896
  serverStatus = `Running (${url})`;
840
897
  }
841
898
  catch (error) {
842
- serverStatus = `Unavailable (${normalizeTurnFailureError(error)})`;
899
+ serverStatus = `Unavailable (${toDiagnosticErrorMessage(error)})`;
843
900
  }
844
901
  if (available) {
845
902
  try {
@@ -905,6 +962,8 @@ export class OpenCodeAgentClient {
905
962
  }
906
963
  }
907
964
  }
965
+ const MAX_OPENCODE_SUB_AGENT_ACTIONS = 200;
966
+ const MAX_OPENCODE_PENDING_CHILD_TOOL_PARTS = 200;
908
967
  function stringifyStructuredAssistantMessage(value) {
909
968
  if (value === undefined) {
910
969
  return null;
@@ -1039,309 +1098,518 @@ export function translateOpenCodeEvent(event, state) {
1039
1098
  const events = [];
1040
1099
  switch (event.type) {
1041
1100
  case "session.created":
1042
- case "session.updated": {
1043
- if (event.properties.info.id === state.sessionId) {
1044
- events.push({
1045
- type: "thread_started",
1046
- sessionId: state.sessionId,
1047
- provider: "opencode",
1048
- });
1049
- }
1101
+ case "session.updated":
1102
+ appendOpenCodeSessionCreatedOrUpdated(event, state, events);
1050
1103
  break;
1051
- }
1052
- case "message.updated": {
1053
- const info = event.properties.info;
1054
- if (info.sessionID !== state.sessionId) {
1055
- break;
1056
- }
1057
- state.messageRoles.set(info.id, info.role);
1058
- if (info.role === "assistant") {
1059
- const modelLookupKey = resolveOpenCodeModelLookupKeyFromAssistantMessage(info);
1060
- if (modelLookupKey) {
1061
- const contextWindowMaxTokens = state.modelContextWindowsByModelKey?.get(modelLookupKey);
1062
- if (contextWindowMaxTokens !== undefined) {
1063
- state.onAssistantModelContextWindowResolved?.(contextWindowMaxTokens);
1064
- }
1065
- }
1066
- if (!state.emittedStructuredMessageIds.has(info.id) && info.time?.completed !== undefined) {
1067
- const text = stringifyStructuredAssistantMessage(info.structured);
1068
- if (text) {
1069
- state.emittedStructuredMessageIds.add(info.id);
1070
- events.push({
1071
- type: "timeline",
1072
- provider: "opencode",
1073
- item: { type: "assistant_message", text },
1074
- });
1075
- }
1076
- }
1077
- }
1104
+ case "message.updated":
1105
+ appendOpenCodeMessageUpdated(event, state, events);
1078
1106
  break;
1079
- }
1080
- case "message.part.updated": {
1081
- const part = event.properties.part;
1082
- if (part.sessionID !== state.sessionId) {
1083
- break;
1084
- }
1085
- const messageRole = state.messageRoles.get(part.messageID);
1086
- state.partTypes.set(part.id, part.type);
1087
- if (part.type === "text") {
1088
- const partKey = resolvePartDedupeKey(part, "text");
1089
- if (messageRole === "user") {
1090
- break;
1091
- }
1092
- if (part.time?.end) {
1093
- if (partKey && state.streamedPartKeys.delete(partKey)) {
1094
- break;
1095
- }
1096
- if (part.text) {
1097
- events.push({
1098
- type: "timeline",
1099
- provider: "opencode",
1100
- item: { type: "assistant_message", text: part.text },
1101
- });
1102
- }
1103
- }
1104
- }
1105
- else if (part.type === "reasoning") {
1106
- const partKey = resolvePartDedupeKey(part, "reasoning");
1107
- if (part.time.end) {
1108
- if (partKey && state.streamedPartKeys.delete(partKey)) {
1109
- break;
1110
- }
1111
- if (part.text) {
1112
- events.push({
1113
- type: "timeline",
1114
- provider: "opencode",
1115
- item: { type: "reasoning", text: part.text },
1116
- });
1117
- }
1118
- }
1119
- }
1120
- else if (part.type === "tool") {
1121
- const parsedToolPart = OpencodeToolPartToTimelineItemSchema.safeParse(part);
1122
- if (parsedToolPart.success && parsedToolPart.data) {
1123
- events.push({
1124
- type: "timeline",
1125
- provider: "opencode",
1126
- item: parsedToolPart.data,
1127
- });
1128
- }
1129
- }
1130
- else if (part.type === "compaction") {
1107
+ case "message.part.updated":
1108
+ appendOpenCodeMessagePartUpdated(event, state, events);
1109
+ break;
1110
+ case "message.part.delta":
1111
+ appendOpenCodeMessagePartDelta(event, state, events);
1112
+ break;
1113
+ case "permission.asked":
1114
+ appendOpenCodePermissionAsked(event, state, events);
1115
+ break;
1116
+ case "question.asked":
1117
+ appendOpenCodeQuestionAsked(event, state, events);
1118
+ break;
1119
+ case "todo.updated":
1120
+ if (event.properties.sessionID === state.sessionId) {
1131
1121
  events.push({
1132
1122
  type: "timeline",
1133
1123
  provider: "opencode",
1134
- item: createCompactionTimelineItem("loading", part.auto ? "auto" : "manual"),
1124
+ item: mapOpenCodeTodosToTimelineItems(event.properties.todos),
1135
1125
  });
1136
1126
  }
1137
- else if (part.type === "step-finish") {
1138
- mergeOpenCodeStepFinishUsage(state.accumulatedUsage, part);
1139
- if (hasNormalizedOpenCodeUsage(state.accumulatedUsage)) {
1140
- events.push({
1141
- type: "usage_updated",
1142
- provider: "opencode",
1143
- usage: { ...state.accumulatedUsage },
1144
- });
1145
- }
1146
- }
1147
1127
  break;
1148
- }
1149
- case "message.part.delta": {
1150
- const { sessionID, messageID, partID, field, delta } = event.properties;
1151
- if (sessionID !== state.sessionId) {
1152
- break;
1153
- }
1154
- if (!delta || !field) {
1155
- break;
1156
- }
1157
- const messageRole = messageID ? state.messageRoles.get(messageID) : undefined;
1158
- const knownPartType = partID ? state.partTypes.get(partID) : undefined;
1159
- const isReasoning = knownPartType === "reasoning" || field === "reasoning";
1160
- if (isReasoning) {
1161
- if (partID) {
1162
- state.streamedPartKeys.add(`reasoning:${partID}`);
1163
- }
1128
+ case "session.compacted":
1129
+ if (event.properties.sessionID === state.sessionId) {
1164
1130
  events.push({
1165
1131
  type: "timeline",
1166
1132
  provider: "opencode",
1167
- item: { type: "reasoning", text: delta },
1133
+ item: createCompactionTimelineItem("completed"),
1168
1134
  });
1169
1135
  }
1170
- else if (field === "text") {
1171
- if (messageRole === "user") {
1172
- break;
1173
- }
1174
- if (partID) {
1175
- state.streamedPartKeys.add(`text:${partID}`);
1176
- }
1136
+ break;
1137
+ case "session.idle":
1138
+ if (event.properties.sessionID === state.sessionId) {
1139
+ resetOpenCodeTurnTrackingState(state);
1140
+ events.push({ type: "turn_completed", provider: "opencode", usage: undefined });
1141
+ }
1142
+ break;
1143
+ case "session.error":
1144
+ if (event.properties.sessionID === state.sessionId) {
1145
+ resetOpenCodeTurnTrackingState(state);
1177
1146
  events.push({
1178
- type: "timeline",
1147
+ type: "turn_failed",
1179
1148
  provider: "opencode",
1180
- item: { type: "assistant_message", text: delta },
1149
+ error: toDiagnosticErrorMessage(event.properties.error),
1181
1150
  });
1182
1151
  }
1183
1152
  break;
1184
- }
1185
- case "permission.asked": {
1186
- if (event.properties.sessionID !== state.sessionId) {
1187
- break;
1188
- }
1189
- const metadata = readOpenCodeRecord(event.properties.metadata);
1190
- const tool = readOpenCodeRecord(event.properties.tool);
1191
- const patterns = Array.isArray(event.properties.patterns)
1192
- ? event.properties.patterns.filter((value) => typeof value === "string")
1193
- : [];
1194
- const command = readPermissionField(metadata, PERMISSION_COMMAND_KEYS);
1195
- const cwd = readPermissionField(metadata, PERMISSION_CWD_KEYS);
1196
- const reason = readPermissionField(metadata, PERMISSION_REASON_KEYS);
1197
- const input = buildOpenCodePermissionInput({
1198
- patterns,
1199
- metadata,
1200
- tool,
1201
- command,
1202
- });
1203
- const detail = buildOpenCodePermissionDetail({
1204
- permission: event.properties.permission,
1205
- input,
1206
- command,
1207
- cwd,
1208
- });
1209
- const description = buildOpenCodePermissionDescription({
1210
- reason,
1211
- patterns,
1212
- });
1213
- events.push({
1214
- type: "permission_requested",
1215
- provider: "opencode",
1216
- request: {
1217
- id: event.properties.id,
1218
- provider: "opencode",
1219
- name: event.properties.permission,
1220
- kind: "tool",
1221
- title: toHumanReadablePermissionTitle(event.properties.permission),
1222
- ...(description ? { description } : {}),
1223
- input,
1224
- detail,
1225
- },
1226
- });
1153
+ case "session.status":
1154
+ appendOpenCodeSessionStatus(event, state, events);
1227
1155
  break;
1156
+ }
1157
+ return events;
1158
+ }
1159
+ function resetOpenCodeTurnTrackingState(state) {
1160
+ state.streamedPartKeys.clear();
1161
+ state.partTypes.clear();
1162
+ }
1163
+ function getOpenCodeSubAgentMaps(state) {
1164
+ state.subAgentsByCallId ?? (state.subAgentsByCallId = new Map());
1165
+ state.subAgentCallIdByChildSessionId ?? (state.subAgentCallIdByChildSessionId = new Map());
1166
+ state.pendingChildToolPartsBySessionId ?? (state.pendingChildToolPartsBySessionId = new Map());
1167
+ return {
1168
+ byCallId: state.subAgentsByCallId,
1169
+ callIdByChildSessionId: state.subAgentCallIdByChildSessionId,
1170
+ pendingChildToolPartsBySessionId: state.pendingChildToolPartsBySessionId,
1171
+ };
1172
+ }
1173
+ function getOpenCodeSubAgentState(callId, state, toolCall) {
1174
+ const maps = getOpenCodeSubAgentMaps(state);
1175
+ const existing = maps.byCallId.get(callId);
1176
+ if (existing) {
1177
+ existing.toolCall = toolCall;
1178
+ return existing;
1179
+ }
1180
+ const created = {
1181
+ toolCall,
1182
+ actions: [],
1183
+ actionIndexByKey: new Map(),
1184
+ nextActionIndex: 1,
1185
+ };
1186
+ maps.byCallId.set(callId, created);
1187
+ return created;
1188
+ }
1189
+ function linkOpenCodeSubAgentChildSession(activity, childSessionId, state) {
1190
+ activity.childSessionId = childSessionId;
1191
+ const maps = getOpenCodeSubAgentMaps(state);
1192
+ maps.callIdByChildSessionId.set(childSessionId, activity.toolCall.callId);
1193
+ }
1194
+ function buildOpenCodeSubAgentLog(detail, activity) {
1195
+ const actionLog = activity.actions
1196
+ .map((action) => action.summary ? `[${action.toolName}] ${action.summary}` : `[${action.toolName}]`)
1197
+ .join("\n");
1198
+ const parts = [actionLog, detail.log].filter((part) => part.trim().length > 0);
1199
+ return parts.join("\n\n");
1200
+ }
1201
+ function buildOpenCodeSubAgentTimelineItem(activity) {
1202
+ const toolCall = activity.toolCall;
1203
+ if (toolCall.detail.type !== "sub_agent") {
1204
+ return toolCall;
1205
+ }
1206
+ const childSessionId = activity.childSessionId ?? toolCall.detail.childSessionId;
1207
+ return {
1208
+ ...toolCall,
1209
+ detail: {
1210
+ ...toolCall.detail,
1211
+ ...(childSessionId ? { childSessionId } : {}),
1212
+ log: buildOpenCodeSubAgentLog(toolCall.detail, activity),
1213
+ },
1214
+ };
1215
+ }
1216
+ function registerOpenCodeSubAgentToolCall(item, state) {
1217
+ if (item.detail.type !== "sub_agent") {
1218
+ return item;
1219
+ }
1220
+ const activity = getOpenCodeSubAgentState(item.callId, state, item);
1221
+ if (item.detail.childSessionId) {
1222
+ linkOpenCodeSubAgentChildSession(activity, item.detail.childSessionId, state);
1223
+ }
1224
+ return buildOpenCodeSubAgentTimelineItem(activity);
1225
+ }
1226
+ function bufferOpenCodeSubAgentChildToolPart(part, state) {
1227
+ const maps = getOpenCodeSubAgentMaps(state);
1228
+ if (maps.byCallId.size === 0) {
1229
+ return;
1230
+ }
1231
+ const totalPending = [...maps.pendingChildToolPartsBySessionId.values()].reduce((total, parts) => total + parts.length, 0);
1232
+ if (totalPending >= MAX_OPENCODE_PENDING_CHILD_TOOL_PARTS) {
1233
+ return;
1234
+ }
1235
+ const pending = maps.pendingChildToolPartsBySessionId.get(part.sessionID) ?? [];
1236
+ pending.push(part);
1237
+ maps.pendingChildToolPartsBySessionId.set(part.sessionID, pending);
1238
+ }
1239
+ function flushOpenCodeSubAgentChildToolParts(childSessionId, state, events) {
1240
+ const maps = getOpenCodeSubAgentMaps(state);
1241
+ const pending = maps.pendingChildToolPartsBySessionId.get(childSessionId);
1242
+ if (!pending || pending.length === 0) {
1243
+ return;
1244
+ }
1245
+ maps.pendingChildToolPartsBySessionId.delete(childSessionId);
1246
+ for (const part of pending) {
1247
+ appendOpenCodeSubAgentChildToolPart(part, state, events);
1248
+ }
1249
+ }
1250
+ function findOnlyOpenCodeSubAgentWaitingForChild(state) {
1251
+ const maps = getOpenCodeSubAgentMaps(state);
1252
+ const candidates = [...maps.byCallId.values()].filter((activity) => activity.toolCall.status === "running" &&
1253
+ activity.toolCall.detail.type === "sub_agent" &&
1254
+ !activity.childSessionId);
1255
+ return candidates.length === 1 ? (candidates[0] ?? null) : null;
1256
+ }
1257
+ function summarizeOpenCodeSubAgentAction(item, cwd) {
1258
+ const display = buildToolCallDisplayModel({
1259
+ name: item.name,
1260
+ status: item.status,
1261
+ error: item.error,
1262
+ metadata: item.metadata,
1263
+ detail: item.detail,
1264
+ cwd,
1265
+ });
1266
+ return display.summary ?? display.errorText;
1267
+ }
1268
+ function appendOpenCodeSubAgentAction(activity, item, cwd) {
1269
+ const key = item.callId || `${item.name}:${activity.actions.length}`;
1270
+ const existingIndex = activity.actionIndexByKey.get(key);
1271
+ const summary = summarizeOpenCodeSubAgentAction(item, cwd);
1272
+ if (existingIndex !== undefined) {
1273
+ const action = activity.actions[existingIndex];
1274
+ if (!action) {
1275
+ return false;
1276
+ }
1277
+ const changed = action.toolName !== item.name || action.summary !== summary;
1278
+ action.toolName = item.name;
1279
+ if (summary) {
1280
+ action.summary = summary;
1228
1281
  }
1229
- case "question.asked": {
1230
- if (event.properties.sessionID !== state.sessionId) {
1231
- break;
1232
- }
1233
- const questions = event.properties.questions.flatMap((q) => {
1234
- if (!q.question || !q.header) {
1235
- return [];
1236
- }
1237
- const options = q.options?.map((o) => ({
1238
- label: o.label,
1239
- ...(o.description ? { description: o.description } : {}),
1240
- })) ?? [];
1241
- return [
1242
- {
1243
- question: q.question,
1244
- header: q.header,
1245
- options,
1246
- ...(q.multiple === true ? { multiSelect: true } : {}),
1247
- },
1248
- ];
1249
- });
1250
- if (questions.length === 0) {
1251
- break;
1252
- }
1253
- events.push({
1254
- type: "permission_requested",
1255
- provider: "opencode",
1256
- request: {
1257
- id: event.properties.id,
1258
- provider: "opencode",
1259
- name: "question",
1260
- kind: "question",
1261
- title: "Question",
1262
- input: { questions },
1263
- metadata: {
1264
- source: "opencode_question",
1265
- ...(event.properties.tool ?? {}),
1266
- },
1267
- },
1268
- });
1269
- break;
1282
+ else {
1283
+ delete action.summary;
1270
1284
  }
1271
- case "todo.updated": {
1272
- if (event.properties.sessionID !== state.sessionId) {
1273
- break;
1274
- }
1275
- events.push({
1276
- type: "timeline",
1277
- provider: "opencode",
1278
- item: mapOpenCodeTodosToTimelineItems(event.properties.todos),
1279
- });
1280
- break;
1285
+ return changed;
1286
+ }
1287
+ if (activity.actions.length >= MAX_OPENCODE_SUB_AGENT_ACTIONS) {
1288
+ return false;
1289
+ }
1290
+ activity.actionIndexByKey.set(key, activity.actions.length);
1291
+ activity.actions.push({
1292
+ index: activity.nextActionIndex,
1293
+ key,
1294
+ toolName: item.name,
1295
+ ...(summary ? { summary } : {}),
1296
+ });
1297
+ activity.nextActionIndex += 1;
1298
+ return true;
1299
+ }
1300
+ function appendOpenCodeToolCallTimelineItem(item, state, events) {
1301
+ const timelineItem = registerOpenCodeSubAgentToolCall(item, state);
1302
+ events.push({
1303
+ type: "timeline",
1304
+ provider: "opencode",
1305
+ item: timelineItem,
1306
+ });
1307
+ if (timelineItem.detail.type === "sub_agent" && timelineItem.detail.childSessionId) {
1308
+ flushOpenCodeSubAgentChildToolParts(timelineItem.detail.childSessionId, state, events);
1309
+ }
1310
+ }
1311
+ function appendOpenCodeSubAgentChildSessionLinked(childSessionId, state, events) {
1312
+ const activity = findOnlyOpenCodeSubAgentWaitingForChild(state);
1313
+ if (!activity) {
1314
+ return;
1315
+ }
1316
+ linkOpenCodeSubAgentChildSession(activity, childSessionId, state);
1317
+ events.push({
1318
+ type: "timeline",
1319
+ provider: "opencode",
1320
+ item: buildOpenCodeSubAgentTimelineItem(activity),
1321
+ });
1322
+ flushOpenCodeSubAgentChildToolParts(childSessionId, state, events);
1323
+ }
1324
+ function appendOpenCodeSubAgentChildToolPart(part, state, events) {
1325
+ const maps = getOpenCodeSubAgentMaps(state);
1326
+ const parentCallId = maps.callIdByChildSessionId.get(part.sessionID);
1327
+ if (!parentCallId) {
1328
+ bufferOpenCodeSubAgentChildToolPart(part, state);
1329
+ return;
1330
+ }
1331
+ const activity = maps.byCallId.get(parentCallId);
1332
+ if (!activity) {
1333
+ return;
1334
+ }
1335
+ const parsedToolPart = OpencodeToolPartToTimelineItemSchema.safeParse(part);
1336
+ if (!parsedToolPart.success || !parsedToolPart.data) {
1337
+ return;
1338
+ }
1339
+ if (!appendOpenCodeSubAgentAction(activity, parsedToolPart.data, state.cwd)) {
1340
+ return;
1341
+ }
1342
+ events.push({
1343
+ type: "timeline",
1344
+ provider: "opencode",
1345
+ item: buildOpenCodeSubAgentTimelineItem(activity),
1346
+ });
1347
+ }
1348
+ function appendOpenCodeSessionCreatedOrUpdated(event, state, events) {
1349
+ if (event.properties.info.id === state.sessionId) {
1350
+ events.push({
1351
+ type: "thread_started",
1352
+ sessionId: state.sessionId,
1353
+ provider: "opencode",
1354
+ });
1355
+ return;
1356
+ }
1357
+ const info = readOpenCodeRecord(event.properties.info);
1358
+ const parentSessionId = readNonEmptyString(info?.parentID) ?? readNonEmptyString(info?.parentId);
1359
+ if (parentSessionId === state.sessionId) {
1360
+ appendOpenCodeSubAgentChildSessionLinked(event.properties.info.id, state, events);
1361
+ }
1362
+ }
1363
+ function appendOpenCodeMessageUpdated(event, state, events) {
1364
+ const info = event.properties.info;
1365
+ if (info.sessionID !== state.sessionId) {
1366
+ return;
1367
+ }
1368
+ state.messageRoles.set(info.id, info.role);
1369
+ if (info.role !== "assistant") {
1370
+ return;
1371
+ }
1372
+ const modelLookupKey = resolveOpenCodeModelLookupKeyFromAssistantMessage(info);
1373
+ if (modelLookupKey) {
1374
+ const contextWindowMaxTokens = state.modelContextWindowsByModelKey?.get(modelLookupKey);
1375
+ if (contextWindowMaxTokens !== undefined) {
1376
+ state.onAssistantModelContextWindowResolved?.(contextWindowMaxTokens);
1281
1377
  }
1282
- case "session.compacted": {
1283
- if (event.properties.sessionID !== state.sessionId) {
1284
- break;
1285
- }
1378
+ }
1379
+ if (state.emittedStructuredMessageIds.has(info.id) || info.time?.completed === undefined) {
1380
+ return;
1381
+ }
1382
+ const text = stringifyStructuredAssistantMessage(info.structured);
1383
+ if (!text) {
1384
+ return;
1385
+ }
1386
+ state.emittedStructuredMessageIds.add(info.id);
1387
+ events.push({
1388
+ type: "timeline",
1389
+ provider: "opencode",
1390
+ item: { type: "assistant_message", text },
1391
+ });
1392
+ }
1393
+ function appendOpenCodeMessagePartUpdated(event, state, events) {
1394
+ const part = event.properties.part;
1395
+ if (part.sessionID !== state.sessionId) {
1396
+ if (part.type === "tool") {
1397
+ appendOpenCodeSubAgentChildToolPart(part, state, events);
1398
+ }
1399
+ return;
1400
+ }
1401
+ const messageRole = state.messageRoles.get(part.messageID);
1402
+ state.partTypes.set(part.id, part.type);
1403
+ if (part.type === "text") {
1404
+ appendOpenCodeTextPart(part, messageRole, state, events);
1405
+ return;
1406
+ }
1407
+ if (part.type === "reasoning") {
1408
+ appendOpenCodeReasoningPart(part, state, events);
1409
+ return;
1410
+ }
1411
+ if (part.type === "tool") {
1412
+ const parsedToolPart = OpencodeToolPartToTimelineItemSchema.safeParse(part);
1413
+ if (parsedToolPart.success && parsedToolPart.data) {
1414
+ appendOpenCodeToolCallTimelineItem(parsedToolPart.data, state, events);
1415
+ }
1416
+ return;
1417
+ }
1418
+ if (part.type === "compaction") {
1419
+ events.push({
1420
+ type: "timeline",
1421
+ provider: "opencode",
1422
+ item: createCompactionTimelineItem("loading", part.auto ? "auto" : "manual"),
1423
+ });
1424
+ return;
1425
+ }
1426
+ if (part.type === "step-finish") {
1427
+ mergeOpenCodeStepFinishUsage(state.accumulatedUsage, part);
1428
+ if (hasNormalizedOpenCodeUsage(state.accumulatedUsage)) {
1286
1429
  events.push({
1287
- type: "timeline",
1430
+ type: "usage_updated",
1288
1431
  provider: "opencode",
1289
- item: createCompactionTimelineItem("completed"),
1432
+ usage: { ...state.accumulatedUsage },
1290
1433
  });
1291
- break;
1292
- }
1293
- case "session.idle": {
1294
- if (event.properties.sessionID === state.sessionId) {
1295
- state.streamedPartKeys.clear();
1296
- state.partTypes.clear();
1297
- events.push({
1298
- type: "turn_completed",
1299
- provider: "opencode",
1300
- usage: undefined,
1301
- });
1302
- }
1303
- break;
1304
- }
1305
- case "session.error": {
1306
- if (event.properties.sessionID === state.sessionId) {
1307
- state.streamedPartKeys.clear();
1308
- state.partTypes.clear();
1309
- events.push({
1310
- type: "turn_failed",
1311
- provider: "opencode",
1312
- error: normalizeTurnFailureError(event.properties.error),
1313
- });
1314
- }
1315
- break;
1316
1434
  }
1317
- case "session.status": {
1318
- if (event.properties.sessionID !== state.sessionId) {
1319
- break;
1320
- }
1321
- const { status } = event.properties;
1322
- if (status.type === "idle") {
1323
- state.streamedPartKeys.clear();
1324
- state.partTypes.clear();
1325
- events.push({
1326
- type: "turn_completed",
1327
- provider: "opencode",
1328
- usage: undefined,
1329
- });
1330
- }
1331
- else if (status.type === "retry" && isFatalOpenCodeRetryMessage(status.message)) {
1332
- state.streamedPartKeys.clear();
1333
- state.partTypes.clear();
1334
- events.push({
1335
- type: "turn_failed",
1336
- provider: "opencode",
1337
- error: normalizeTurnFailureError(status.message),
1338
- });
1339
- }
1340
- // "retry" and "busy" are transient — no terminal event.
1341
- break;
1435
+ }
1436
+ }
1437
+ function appendOpenCodeTextPart(part, messageRole, state, events) {
1438
+ if (messageRole === "user") {
1439
+ return;
1440
+ }
1441
+ if (!part.time?.end) {
1442
+ return;
1443
+ }
1444
+ const partKey = resolvePartDedupeKey(part, "text");
1445
+ if (partKey && state.streamedPartKeys.delete(partKey)) {
1446
+ return;
1447
+ }
1448
+ if (part.text) {
1449
+ events.push({
1450
+ type: "timeline",
1451
+ provider: "opencode",
1452
+ item: { type: "assistant_message", text: part.text },
1453
+ });
1454
+ }
1455
+ }
1456
+ function appendOpenCodeReasoningPart(part, state, events) {
1457
+ if (!part.time.end) {
1458
+ return;
1459
+ }
1460
+ const partKey = resolvePartDedupeKey(part, "reasoning");
1461
+ if (partKey && state.streamedPartKeys.delete(partKey)) {
1462
+ return;
1463
+ }
1464
+ if (part.text) {
1465
+ events.push({
1466
+ type: "timeline",
1467
+ provider: "opencode",
1468
+ item: { type: "reasoning", text: part.text },
1469
+ });
1470
+ }
1471
+ }
1472
+ function appendOpenCodeMessagePartDelta(event, state, events) {
1473
+ const { sessionID, messageID, partID, field, delta } = event.properties;
1474
+ if (sessionID !== state.sessionId) {
1475
+ return;
1476
+ }
1477
+ if (!delta || !field) {
1478
+ return;
1479
+ }
1480
+ const messageRole = messageID ? state.messageRoles.get(messageID) : undefined;
1481
+ const knownPartType = partID ? state.partTypes.get(partID) : undefined;
1482
+ const isReasoning = knownPartType === "reasoning" || field === "reasoning";
1483
+ if (isReasoning) {
1484
+ if (partID) {
1485
+ state.streamedPartKeys.add(`reasoning:${partID}`);
1486
+ }
1487
+ events.push({
1488
+ type: "timeline",
1489
+ provider: "opencode",
1490
+ item: { type: "reasoning", text: delta },
1491
+ });
1492
+ return;
1493
+ }
1494
+ if (field !== "text") {
1495
+ return;
1496
+ }
1497
+ if (messageRole === "user") {
1498
+ return;
1499
+ }
1500
+ if (partID) {
1501
+ state.streamedPartKeys.add(`text:${partID}`);
1502
+ }
1503
+ events.push({
1504
+ type: "timeline",
1505
+ provider: "opencode",
1506
+ item: { type: "assistant_message", text: delta },
1507
+ });
1508
+ }
1509
+ function appendOpenCodePermissionAsked(event, state, events) {
1510
+ if (event.properties.sessionID !== state.sessionId) {
1511
+ return;
1512
+ }
1513
+ const metadata = readOpenCodeRecord(event.properties.metadata);
1514
+ const tool = readOpenCodeRecord(event.properties.tool);
1515
+ const patterns = Array.isArray(event.properties.patterns)
1516
+ ? event.properties.patterns.filter((value) => typeof value === "string")
1517
+ : [];
1518
+ const command = readPermissionField(metadata, PERMISSION_COMMAND_KEYS);
1519
+ const cwd = readPermissionField(metadata, PERMISSION_CWD_KEYS);
1520
+ const reason = readPermissionField(metadata, PERMISSION_REASON_KEYS);
1521
+ const input = buildOpenCodePermissionInput({ patterns, metadata, tool, command });
1522
+ const detail = buildOpenCodePermissionDetail({
1523
+ permission: event.properties.permission,
1524
+ input,
1525
+ command,
1526
+ cwd,
1527
+ });
1528
+ const description = buildOpenCodePermissionDescription({ reason, patterns });
1529
+ events.push({
1530
+ type: "permission_requested",
1531
+ provider: "opencode",
1532
+ request: {
1533
+ id: event.properties.id,
1534
+ provider: "opencode",
1535
+ name: event.properties.permission,
1536
+ kind: "tool",
1537
+ title: toHumanReadablePermissionTitle(event.properties.permission),
1538
+ ...(description ? { description } : {}),
1539
+ input,
1540
+ detail,
1541
+ },
1542
+ });
1543
+ }
1544
+ function appendOpenCodeQuestionAsked(event, state, events) {
1545
+ if (event.properties.sessionID !== state.sessionId) {
1546
+ return;
1547
+ }
1548
+ const questions = event.properties.questions.flatMap((q) => {
1549
+ if (!q.question || !q.header) {
1550
+ return [];
1342
1551
  }
1552
+ const options = q.options?.map((o) => ({
1553
+ label: o.label,
1554
+ ...(o.description ? { description: o.description } : {}),
1555
+ })) ?? [];
1556
+ return [
1557
+ {
1558
+ question: q.question,
1559
+ header: q.header,
1560
+ options,
1561
+ ...(q.multiple === true ? { multiSelect: true } : {}),
1562
+ },
1563
+ ];
1564
+ });
1565
+ if (questions.length === 0) {
1566
+ return;
1343
1567
  }
1344
- return events;
1568
+ events.push({
1569
+ type: "permission_requested",
1570
+ provider: "opencode",
1571
+ request: {
1572
+ id: event.properties.id,
1573
+ provider: "opencode",
1574
+ name: "question",
1575
+ kind: "question",
1576
+ title: "Question",
1577
+ input: { questions },
1578
+ metadata: {
1579
+ source: "opencode_question",
1580
+ ...event.properties.tool,
1581
+ },
1582
+ },
1583
+ });
1584
+ }
1585
+ function appendOpenCodeSessionStatus(event, state, events) {
1586
+ if (event.properties.sessionID !== state.sessionId) {
1587
+ return;
1588
+ }
1589
+ const { status } = event.properties;
1590
+ if (status.type === "idle") {
1591
+ resetOpenCodeTurnTrackingState(state);
1592
+ events.push({ type: "turn_completed", provider: "opencode", usage: undefined });
1593
+ return;
1594
+ }
1595
+ if (status.type === "retry" && isFatalOpenCodeRetryMessage(status.message)) {
1596
+ resetOpenCodeTurnTrackingState(state);
1597
+ events.push({
1598
+ type: "turn_failed",
1599
+ provider: "opencode",
1600
+ error: toDiagnosticErrorMessage(status.message),
1601
+ });
1602
+ }
1603
+ // "retry" and "busy" are transient — no terminal event.
1604
+ }
1605
+ function createDeferred() {
1606
+ let resolve;
1607
+ let reject;
1608
+ const promise = new Promise((res, rej) => {
1609
+ resolve = res;
1610
+ reject = rej;
1611
+ });
1612
+ return { promise, resolve, reject };
1345
1613
  }
1346
1614
  class OpenCodeAgentSession {
1347
1615
  constructor(config, client, sessionId, logger, modelContextWindowsByModelKey = new Map(), releaseServer) {
@@ -1366,6 +1634,9 @@ class OpenCodeAgentSession {
1366
1634
  this.nextTurnOrdinal = 0;
1367
1635
  this.activeForegroundTurnId = null;
1368
1636
  this.runningToolCalls = new Map();
1637
+ this.subAgentsByCallId = new Map();
1638
+ this.subAgentCallIdByChildSessionId = new Map();
1639
+ this.pendingChildToolPartsBySessionId = new Map();
1369
1640
  this.config = config;
1370
1641
  this.client = client;
1371
1642
  this.sessionId = sessionId;
@@ -1398,75 +1669,13 @@ class OpenCodeAgentSession {
1398
1669
  this.config.thinkingOptionId = normalizedThinkingOptionId ?? undefined;
1399
1670
  }
1400
1671
  async run(prompt, options) {
1401
- const timeline = [];
1402
- let finalText = "";
1403
- let usage;
1404
- let turnId = null;
1405
- const bufferedEvents = [];
1406
- let settled = false;
1407
- let resolveCompletion;
1408
- let rejectCompletion;
1409
- const processEvent = (event) => {
1410
- if (settled) {
1411
- return;
1412
- }
1413
- const eventTurnId = event.turnId;
1414
- if (turnId && eventTurnId && eventTurnId !== turnId) {
1415
- return;
1416
- }
1417
- if (event.type === "timeline") {
1418
- timeline.push(event.item);
1419
- if (event.item.type === "assistant_message") {
1420
- finalText = event.item.text;
1421
- }
1422
- return;
1423
- }
1424
- if (event.type === "turn_completed") {
1425
- usage = event.usage;
1426
- settled = true;
1427
- resolveCompletion();
1428
- return;
1429
- }
1430
- if (event.type === "turn_failed") {
1431
- settled = true;
1432
- rejectCompletion(new Error(event.error));
1433
- return;
1434
- }
1435
- if (event.type === "turn_canceled") {
1436
- settled = true;
1437
- resolveCompletion();
1438
- }
1439
- };
1440
- const completion = new Promise((resolve, reject) => {
1441
- resolveCompletion = resolve;
1442
- rejectCompletion = reject;
1443
- });
1444
- const unsubscribe = this.subscribe((event) => {
1445
- if (!turnId) {
1446
- bufferedEvents.push(event);
1447
- return;
1448
- }
1449
- processEvent(event);
1672
+ return runProviderTurn({
1673
+ prompt,
1674
+ runOptions: options,
1675
+ startTurn: (p, o) => this.startTurn(p, o),
1676
+ subscribe: (callback) => this.subscribe(callback),
1677
+ getSessionId: () => this.sessionId,
1450
1678
  });
1451
- try {
1452
- const result = await this.startTurn(prompt, options);
1453
- turnId = result.turnId;
1454
- for (const event of bufferedEvents) {
1455
- processEvent(event);
1456
- }
1457
- if (!settled) {
1458
- await completion;
1459
- }
1460
- }
1461
- finally {
1462
- unsubscribe();
1463
- }
1464
- return {
1465
- sessionId: this.sessionId,
1466
- finalText,
1467
- usage,
1468
- timeline,
1469
- };
1470
1679
  }
1471
1680
  async interrupt() {
1472
1681
  const turnId = this.activeForegroundTurnId;
@@ -1485,6 +1694,9 @@ class OpenCodeAgentSession {
1485
1694
  throw new Error("A foreground turn is already active");
1486
1695
  }
1487
1696
  this.runningToolCalls.clear();
1697
+ this.subAgentsByCallId.clear();
1698
+ this.subAgentCallIdByChildSessionId.clear();
1699
+ this.pendingChildToolPartsBySessionId.clear();
1488
1700
  const turnAbortController = new AbortController();
1489
1701
  this.abortController = turnAbortController;
1490
1702
  await this.ensureMcpServersConfigured();
@@ -1494,12 +1706,54 @@ class OpenCodeAgentSession {
1494
1706
  const model = this.parseModel(this.config.model);
1495
1707
  const thinkingOptionId = this.config.thinkingOptionId;
1496
1708
  const effectiveVariant = thinkingOptionId ?? undefined;
1497
- const effectiveMode = normalizeOpenCodeModeId(this.currentMode);
1709
+ const effectiveMode = resolveOpenCodeRuntimeAgentId(this.currentMode);
1498
1710
  const turnId = this.createTurnId();
1499
1711
  this.activeForegroundTurnId = turnId;
1500
- void this.consumeEventStream(turnId, turnAbortController);
1712
+ // OpenCode's /event SSE endpoint does NOT replay past events. If we send
1713
+ // the prompt before our reader is connected, terminal events fired early
1714
+ // by the server (e.g. session.error / session.idle for invalid model or
1715
+ // mode) are missed and the turn hangs forever. Wait for the subscription
1716
+ // to be established before sending anything.
1717
+ const subscriptionReady = createDeferred();
1718
+ void this.consumeEventStream(turnId, turnAbortController, subscriptionReady);
1719
+ try {
1720
+ await subscriptionReady.promise;
1721
+ }
1722
+ catch {
1723
+ // consumeEventStream already finished the turn with the subscription error.
1724
+ return { turnId };
1725
+ }
1501
1726
  const slashCommand = await this.resolveSlashCommandInvocation(prompt);
1502
1727
  if (slashCommand) {
1728
+ if (slashCommand.commandName === "compact" || slashCommand.commandName === "summarize") {
1729
+ void this.client.session
1730
+ .summarize({
1731
+ sessionID: this.sessionId,
1732
+ directory: this.config.cwd,
1733
+ ...(model ? { providerID: model.providerID, modelID: model.modelID } : {}),
1734
+ })
1735
+ .then((response) => {
1736
+ if (response.error) {
1737
+ this.finishForegroundTurn({
1738
+ type: "turn_failed",
1739
+ provider: "opencode",
1740
+ error: toDiagnosticErrorMessage(response.error),
1741
+ }, turnId);
1742
+ }
1743
+ else {
1744
+ this.finishForegroundTurn({ type: "turn_completed", provider: "opencode", usage: undefined }, turnId);
1745
+ }
1746
+ return;
1747
+ })
1748
+ .catch((error) => {
1749
+ this.finishForegroundTurn({
1750
+ type: "turn_failed",
1751
+ provider: "opencode",
1752
+ error: toDiagnosticErrorMessage(error),
1753
+ }, turnId);
1754
+ });
1755
+ return { turnId };
1756
+ }
1503
1757
  // command() blocks until the server finishes processing. OpenCode's SSE
1504
1758
  // endpoint does NOT replay past events, so if the command completes before
1505
1759
  // our SSE reader connects, we miss `session.idle` and the turn hangs.
@@ -1526,12 +1780,13 @@ class OpenCodeAgentSession {
1526
1780
  }, "OpenCode slash command hit a header timeout; waiting for SSE terminal event");
1527
1781
  return;
1528
1782
  }
1529
- const errorMsg = normalizeTurnFailureError(response.error);
1783
+ const errorMsg = toDiagnosticErrorMessage(response.error);
1530
1784
  this.finishForegroundTurn({ type: "turn_failed", provider: "opencode", error: errorMsg }, turnId);
1531
1785
  }
1532
1786
  else {
1533
1787
  this.finishForegroundTurn({ type: "turn_completed", provider: "opencode", usage: undefined }, turnId);
1534
1788
  }
1789
+ return;
1535
1790
  })
1536
1791
  .catch((err) => {
1537
1792
  if (isOpenCodeHeadersTimeoutFailure(err)) {
@@ -1542,44 +1797,48 @@ class OpenCodeAgentSession {
1542
1797
  }, "OpenCode slash command hit a header timeout; waiting for SSE terminal event");
1543
1798
  return;
1544
1799
  }
1545
- this.finishForegroundTurn({ type: "turn_failed", provider: "opencode", error: normalizeTurnFailureError(err) }, turnId);
1800
+ this.finishForegroundTurn({ type: "turn_failed", provider: "opencode", error: toDiagnosticErrorMessage(err) }, turnId);
1546
1801
  });
1547
1802
  }
1548
1803
  else {
1549
- void this.client.session
1550
- .promptAsync({
1551
- sessionID: this.sessionId,
1552
- directory: this.config.cwd,
1553
- parts,
1554
- ...(options?.outputSchema
1555
- ? {
1556
- format: {
1557
- type: "json_schema",
1558
- schema: options.outputSchema,
1559
- },
1804
+ // Wrap in an async IIFE so a synchronous throw from promptAsync (e.g.
1805
+ // SDK input validation) is caught alongside async rejections. A plain
1806
+ // `.then().catch()` chain would let a sync throw escape unhandled.
1807
+ void (async () => {
1808
+ try {
1809
+ const promptResponse = await this.client.session.promptAsync({
1810
+ sessionID: this.sessionId,
1811
+ directory: this.config.cwd,
1812
+ parts,
1813
+ ...(options?.outputSchema
1814
+ ? {
1815
+ format: {
1816
+ type: "json_schema",
1817
+ schema: options.outputSchema,
1818
+ },
1819
+ }
1820
+ : {}),
1821
+ ...(this.config.systemPrompt ? { system: this.config.systemPrompt } : {}),
1822
+ ...(model ? { model } : {}),
1823
+ ...(effectiveMode ? { agent: effectiveMode } : {}),
1824
+ ...(effectiveVariant ? { variant: effectiveVariant } : {}),
1825
+ });
1826
+ if (promptResponse.error) {
1827
+ this.finishForegroundTurn({
1828
+ type: "turn_failed",
1829
+ provider: "opencode",
1830
+ error: toDiagnosticErrorMessage(promptResponse.error),
1831
+ }, turnId);
1560
1832
  }
1561
- : {}),
1562
- ...(this.config.systemPrompt ? { system: this.config.systemPrompt } : {}),
1563
- ...(model ? { model } : {}),
1564
- ...(effectiveMode ? { agent: effectiveMode } : {}),
1565
- ...(effectiveVariant ? { variant: effectiveVariant } : {}),
1566
- })
1567
- .then((promptResponse) => {
1568
- if (promptResponse.error) {
1833
+ }
1834
+ catch (error) {
1569
1835
  this.finishForegroundTurn({
1570
1836
  type: "turn_failed",
1571
1837
  provider: "opencode",
1572
- error: normalizeTurnFailureError(promptResponse.error),
1838
+ error: toDiagnosticErrorMessage(error),
1573
1839
  }, turnId);
1574
1840
  }
1575
- })
1576
- .catch((error) => {
1577
- this.finishForegroundTurn({
1578
- type: "turn_failed",
1579
- provider: "opencode",
1580
- error: normalizeTurnFailureError(error),
1581
- }, turnId);
1582
- });
1841
+ })();
1583
1842
  }
1584
1843
  return { turnId };
1585
1844
  }
@@ -1589,14 +1848,15 @@ class OpenCodeAgentSession {
1589
1848
  this.subscribers.delete(callback);
1590
1849
  };
1591
1850
  }
1592
- async consumeEventStream(turnId, turnAbortController) {
1851
+ async consumeEventStream(turnId, turnAbortController, subscriptionReady) {
1593
1852
  try {
1594
1853
  const result = await this.client.event.subscribe({ directory: this.config.cwd }, { signal: turnAbortController.signal, sseMaxRetryAttempts: 0 });
1854
+ subscriptionReady.resolve();
1595
1855
  for await (const event of result.stream) {
1596
1856
  if (turnAbortController.signal.aborted || this.activeForegroundTurnId !== turnId) {
1597
1857
  break;
1598
1858
  }
1599
- const translated = this.translateEvent(event);
1859
+ const translated = await this.translateEvent(event);
1600
1860
  for (const e of translated) {
1601
1861
  if (this.activeForegroundTurnId !== turnId) {
1602
1862
  return;
@@ -1604,19 +1864,9 @@ class OpenCodeAgentSession {
1604
1864
  if (e.type === "timeline" && e.item.type === "tool_call") {
1605
1865
  this.trackToolCall(e.item);
1606
1866
  }
1607
- if (e.type === "turn_completed" ||
1608
- e.type === "turn_failed" ||
1609
- e.type === "turn_canceled") {
1610
- if (e.type === "turn_failed") {
1611
- this.finishForegroundTurn({
1612
- type: "turn_failed",
1613
- provider: "opencode",
1614
- error: normalizeTurnFailureError(e.error),
1615
- }, turnId);
1616
- }
1617
- else {
1618
- this.finishForegroundTurn(e, turnId);
1619
- }
1867
+ const terminalEvent = toTerminalTurnEvent(e);
1868
+ if (terminalEvent) {
1869
+ this.finishForegroundTurn(terminalEvent, turnId);
1620
1870
  return;
1621
1871
  }
1622
1872
  this.notifySubscribers(e, turnId);
@@ -1631,11 +1881,12 @@ class OpenCodeAgentSession {
1631
1881
  }
1632
1882
  }
1633
1883
  catch (error) {
1884
+ subscriptionReady.reject(error);
1634
1885
  if (!turnAbortController.signal.aborted && this.activeForegroundTurnId === turnId) {
1635
1886
  this.finishForegroundTurn({
1636
1887
  type: "turn_failed",
1637
1888
  provider: "opencode",
1638
- error: normalizeTurnFailureError(error),
1889
+ error: toDiagnosticErrorMessage(error),
1639
1890
  }, turnId);
1640
1891
  }
1641
1892
  }
@@ -1677,13 +1928,22 @@ class OpenCodeAgentSession {
1677
1928
  }
1678
1929
  synthesizeInterruptedToolCalls(turnId) {
1679
1930
  for (const item of this.runningToolCalls.values()) {
1931
+ const error = { message: "Tool execution aborted" };
1680
1932
  this.notifySubscribers({
1681
1933
  type: "timeline",
1682
1934
  provider: "opencode",
1683
1935
  item: {
1684
1936
  ...item,
1685
1937
  status: "failed",
1686
- error: { message: "Tool execution aborted" },
1938
+ error,
1939
+ detail: item.detail.type === "sub_agent"
1940
+ ? {
1941
+ ...item.detail,
1942
+ log: [item.detail.log, error.message]
1943
+ .filter((entry) => entry.trim().length > 0)
1944
+ .join("\n"),
1945
+ }
1946
+ : item.detail,
1687
1947
  },
1688
1948
  }, turnId);
1689
1949
  }
@@ -1729,34 +1989,33 @@ class OpenCodeAgentSession {
1729
1989
  else {
1730
1990
  let emittedAssistantText = false;
1731
1991
  for (const part of parts) {
1732
- if (part.type === "text") {
1733
- if (part.text) {
1734
- emittedAssistantText = true;
1735
- yield {
1736
- type: "timeline",
1737
- provider: "opencode",
1738
- item: { type: "assistant_message", text: part.text },
1739
- };
1740
- }
1992
+ if (part.type === "text" && part.text) {
1993
+ emittedAssistantText = true;
1994
+ yield {
1995
+ type: "timeline",
1996
+ provider: "opencode",
1997
+ item: { type: "assistant_message", text: part.text },
1998
+ };
1999
+ continue;
1741
2000
  }
1742
- else if (part.type === "reasoning") {
1743
- if (part.text) {
1744
- yield {
1745
- type: "timeline",
1746
- provider: "opencode",
1747
- item: { type: "reasoning", text: part.text },
1748
- };
1749
- }
2001
+ if (part.type === "reasoning" && part.text) {
2002
+ yield {
2003
+ type: "timeline",
2004
+ provider: "opencode",
2005
+ item: { type: "reasoning", text: part.text },
2006
+ };
2007
+ continue;
1750
2008
  }
1751
- else if (part.type === "tool") {
1752
- const parsedToolPart = OpencodeToolPartToTimelineItemSchema.safeParse(part);
1753
- if (parsedToolPart.success && parsedToolPart.data) {
1754
- yield {
1755
- type: "timeline",
1756
- provider: "opencode",
1757
- item: parsedToolPart.data,
1758
- };
1759
- }
2009
+ if (part.type !== "tool") {
2010
+ continue;
2011
+ }
2012
+ const parsedToolPart = OpencodeToolPartToTimelineItemSchema.safeParse(part);
2013
+ if (parsedToolPart.success && parsedToolPart.data) {
2014
+ yield {
2015
+ type: "timeline",
2016
+ provider: "opencode",
2017
+ item: parsedToolPart.data,
2018
+ };
1760
2019
  }
1761
2020
  }
1762
2021
  if (!emittedAssistantText) {
@@ -1779,19 +2038,15 @@ class OpenCodeAgentSession {
1779
2038
  const response = await this.client.app.agents({
1780
2039
  directory: this.config.cwd,
1781
2040
  });
1782
- const discoveredModes = response.error || !response.data
1783
- ? []
1784
- : response.data
1785
- .filter((agent) => agent.mode === "primary" && agent.hidden !== true)
1786
- .map((agent) => ({
1787
- id: agent.name,
1788
- label: agent.name.charAt(0).toUpperCase() + agent.name.slice(1),
1789
- description: typeof agent.description === "string" && agent.description.trim().length > 0
1790
- ? agent.description.trim()
1791
- : DEFAULT_MODES.find((mode) => mode.id === agent.name)?.description,
1792
- }));
1793
- this.availableModesCache =
1794
- discoveredModes.length > 0 ? sortOpenCodeModes(discoveredModes) : DEFAULT_MODES;
2041
+ const agents = response.error || !response.data ? [] : response.data;
2042
+ const discoveredModes = agents.filter(isSelectableOpenCodeAgent).map((agent) => ({
2043
+ id: agent.name,
2044
+ label: agent.name.charAt(0).toUpperCase() + agent.name.slice(1),
2045
+ description: typeof agent.description === "string" && agent.description.trim().length > 0
2046
+ ? agent.description.trim()
2047
+ : DEFAULT_MODES.find((mode) => mode.id === agent.name)?.description,
2048
+ }));
2049
+ this.availableModesCache = mergeOpenCodeModes(discoveredModes);
1795
2050
  return this.availableModesCache;
1796
2051
  }
1797
2052
  async getCurrentMode() {
@@ -1801,14 +2056,18 @@ class OpenCodeAgentSession {
1801
2056
  const result = await this.client.command.list({
1802
2057
  directory: this.config.cwd,
1803
2058
  });
2059
+ const commandsByName = new Map(OPENCODE_HANDLED_BUILTIN_SLASH_COMMANDS.map((command) => [command.name, command]));
1804
2060
  if (result.error || !result.data) {
1805
- return [];
2061
+ return Array.from(commandsByName.values());
1806
2062
  }
1807
- return result.data.map((cmd) => ({
1808
- name: cmd.name,
1809
- description: cmd.description ?? "",
1810
- argumentHint: cmd.hints?.length ? cmd.hints.join(" ") : "",
1811
- }));
2063
+ for (const cmd of result.data) {
2064
+ commandsByName.set(cmd.name, {
2065
+ name: cmd.name,
2066
+ description: cmd.description ?? "",
2067
+ argumentHint: cmd.hints?.length ? cmd.hints.join(" ") : "",
2068
+ });
2069
+ }
2070
+ return Array.from(commandsByName.values());
1812
2071
  }
1813
2072
  async setMode(modeId) {
1814
2073
  this.currentMode = normalizeOpenCodeModeId(modeId);
@@ -1950,10 +2209,7 @@ class OpenCodeAgentSession {
1950
2209
  }
1951
2210
  }
1952
2211
  async configureMcpServers(mcpServers) {
1953
- for (const [name, serverConfig] of Object.entries(mcpServers)) {
1954
- const mappedConfig = toOpenCodeMcpConfig(serverConfig);
1955
- await this.registerMcpServer(name, mappedConfig);
1956
- }
2212
+ await Promise.all(Object.entries(mcpServers).map(([name, serverConfig]) => this.registerMcpServer(name, toOpenCodeMcpConfig(serverConfig))));
1957
2213
  }
1958
2214
  async registerMcpServer(name, config) {
1959
2215
  await this.runMcpOperation("add", name, () => this.client.mcp.add({
@@ -1975,16 +2231,20 @@ class OpenCodeAgentSession {
1975
2231
  if (isAlreadyPresentMcpError(error)) {
1976
2232
  return;
1977
2233
  }
1978
- throw new Error(`Failed to ${operation} OpenCode MCP server '${name}': ${stringifyUnknownError(error)}`);
2234
+ throw new Error(`Failed to ${operation} OpenCode MCP server '${name}': ${toDiagnosticErrorMessage(error)}`);
1979
2235
  }
1980
- translateEvent(event) {
2236
+ async translateEvent(event) {
1981
2237
  const translated = translateOpenCodeEvent(event, {
1982
2238
  sessionId: this.sessionId,
2239
+ cwd: this.config.cwd,
1983
2240
  messageRoles: this.messageRoles,
1984
2241
  accumulatedUsage: this.accumulatedUsage,
1985
2242
  streamedPartKeys: this.streamedPartKeys,
1986
2243
  emittedStructuredMessageIds: this.emittedStructuredMessageIds,
1987
2244
  partTypes: this.partTypes,
2245
+ subAgentsByCallId: this.subAgentsByCallId,
2246
+ subAgentCallIdByChildSessionId: this.subAgentCallIdByChildSessionId,
2247
+ pendingChildToolPartsBySessionId: this.pendingChildToolPartsBySessionId,
1988
2248
  modelContextWindowsByModelKey: this.modelContextWindowsByModelKey,
1989
2249
  onAssistantModelContextWindowResolved: (contextWindowMaxTokens) => {
1990
2250
  this.accumulatedUsage.contextWindowMaxTokens = contextWindowMaxTokens;
@@ -1993,8 +2253,13 @@ class OpenCodeAgentSession {
1993
2253
  }
1994
2254
  },
1995
2255
  });
2256
+ const events = [];
1996
2257
  for (const translatedEvent of translated) {
1997
2258
  if (translatedEvent.type === "permission_requested") {
2259
+ const autoApproved = await this.tryAutoApproveToolPermission(translatedEvent.request);
2260
+ if (autoApproved) {
2261
+ continue;
2262
+ }
1998
2263
  this.pendingPermissions.set(translatedEvent.request.id, translatedEvent.request);
1999
2264
  }
2000
2265
  if (translatedEvent.type === "turn_completed") {
@@ -2005,8 +2270,26 @@ class OpenCodeAgentSession {
2005
2270
  this.accumulatedUsage =
2006
2271
  contextWindowMaxTokens !== undefined ? { contextWindowMaxTokens } : {};
2007
2272
  }
2273
+ events.push(translatedEvent);
2274
+ }
2275
+ return events;
2276
+ }
2277
+ async tryAutoApproveToolPermission(request) {
2278
+ if (this.currentMode !== OPENCODE_FULL_ACCESS_MODE_ID || request.kind !== "tool") {
2279
+ return false;
2280
+ }
2281
+ try {
2282
+ await this.client.permission.reply({
2283
+ requestID: request.id,
2284
+ directory: this.config.cwd,
2285
+ reply: "once",
2286
+ });
2287
+ return true;
2288
+ }
2289
+ catch (error) {
2290
+ this.logger.warn({ err: error, requestId: request.id }, "Failed to auto-approve OpenCode tool permission");
2291
+ return false;
2008
2292
  }
2009
- return translated;
2010
2293
  }
2011
2294
  resolveSelectedModelContextWindowMaxTokens() {
2012
2295
  return this.selectedModelContextWindowMaxTokens;