@vantran-se/openchamber-web 1.24.4 → 2.0.2

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 (367) hide show
  1. package/README.md +2 -8
  2. package/bin/lib/commands-connect-url.js +3 -8
  3. package/bin/lib/commands-tunnel.js +3 -0
  4. package/dist/assets/{CodeMirrorCommentWidgets-B4a0JkUz.js → CodeMirrorCommentWidgets-B82Oye3V.js} +1 -1
  5. package/dist/assets/DiffView-DJLmWn6Z.js +4 -0
  6. package/dist/assets/FilesView-DjksmZRo.js +17 -0
  7. package/dist/assets/{GitView-Byu2DY7s.js → GitView-DiUsUIgr.js} +4 -4
  8. package/dist/assets/{GuestAttachDialog-B808E0-d.js → GuestAttachDialog-CYwWYLr3.js} +1 -1
  9. package/dist/assets/GuestSurfacePane-CmctyRI4.js +1 -0
  10. package/dist/assets/{JsonTreeView-VW_7czo3.js → JsonTreeView-DOHHcbgJ.js} +1 -1
  11. package/dist/assets/LinearIssuesView-DaqnylcV.js +1 -0
  12. package/dist/assets/MarkdownImageGallery-HJNvWt7L.js +1 -0
  13. package/dist/assets/MarkdownRendererImpl-nDZRGg2I.js +12 -0
  14. package/dist/assets/OnboardingScreen-C2B5Bsof.js +1 -0
  15. package/dist/assets/{PatchDiff-DCjGhlYV.js → PatchDiff-C4FLBjpt.js} +1 -1
  16. package/dist/assets/{PierreDiffViewer-CEDZNkU2.js → PierreDiffViewer-C_1S9c9n.js} +1 -1
  17. package/dist/assets/PlanView-_eZvb-G5.js +5 -0
  18. package/dist/assets/PluginPane-sM8fcZIV.js +3 -0
  19. package/dist/assets/SettingsView-BRfr46hb.js +29 -0
  20. package/dist/assets/SettingsWindow-CcUDwQHg.js +1 -0
  21. package/dist/assets/SubmoduleDiffSummary-CrN1ZGwl.js +1 -0
  22. package/dist/assets/ToolOutputDialog-Cij4jI09.js +15 -0
  23. package/dist/assets/ToolPartDiffPreview-BXzwQ-JY.js +8 -0
  24. package/dist/assets/{VirtualizedFileDiff-NU0FHFhT.js → VirtualizedFileDiff-DSWTLJNH.js} +4 -4
  25. package/dist/assets/{WalkthroughView-BZyjhqHv.js → WalkthroughView-CpUUgY8H.js} +2 -2
  26. package/dist/assets/appThemeRegistry-B5tHTkR8.js +1 -0
  27. package/dist/assets/{commitAndPush-BDftrjr6.js → commitAndPush-D7D8qV8p.js} +1 -1
  28. package/dist/assets/{computeVirtualFileMetrics-DlWlEM3x.js → computeVirtualFileMetrics-cq9uQ30i.js} +1 -1
  29. package/dist/assets/de-CUO1-KqF.js +10 -0
  30. package/dist/assets/es-BlbC6sGJ.js +16 -0
  31. package/dist/assets/fr-D2nwe_0W.js +14 -0
  32. package/dist/assets/index-BQOoYIOu.js +1 -0
  33. package/dist/assets/index-CLcM8HKx.css +1 -0
  34. package/dist/assets/index-CvLgnuNI.js +41 -0
  35. package/dist/assets/{isDiffPlainText-CO4e5J_S.js → isDiffPlainText-D0obJ2p8.js} +1 -1
  36. package/dist/assets/{isFilePlainText-ue6kCou7.js → isFilePlainText-DB3_rjyW.js} +1 -1
  37. package/dist/assets/ja-CA7vnDsZ.js +16 -0
  38. package/dist/assets/ko-Chy6a9l-.js +16 -0
  39. package/dist/assets/main-B9JFK3vF.js +896 -0
  40. package/dist/assets/main-Bhiqnrhd.js +2 -0
  41. package/dist/assets/{markdownCore-CK48LG0z.js → markdownCore-tfqOFaBd.js} +4 -4
  42. package/dist/assets/miniChat-B0UOL5zA.js +2 -0
  43. package/dist/assets/mobile-BJppFIEo.js +2 -0
  44. package/dist/assets/{patchFileDiff-D7QVlovD.js → patchFileDiff-Db6KuwCP.js} +3 -3
  45. package/dist/assets/pl-CTR5A_1P.js +16 -0
  46. package/dist/assets/pt-BR-BE1O1KEx.js +16 -0
  47. package/dist/assets/renderElectronMiniChatApp-Yz5sfoFh.js +2 -0
  48. package/dist/assets/renderMobileApp-QQ-yB8aY.js +25 -0
  49. package/dist/assets/runtimeEndpointReset-DKDdzRzm.js +27 -0
  50. package/dist/assets/scheduledTasksApi-C5sCuNqf.js +1 -0
  51. package/dist/assets/{shikiHighlight-BPu3JiQs.js → shikiHighlight-xURoo5t_.js} +1 -1
  52. package/dist/assets/{textMateThemeFromAppTheme-DWqRPo9A.js → textMateThemeFromAppTheme-BZLGuYTU.js} +1 -1
  53. package/dist/assets/tr-Bh5vK6cW.js +7 -0
  54. package/dist/assets/uk-CLDkZFy_.js +16 -0
  55. package/dist/assets/useAppFontEffects-BxrtCnfR.js +7337 -0
  56. package/dist/assets/{useInlineCommentController-CgS0fnw_.js → useInlineCommentController-CeXuR-SR.js} +2 -2
  57. package/dist/assets/useRootScrollLock-DgWxezc1.js +2 -0
  58. package/dist/assets/{vendor-codemirror-language-data-Bx2EHc1O.js → vendor-codemirror-language-data-DOuaQUZ0.js} +2 -2
  59. package/dist/assets/vendor-cron-parser-CjvYVigk.js +2 -0
  60. package/dist/assets/vendor-opencode-client-_BAHQo4R.js +12 -0
  61. package/dist/assets/{vendor-remixicon-react-BDmGmFCA.js → vendor-remixicon-react-D6dZ0UwF.js} +1 -1
  62. package/dist/assets/{vendor-zod-CgAdXWZO.js → vendor-zod-Gea9uBlY.js} +1 -1
  63. package/dist/assets/{web-components-DxX8bZ1o.js → web-components-63H1h21j.js} +2 -2
  64. package/dist/assets/zh-CN-DODgcmYj.js +16 -0
  65. package/dist/assets/zh-TW-ByNfIwLA.js +16 -0
  66. package/dist/index.html +13 -7
  67. package/dist/mini-chat.html +5 -5
  68. package/dist/mobile.html +5 -5
  69. package/package.json +6 -5
  70. package/server/index.d.ts +1 -0
  71. package/server/index.js +246 -91
  72. package/server/lib/agent-tool/DOCUMENTATION.md +32 -15
  73. package/server/lib/agent-tool/runtime.js +135 -54
  74. package/server/lib/agent-tool/runtime.test.js +155 -87
  75. package/server/lib/browser-control/DOCUMENTATION.md +37 -2
  76. package/server/lib/browser-control/provider.js +217 -0
  77. package/server/lib/browser-control/provider.test.js +251 -0
  78. package/server/lib/context-obligatory/runtime.js +61 -50
  79. package/server/lib/context-obligatory/runtime.test.js +62 -162
  80. package/server/lib/event-stream/DOCUMENTATION.md +12 -1
  81. package/server/lib/event-stream/delta-coalescer.js +0 -0
  82. package/server/lib/event-stream/delta-coalescer.test.js +68 -57
  83. package/server/lib/event-stream/directory-ws-bridge.js +1 -1
  84. package/server/lib/event-stream/global-hub.js +10 -1
  85. package/server/lib/event-stream/global-hub.test.js +27 -26
  86. package/server/lib/event-stream/index.js +6 -0
  87. package/server/lib/event-stream/protocol.js +26 -19
  88. package/server/lib/event-stream/protocol.test.js +18 -7
  89. package/server/lib/event-stream/rebind.test.js +5 -5
  90. package/server/lib/event-stream/runtime.test.js +17 -15
  91. package/server/lib/event-stream/translate-v2.js +313 -0
  92. package/server/lib/event-stream/translate-v2.test.js +209 -0
  93. package/server/lib/event-stream/upstream-reader.test.js +16 -16
  94. package/server/lib/fs/DOCUMENTATION.md +4 -2
  95. package/server/lib/fs/byte-range.js +35 -0
  96. package/server/lib/fs/byte-range.test.js +31 -0
  97. package/server/lib/fs/routes.js +47 -42
  98. package/server/lib/fs/routes.test.js +123 -18
  99. package/server/lib/git/service.js +12 -0
  100. package/server/lib/github/DOCUMENTATION.md +1 -1
  101. package/server/lib/github/pr-status.js +22 -2
  102. package/server/lib/github/pr-status.test.js +27 -14
  103. package/server/lib/guests/DOCUMENTATION.md +13 -0
  104. package/server/lib/guests/catalog.js +12 -0
  105. package/server/lib/guests/catalog.test.js +33 -0
  106. package/server/lib/guests/routes.js +10 -1
  107. package/server/lib/guests/service.js +192 -14
  108. package/server/lib/guests/service.test.js +201 -1
  109. package/server/lib/guests/surface.js +630 -0
  110. package/server/lib/guests/surface.test.js +486 -0
  111. package/server/lib/markdown-image-grants/routes.js +18 -5
  112. package/server/lib/markdown-image-grants/routes.test.js +9 -6
  113. package/server/lib/message-queue/DOCUMENTATION.md +33 -22
  114. package/server/lib/message-queue/runtime.js +155 -100
  115. package/server/lib/message-queue/runtime.test.js +168 -82
  116. package/server/lib/notifications/DOCUMENTATION.md +28 -0
  117. package/server/lib/notifications/control-stream.http.test.js +68 -0
  118. package/server/lib/notifications/emitter-runtime.js +15 -0
  119. package/server/lib/notifications/emitter-runtime.test.js +32 -0
  120. package/server/lib/notifications/push-runtime.js +5 -1
  121. package/server/lib/notifications/push-runtime.test.js +2 -2
  122. package/server/lib/notifications/routes.js +1 -1
  123. package/server/lib/notifications/runtime.js +115 -26
  124. package/server/lib/notifications/template-runtime.js +13 -15
  125. package/server/lib/notifications/template-runtime.test.js +16 -9
  126. package/server/lib/notifications/trigger-runtime.test.js +187 -0
  127. package/server/lib/openchamber-control/DOCUMENTATION.md +10 -0
  128. package/server/lib/openchamber-control/actions.js +3 -2
  129. package/server/lib/openchamber-control/error.js +1 -1
  130. package/server/lib/openchamber-control/file-open.js +59 -0
  131. package/server/lib/openchamber-control/file-open.test.js +57 -0
  132. package/server/lib/openchamber-control/routes.test.js +12 -0
  133. package/server/lib/openchamber-control/service.js +102 -49
  134. package/server/lib/openchamber-control/service.test.js +84 -44
  135. package/server/lib/openchamber-sessions/archive-store.js +224 -0
  136. package/server/lib/openchamber-sessions/archive-store.test.js +187 -0
  137. package/server/lib/openchamber-sessions/opencode-client.js +22 -0
  138. package/server/lib/openchamber-sessions/routes.js +398 -328
  139. package/server/lib/openchamber-sessions/routes.test.js +777 -740
  140. package/server/lib/openchamber-sessions/session-metadata-store.js +285 -0
  141. package/server/lib/openchamber-sessions/session-metadata-store.test.js +259 -0
  142. package/server/lib/opencode/DOCUMENTATION.md +449 -29
  143. package/server/lib/opencode/agents.js +233 -327
  144. package/server/lib/opencode/auth.js +41 -44
  145. package/server/lib/opencode/auth.test.js +92 -0
  146. package/server/lib/opencode/cli-upgrade.d.ts +4 -0
  147. package/server/lib/opencode/cli-upgrade.js +18 -0
  148. package/server/lib/opencode/cli-upgrade.test.js +36 -0
  149. package/server/lib/opencode/commands.js +164 -145
  150. package/server/lib/opencode/compatibility.d.ts +16 -0
  151. package/server/lib/opencode/compatibility.js +88 -0
  152. package/server/lib/opencode/compatibility.test.js +62 -0
  153. package/server/lib/opencode/config-entity-routes.js +58 -29
  154. package/server/lib/opencode/config-entity-v2.test.js +290 -0
  155. package/server/lib/opencode/config-mutation-response.js +17 -7
  156. package/server/lib/opencode/config-mutation-response.test.js +4 -7
  157. package/server/lib/opencode/config-paths.test.js +2 -2
  158. package/server/lib/opencode/config-v2.d.ts +183 -0
  159. package/server/lib/opencode/config-v2.js +801 -0
  160. package/server/lib/opencode/config-v2.test.js +466 -0
  161. package/server/lib/opencode/credential-db.js +144 -0
  162. package/server/lib/opencode/credential-db.test.js +104 -0
  163. package/server/lib/opencode/env-runtime.js +48 -9
  164. package/server/lib/opencode/env-runtime.test.js +45 -0
  165. package/server/lib/opencode/feature-routes-runtime.js +15 -5
  166. package/server/lib/opencode/lifecycle-process.test.js +7 -4
  167. package/server/lib/opencode/lifecycle.js +85 -30
  168. package/server/lib/opencode/lifecycle.test.js +80 -8
  169. package/server/lib/opencode/login-shell-env.js +27 -0
  170. package/server/lib/opencode/managed-config-file.js +119 -0
  171. package/server/lib/opencode/managed-config-file.test.js +152 -0
  172. package/server/lib/opencode/managed-plugin-config.js +33 -13
  173. package/server/lib/opencode/mcp.js +43 -149
  174. package/server/lib/opencode/network-runtime.js +6 -7
  175. package/server/lib/opencode/openchamber-routes.test.js +2 -5
  176. package/server/lib/opencode/plugin-routes.js +3 -3
  177. package/server/lib/opencode/plugin-routes.test.js +6 -24
  178. package/server/lib/opencode/plugins.js +91 -40
  179. package/server/lib/opencode/plugins.test.js +28 -15
  180. package/server/lib/opencode/providers.js +63 -83
  181. package/server/lib/opencode/providers.test.js +128 -59
  182. package/server/lib/opencode/proxy-agent-wiring.test.js +4 -2
  183. package/server/lib/opencode/proxy.js +179 -129
  184. package/server/lib/opencode/pwa-manifest-routes.js +4 -2
  185. package/server/lib/opencode/pwa-manifest-routes.test.js +3 -2
  186. package/server/lib/opencode/response-envelope.js +14 -0
  187. package/server/lib/opencode/response-envelope.test.js +23 -0
  188. package/server/lib/opencode/routes-upgrade.test.js +73 -116
  189. package/server/lib/opencode/routes.js +121 -428
  190. package/server/lib/opencode/server-utils-runtime.js +10 -4
  191. package/server/lib/opencode/session-activity.js +78 -0
  192. package/server/lib/opencode/session-runtime.js +21 -10
  193. package/server/lib/opencode/session-runtime.test.js +9 -9
  194. package/server/lib/opencode/settings-helpers.js +9 -9
  195. package/server/lib/opencode/settings-helpers.test.js +7 -12
  196. package/server/lib/opencode/settings-registry.json +6 -8
  197. package/server/lib/opencode/settings-runtime.js +18 -1
  198. package/server/lib/opencode/settings-runtime.test.js +31 -2
  199. package/server/lib/opencode/shared.js +54 -22
  200. package/server/lib/opencode/shared.test.js +8 -4
  201. package/server/lib/opencode/shutdown-runtime.js +54 -7
  202. package/server/lib/opencode/shutdown-runtime.test.js +224 -30
  203. package/server/lib/opencode/skill-routes.js +23 -24
  204. package/server/lib/opencode/skills.js +7 -5
  205. package/server/lib/opencode/tunnel-wiring-runtime.js +2 -1
  206. package/server/lib/opencode/upgrade-capability.test.js +1 -1
  207. package/server/lib/opencode/v1-migration-topup.js +288 -0
  208. package/server/lib/opencode/v1-migration-topup.test.js +266 -0
  209. package/server/lib/opencode/v2-install.d.ts +8 -0
  210. package/server/lib/opencode/v2-install.js +158 -0
  211. package/server/lib/opencode/v2-install.test.js +124 -0
  212. package/server/lib/opencode/watcher.js +10 -3
  213. package/server/lib/opencode/watcher.test.js +17 -21
  214. package/server/lib/opencode/websearch-config.js +66 -0
  215. package/server/lib/package-manager.js +55 -68
  216. package/server/lib/package-manager.test.js +241 -75
  217. package/server/lib/permission-auto-accept/runtime.js +38 -22
  218. package/server/lib/permission-auto-accept/runtime.test.js +39 -17
  219. package/server/lib/quota/DOCUMENTATION.md +4 -0
  220. package/server/lib/quota/providers/xai.js +4 -4
  221. package/server/lib/relay/tunnel-host.js +4 -1
  222. package/server/lib/relay/tunnel-host.test.js +7 -0
  223. package/server/lib/routing/DOCUMENTATION.md +52 -21
  224. package/server/lib/routing/defaults.js +23 -6
  225. package/server/lib/routing/jev.js +17 -7
  226. package/server/lib/routing/routes.http.test.js +68 -33
  227. package/server/lib/routing/routes.js +65 -22
  228. package/server/lib/routing/runtime.js +145 -48
  229. package/server/lib/routing/runtime.test.js +79 -55
  230. package/server/lib/scheduled-tasks/DOCUMENTATION.md +4 -0
  231. package/server/lib/scheduled-tasks/issue-2710-double-execution.test.js +51 -46
  232. package/server/lib/scheduled-tasks/runtime.js +81 -74
  233. package/server/lib/scheduled-tasks/runtime.test.js +53 -1
  234. package/server/lib/session-assist/DOCUMENTATION.md +8 -3
  235. package/server/lib/session-assist/context.js +122 -46
  236. package/server/lib/session-assist/context.test.js +117 -49
  237. package/server/lib/session-assist/runtime.js +52 -22
  238. package/server/lib/session-assist/runtime.test.js +145 -173
  239. package/server/lib/session-goal/DOCUMENTATION.md +23 -15
  240. package/server/lib/session-goal/create.js +9 -12
  241. package/server/lib/session-goal/create.test.js +27 -28
  242. package/server/lib/session-goal/runtime.js +164 -77
  243. package/server/lib/session-goal/runtime.test.js +271 -519
  244. package/server/lib/session-knowledge/DOCUMENTATION.md +5 -0
  245. package/server/lib/session-knowledge/runtime.js +59 -41
  246. package/server/lib/session-knowledge/runtime.test.js +90 -20
  247. package/server/lib/small-model/DOCUMENTATION.md +154 -208
  248. package/server/lib/small-model/client.js +113 -0
  249. package/server/lib/small-model/index.js +296 -158
  250. package/server/lib/small-model/index.test.js +423 -256
  251. package/server/lib/small-model/routes.js +1 -1
  252. package/server/lib/spaces/DOCUMENTATION.md +807 -0
  253. package/server/lib/spaces/code-in-bait.js +185 -0
  254. package/server/lib/spaces/code-in.js +641 -0
  255. package/server/lib/spaces/code-in.test.js +1048 -0
  256. package/server/lib/spaces/errors.js +8 -0
  257. package/server/lib/spaces/exec-http.js +94 -0
  258. package/server/lib/spaces/gatekeeper-channel.js +202 -0
  259. package/server/lib/spaces/gatekeeper-channel.test.js +215 -0
  260. package/server/lib/spaces/gatekeeper-program.cjs +914 -0
  261. package/server/lib/spaces/gatekeeper-program.test.js +1391 -0
  262. package/server/lib/spaces/hardening.js +457 -0
  263. package/server/lib/spaces/hardening.test.js +368 -0
  264. package/server/lib/spaces/host-git.js +127 -0
  265. package/server/lib/spaces/host-git.test.js +137 -0
  266. package/server/lib/spaces/labels.js +234 -0
  267. package/server/lib/spaces/labels.test.js +219 -0
  268. package/server/lib/spaces/layout.js +184 -0
  269. package/server/lib/spaces/layout.test.js +30 -0
  270. package/server/lib/spaces/manager.js +82 -0
  271. package/server/lib/spaces/manager.test.js +114 -0
  272. package/server/lib/spaces/places/code-in.docker.live.test.js +216 -0
  273. package/server/lib/spaces/places/contract-suite.js +156 -0
  274. package/server/lib/spaces/places/contract.docker.live.test.js +7 -0
  275. package/server/lib/spaces/places/contract.test.js +6 -0
  276. package/server/lib/spaces/places/docker-engine.js +126 -0
  277. package/server/lib/spaces/places/docker-live-support.js +202 -0
  278. package/server/lib/spaces/places/docker-tools.js +186 -0
  279. package/server/lib/spaces/places/docker.js +587 -0
  280. package/server/lib/spaces/places/docker.test.js +1610 -0
  281. package/server/lib/spaces/places/escape-suite.js +1018 -0
  282. package/server/lib/spaces/places/escape.docker.live.test.js +7 -0
  283. package/server/lib/spaces/places/fake-docker.js +375 -0
  284. package/server/lib/spaces/places/memory-place.js +103 -0
  285. package/server/lib/spaces/places/packed.docker.live.test.js +77 -0
  286. package/server/lib/spaces/places/registry.js +43 -0
  287. package/server/lib/spaces/places/registry.test.js +50 -0
  288. package/server/lib/spaces/places/server.docker.live.test.js +225 -0
  289. package/server/lib/spaces/run-command.js +261 -0
  290. package/server/lib/spaces/run-command.test.js +396 -0
  291. package/server/lib/spaces/space-server.js +190 -0
  292. package/server/lib/spaces/space-server.test.js +335 -0
  293. package/server/lib/spaces/tools-filler.js +82 -0
  294. package/server/lib/spaces/tools-filler.test.js +148 -0
  295. package/server/lib/spaces/tools-pack.js +49 -0
  296. package/server/lib/spaces/tools-pack.test.js +57 -0
  297. package/server/lib/spaces/tools.js +138 -0
  298. package/server/lib/spaces/tools.test.js +153 -0
  299. package/server/lib/tts/openai-sdk.js +11 -0
  300. package/server/lib/tts/service.js +7 -5
  301. package/server/lib/tts/stt.js +3 -2
  302. package/server/lib/tunnels/DOCUMENTATION.md +2 -0
  303. package/server/lib/tunnels/routes.js +7 -0
  304. package/server/lib/tunnels/routes.test.js +55 -0
  305. package/server/lib/ui-auth/ui-auth.js +38 -2
  306. package/server/lib/ui-auth/ui-auth.test.js +42 -0
  307. package/server/lib/ui-auth/ui-passkeys.js +12 -10
  308. package/server/lib/walkthrough/DOCUMENTATION.md +10 -1
  309. package/server/lib/walkthrough/pull-request.js +61 -8
  310. package/server/lib/walkthrough/pull-request.test.js +54 -1
  311. package/server/lib/walkthrough/routes.js +20 -0
  312. package/server/lib/walkthrough/routes.test.js +19 -0
  313. package/server/opencode-proxy.test.js +190 -166
  314. package/server/opencode-worktree-readiness.test.js +5 -4
  315. package/dist/assets/DiffView-B2CD9wC8.js +0 -4
  316. package/dist/assets/FilesView-C4vMFclc.js +0 -13
  317. package/dist/assets/LinearIssuesView-EzGNCGrd.js +0 -1
  318. package/dist/assets/MarkdownImageGallery-B2YUDFaB.js +0 -1
  319. package/dist/assets/MarkdownRendererImpl-B4ikIzR3.js +0 -12
  320. package/dist/assets/OnboardingScreen-CQHBSTEi.js +0 -1
  321. package/dist/assets/PlanView-D3x-pTkZ.js +0 -5
  322. package/dist/assets/PluginPane-DEcgDQ9h.js +0 -3
  323. package/dist/assets/SettingsView-CSinuH-1.js +0 -29
  324. package/dist/assets/SettingsWindow-B5CHoJFZ.js +0 -1
  325. package/dist/assets/SubmoduleDiffSummary-oxeACCWs.js +0 -1
  326. package/dist/assets/ToolOutputDialog-tLNWmfcW.js +0 -15
  327. package/dist/assets/ToolPartDiffPreview-CflzmK-x.js +0 -8
  328. package/dist/assets/appThemeRegistry-DLicw4dH.js +0 -1
  329. package/dist/assets/de-Bro6_zyl.js +0 -10
  330. package/dist/assets/es-Bb9XQZvd.js +0 -16
  331. package/dist/assets/fr-Dgfzn-IL.js +0 -14
  332. package/dist/assets/index-CtQNmqUL.js +0 -1
  333. package/dist/assets/index-DqaMWNrC.css +0 -1
  334. package/dist/assets/index-Dqc6USl3.js +0 -40
  335. package/dist/assets/ja-BYsakGFh.js +0 -16
  336. package/dist/assets/ko-BSaQz9aN.js +0 -16
  337. package/dist/assets/main-B62_pjL5.js +0 -2
  338. package/dist/assets/main-BEdcOI2P.js +0 -896
  339. package/dist/assets/miniChat-LT8Rqofr.js +0 -2
  340. package/dist/assets/mobile-CqarEynh.js +0 -2
  341. package/dist/assets/pl-OIviPdoj.js +0 -16
  342. package/dist/assets/pt-BR-Cltg-E6s.js +0 -16
  343. package/dist/assets/renderElectronMiniChatApp-COyLTtZx.js +0 -2
  344. package/dist/assets/renderMobileApp-BC1MHg6g.js +0 -25
  345. package/dist/assets/runtimeEndpointReset-DdrazOVH.js +0 -25
  346. package/dist/assets/scheduledTasksApi-B2SWMGEU.js +0 -1
  347. package/dist/assets/tr-CQI-KPre.js +0 -7
  348. package/dist/assets/uk-CqW7R4DA.js +0 -16
  349. package/dist/assets/useAppFontEffects-ne84JBVL.js +0 -7333
  350. package/dist/assets/useRootScrollLock-Cpf1qoGp.js +0 -2
  351. package/dist/assets/vendor-cron-parser-CUcP7OfX.js +0 -2
  352. package/dist/assets/vendor-opencode-sdk-BJ73u-bH.js +0 -7
  353. package/dist/assets/zh-CN-CVZG_o_J.js +0 -16
  354. package/dist/assets/zh-TW-D5ZxzCZp.js +0 -16
  355. package/server/lib/opencode/mcp-oauth-callback.test.js +0 -111
  356. package/server/lib/routing/feature-flag.js +0 -11
  357. package/server/lib/small-model/call.js +0 -851
  358. package/server/lib/small-model/call.test.js +0 -1292
  359. package/server/lib/small-model/catalog.js +0 -13
  360. package/server/lib/small-model/resolve.js +0 -131
  361. package/server/lib/small-model/resolve.test.js +0 -197
  362. package/server/lib/small-model/runtime-providers.js +0 -164
  363. package/server/lib/small-model/runtime-providers.test.js +0 -118
  364. package/server/lib/system-prompt/DOCUMENTATION.md +0 -36
  365. package/server/lib/system-prompt/runtime.js +0 -49
  366. package/server/lib/system-prompt/runtime.test.js +0 -76
  367. package/server/lib/walkthrough/reproduce-2607.test.js +0 -148
@@ -13,6 +13,8 @@
13
13
 
14
14
  import fs from 'fs';
15
15
  import path from 'path';
16
+ import { unwrapOpenCodeResponse } from '../opencode/response-envelope.js';
17
+ import { createSessionActivityProbe } from '../opencode/session-activity.js';
16
18
 
17
19
  const QUEUE_FILE_NAME = 'message-queue.json';
18
20
  const QUEUE_FILE_VERSION = 1;
@@ -27,6 +29,9 @@ const DISPATCH_QUIET_MS = 500;
27
29
  // After a user abort the UI held the queue for two seconds so the stop is not
28
30
  // immediately followed by the next prompt; the server keeps that window.
29
31
  const ABORT_HOLD_MS = 2_000;
32
+ // While a background subagent keeps the turn open, how often the head is
33
+ // rechecked in case the parent's rerun idle event is missed.
34
+ const SUBAGENT_RECHECK_MS = 5_000;
30
35
  const RETRY_BASE_DELAY_MS = 2_000;
31
36
  const RETRY_MAX_DELAY_MS = 60_000;
32
37
  // A hold is asserted by a UI-driven process (auto-review) that dies with the
@@ -193,11 +198,22 @@ const extractAssistantMessageUpdate = (payload) => {
193
198
  if (!sessionId) return null;
194
199
  return {
195
200
  sessionId,
196
- aborted: asRecord(info.error)?.name === 'MessageAbortedError',
197
201
  completed: asCount(asRecord(info.time)?.completed) !== null,
198
202
  };
199
203
  };
200
204
 
205
+ /**
206
+ * A user abort no longer arrives as an assistant message carrying
207
+ * `MessageAbortedError`: v2 reports `session.execution.interrupted`, which the
208
+ * translator turns into `session.idle` with `aborted: true`.
209
+ */
210
+ const extractAbortedSessionId = (payload) => {
211
+ if (payload.type !== 'session.idle') return null;
212
+ const properties = asRecord(payload.properties) ?? {};
213
+ if (properties.aborted !== true) return null;
214
+ return asNonEmptyString(properties.sessionID);
215
+ };
216
+
201
217
  const extractDeletedSessionId = (payload) => {
202
218
  if (payload.type !== 'session.deleted') return null;
203
219
  const properties = asRecord(payload.properties) ?? {};
@@ -211,9 +227,9 @@ export function createMessageQueueRuntime({
211
227
  sessionKnowledgeRuntime = null,
212
228
  broadcastGlobalUiEvent,
213
229
  onPromptSent,
214
- // Turns the `openchamber/auto` model into a real one right before the send;
215
- // absent means the queue never sees the sentinel.
216
- resolvePromptBody = null,
230
+ // Resolves the `openchamber/auto` sentinel into a real model and agent right
231
+ // before the send; absent means the queue never sees the sentinel.
232
+ resolveAutoSelection = null,
217
233
  dataDir,
218
234
  fetchImpl = fetch,
219
235
  now = Date.now,
@@ -382,29 +398,43 @@ export function createMessageQueueRuntime({
382
398
  const detail = await response.text().catch(() => '');
383
399
  throw httpError(`OpenCode ${method} ${fetchPath} failed with ${response.status}${detail ? `: ${detail.slice(0, 200)}` : ''}`, response.status);
384
400
  }
385
- return response.json().catch(() => null);
401
+ return unwrapOpenCodeResponse(await response.json().catch(() => null));
386
402
  };
387
403
 
388
404
  /**
389
405
  * Live idleness, or null when it could not be established. Unknown is never
390
406
  * idle: a fetch failure re-arms instead of sending into a running turn.
391
407
  */
408
+ const activityProbe = createSessionActivityProbe({ buildOpenCodeUrl, getOpenCodeAuthHeaders, timeoutMs: FETCH_TIMEOUT_MS, fetchImpl });
409
+
410
+ /** True while a subagent of the session runs; null when it could not be checked. */
411
+ const hasWorkingSubagents = async (sessionId) => {
412
+ const statuses = await activityProbe.fetchActiveSessionStatuses();
413
+ if (!statuses) return null;
414
+ return activityProbe.hasWorkingChildren(sessionId, statuses);
415
+ };
416
+
392
417
  const isSessionIdle = async (sessionId, directory) => {
393
- const statuses = asRecord(await openCodeFetch('/session/status', { directory }).catch(() => null));
418
+ // `/api/session/active` is global and lists only the sessions that are
419
+ // running right now, so an absent entry means idle.
420
+ // The route answers `{ data: { [id]: { type: 'running' } } }`; the shared
421
+ // unwrap hands over the map, and an envelope is still accepted.
422
+ const body = asRecord(await openCodeFetch('/api/session/active').catch(() => null));
423
+ const statuses = asRecord(body && 'data' in body ? body.data : body);
394
424
  if (!statuses) return null;
395
- const type = asRecord(statuses[sessionId])?.type;
396
- if (type === 'busy' || type === 'retry') return false;
397
- // The status map lists only busy sessions, so a missed busy event leaves
398
- // no entry while a turn still streams. The trailing unfinished assistant
399
- // message is the live evidence of that turn (mirrors the UI gate).
400
- const messages = asList(await openCodeFetch(`/session/${encodeURIComponent(sessionId)}/message`, {
425
+ if (asRecord(statuses[sessionId])) return false;
426
+ // A missed event leaves no entry while a turn still streams. The trailing
427
+ // unfinished assistant message is the live evidence of that turn (mirrors
428
+ // the UI gate). v2 lists messages newest first.
429
+ const page = await openCodeFetch(`/api/session/${encodeURIComponent(sessionId)}/message`, {
401
430
  directory,
402
431
  query: { limit: String(MESSAGE_TAIL_LIMIT) },
403
- }).catch(() => null));
432
+ }).catch(() => null);
433
+ const messages = asList(asRecord(page)?.data);
404
434
  if (!messages) return null;
405
- const last = asRecord(asRecord(messages[messages.length - 1])?.info);
435
+ const last = asRecord(messages[0]);
406
436
  const lastTime = asRecord(last?.time);
407
- if (last?.role === 'assistant' && asCount(lastTime?.completed) === null) {
437
+ if (last?.type === 'assistant' && asCount(lastTime?.completed) === null) {
408
438
  const created = asCount(lastTime?.created);
409
439
  if (created === null || created >= runtimeStartedAt) return false;
410
440
  // Unfinished tail from before this runtime started: its run died with
@@ -420,112 +450,122 @@ export function createMessageQueueRuntime({
420
450
  const [head, ...tail] = text.split(' ');
421
451
  const name = head.slice(1);
422
452
  if (!name) return null;
423
- const commands = asList(await openCodeFetch('/command', { directory })) ?? [];
453
+ const commands = asList(await openCodeFetch('/api/command', { directory })) ?? [];
424
454
  const match = commands.map(asRecord).find((command) => command?.name === name);
425
455
  if (!match) return null;
426
456
  return {
427
457
  name,
428
458
  arguments: tail.join(' '),
429
- isSkill: match.source === 'skill',
430
- template: asNonEmptyString(match.template),
431
459
  };
432
460
  };
433
461
 
434
- /**
435
- * The prompt a slash command stands for, expanded the way OpenCode expands
436
- * it: `$ARGUMENTS` takes the whole argument string, `$1..$N` take quoted or
437
- * bare words with the last position absorbing the rest, and a template with
438
- * no placeholder gets the arguments appended. Twin of the UI's
439
- * `expandSlashCommandGoalObjective` in `packages/ui/src/sync/session-ui-store.ts`.
440
- */
441
- const expandCommandTemplate = (template, argumentsText) => {
442
- if (template.includes('$ARGUMENTS')) return template.replaceAll('$ARGUMENTS', argumentsText);
443
- const positions = [...template.matchAll(/\$(\d+)/g)].map((match) => Number(match[1]));
444
- if (positions.length > 0) {
445
- const parsed = [...argumentsText.matchAll(/"([^"]*)"|'([^']*)'|(\S+)/g)]
446
- .map((match) => match[1] ?? match[2] ?? match[3] ?? '');
447
- const last = Math.max(...positions);
448
- return template.replace(/\$(\d+)/g, (_match, value) => {
449
- const position = Number(value);
450
- return position === last ? parsed.slice(position - 1).join(' ') : (parsed[position - 1] ?? '');
451
- });
452
- }
453
- return argumentsText ? `${template}\n\n${argumentsText}` : template;
454
- };
455
-
456
- const toFilePart = (attachment) => ({
457
- type: 'file',
458
- mime: attachment.mimeType,
459
- filename: attachment.filename,
460
- url: attachment.dataUrl,
462
+ // v2 takes prompt attachments as URIs; a data URL is one.
463
+ const toPromptFile = (attachment) => ({
464
+ uri: attachment.dataUrl,
465
+ ...(attachment.filename ? { name: attachment.filename } : {}),
461
466
  });
462
467
 
463
- // Captured context is delivered the way the composer delivers it: one
464
- // synthetic text part per entry, an attached item's metadata riding along
465
- // and its reading instructions (a linked PR) going first.
466
- const toContextParts = (part) => {
467
- const synthetic = { type: 'text', text: part.text, synthetic: true };
468
- if (part.kind !== 'context') return [synthetic];
469
- synthetic.metadata = part.metadata;
468
+ /**
469
+ * Captured context travels as synthetic messages in v2 — the composer's
470
+ * inline `synthetic: true` text parts are gone. One message per entry, an
471
+ * attached item's metadata riding along, and its reading instructions (a
472
+ * linked PR) going first.
473
+ */
474
+ const toContextMessages = (part) => {
475
+ const body = { text: part.text, resume: false };
476
+ if (part.kind !== 'context') return [body];
477
+ const withMetadata = part.metadata ? { ...body, metadata: part.metadata } : body;
470
478
  return part.instructions
471
- ? [{ type: 'text', text: part.instructions, synthetic: true }, synthetic]
472
- : [synthetic];
479
+ ? [{ text: part.instructions, resume: false }, withMetadata]
480
+ : [withMetadata];
473
481
  };
474
482
 
475
483
  const sendItem = async (sessionId, directory, item) => {
476
- const { providerID, modelID, agent, variant } = item.sendConfig;
477
- const fileParts = item.attachments.map(toFilePart);
478
- const contextParts = item.context.flatMap(toContextParts);
479
- // OpenCode's command route takes file parts only, so a command queued
480
- // with captured context cannot go through it. Same rule as the composer:
481
- // without context the command route keeps its semantics; with context the
482
- // prompt route carries the expanded template (or the skill invocation as an
483
- // explicit instruction) together with the context.
484
- const command = await resolveSlashCommand(item.text, directory);
485
- if (command && contextParts.length === 0) {
486
- const body = { command: command.name, arguments: command.arguments, model: `${providerID}/${modelID}` };
487
- if (agent) body.agent = agent;
488
- if (variant) body.variant = variant;
489
- if (fileParts.length > 0) body.parts = fileParts;
490
- await resolvePromptBody?.(body, { sessionId, directory });
491
- await openCodeFetch(`/session/${encodeURIComponent(sessionId)}/command`, { directory, method: 'POST', body });
492
- return;
484
+ const { providerID, modelID, variant } = item.sendConfig;
485
+ let agent = item.sendConfig.agent;
486
+ let model = { id: modelID, providerID, ...(variant ? { variant } : {}) };
487
+ const promptFiles = item.attachments.map(toPromptFile);
488
+ const contextMessages = item.context.flatMap(toContextMessages);
489
+
490
+ // Jev routing, when the queued send named the Auto sentinel. A failure
491
+ // inside resolves to the fallback model; only a missing fallback throws.
492
+ const routed = await resolveAutoSelection?.({
493
+ sessionId,
494
+ directory,
495
+ model,
496
+ agent,
497
+ requestText: item.text,
498
+ });
499
+ if (routed) {
500
+ model = routed.model;
501
+ agent = routed.agent ?? agent;
493
502
  }
494
- let text = item.text;
495
- const commandParts = [];
496
- if (command?.isSkill) {
497
- commandParts.push({
498
- type: 'text',
499
- text: `The user explicitly invoked the ${command.name} skill. Use the corresponding skill tool to handle this request.`,
500
- synthetic: true,
503
+
504
+ // v2 selects model and agent on the session, not per prompt: the choice is
505
+ // switched once and then persists.
506
+ await openCodeFetch(`/api/session/${encodeURIComponent(sessionId)}/model`, {
507
+ directory,
508
+ method: 'POST',
509
+ body: { model },
510
+ });
511
+ if (agent) {
512
+ await openCodeFetch(`/api/session/${encodeURIComponent(sessionId)}/agent`, {
513
+ directory,
514
+ method: 'POST',
515
+ body: { agent },
501
516
  });
502
- } else if (command?.template) {
503
- text = expandCommandTemplate(command.template, command.arguments);
504
517
  }
505
518
 
506
- // Standing project context rides the prompt exactly as a UI send would
519
+ // Resolved before anything is admitted: a failed command lookup fails the
520
+ // whole send, so a retry does not admit the context twice.
521
+ const command = await resolveSlashCommand(item.text, directory);
522
+
523
+ // Standing project context rides the send exactly as a UI send would
507
524
  // attach it; a failed lookup sends without it rather than not at all.
508
525
  const knowledge = sessionKnowledgeRuntime
509
526
  ? await sessionKnowledgeRuntime.resolvePendingForSession(sessionId, directory)
510
527
  .catch(() => ({ text: '', signature: '' }))
511
528
  : { text: '', signature: '' };
512
- // Same order as a UI send: the user's text and files, the context queued
513
- // with them, then the standing context, then the mentioned agent.
514
- const parts = [];
515
- if (text.trim()) parts.push({ type: 'text', text });
516
- parts.push(...fileParts);
517
- parts.push(...contextParts);
518
- parts.push(...commandParts);
519
- if (knowledge.text) parts.push({ type: 'text', text: knowledge.text, synthetic: true });
520
- if (item.agentMention) parts.push({ type: 'agent', name: item.agentMention });
521
- const body = { model: { providerID, modelID } };
522
- if (agent) body.agent = agent;
523
- if (variant) body.variant = variant;
524
- body.parts = parts;
525
- await resolvePromptBody?.(body, { sessionId, directory });
526
- await openCodeFetch(`/session/${encodeURIComponent(sessionId)}/prompt_async`, { directory, method: 'POST', body });
529
+
530
+ // Same order as a UI send: everything attached to the message is admitted
531
+ // before the message itself, so the model reads it as background. This
532
+ // holds for a command too: its route takes file attachments only, and
533
+ // sending "/name args" as a prompt instead would skip the template
534
+ // OpenCode 2.x expands only on the command route.
535
+ const preamble = [...contextMessages];
536
+ if (knowledge.text) preamble.push({ text: knowledge.text, resume: false });
537
+ for (const synthetic of preamble) {
538
+ await openCodeFetch(`/api/session/${encodeURIComponent(sessionId)}/synthetic`, {
539
+ directory,
540
+ method: 'POST',
541
+ body: synthetic,
542
+ });
543
+ }
544
+
545
+ if (command) {
546
+ await openCodeFetch(`/api/session/${encodeURIComponent(sessionId)}/command`, {
547
+ directory,
548
+ method: 'POST',
549
+ body: {
550
+ // OpenCode 2.0.8 renamed the command body field `command` to `name`.
551
+ name: command.name,
552
+ text: command.arguments,
553
+ ...(promptFiles.length > 0 ? { files: promptFiles } : {}),
554
+ },
555
+ });
556
+ } else {
557
+ await openCodeFetch(`/api/session/${encodeURIComponent(sessionId)}/prompt`, {
558
+ directory,
559
+ method: 'POST',
560
+ body: {
561
+ text: item.text,
562
+ ...(promptFiles.length > 0 ? { files: promptFiles } : {}),
563
+ ...(item.agentMention ? { agents: [{ name: item.agentMention }] } : {}),
564
+ },
565
+ });
566
+ }
527
567
  if (knowledge.text && sessionKnowledgeRuntime) {
528
- // After the prompt is accepted, so a rejected dispatch carries it again.
568
+ // After the send is accepted, so a rejected dispatch carries it again.
529
569
  await sessionKnowledgeRuntime.recordDelivered(sessionId, directory, knowledge.signature).catch(() => undefined);
530
570
  }
531
571
  };
@@ -588,6 +628,16 @@ export function createMessageQueueRuntime({
588
628
  // Busy: the next idle status event re-arms the loop.
589
629
  if (!idle) return;
590
630
 
631
+ // A queued message waits for the whole turn. A parent idles while a
632
+ // background subagent works and runs again when OpenCode hands the
633
+ // result back, so the turn is only over once no subagent runs. That rerun
634
+ // re-arms through its idle event; the recheck covers a missed one.
635
+ const subagentsWorking = await hasWorkingSubagents(sessionId);
636
+ if (subagentsWorking !== false) {
637
+ armDispatch(sessionId, subagentsWorking === null ? retryDelayMs(1) : SUBAGENT_RECHECK_MS);
638
+ return;
639
+ }
640
+
591
641
  // Re-read after the awaits — the user may have edited the queue meanwhile.
592
642
  const current = queues.get(sessionId);
593
643
  const item = current?.items[0];
@@ -771,9 +821,14 @@ export function createMessageQueueRuntime({
771
821
  return;
772
822
  }
773
823
 
824
+ const abortedSessionId = extractAbortedSessionId(payload);
825
+ if (abortedSessionId) {
826
+ if (queues.has(abortedSessionId)) abortedAt.set(abortedSessionId, now());
827
+ return;
828
+ }
829
+
774
830
  const assistant = extractAssistantMessageUpdate(payload);
775
831
  if (assistant && queues.has(assistant.sessionId)) {
776
- if (assistant.aborted) abortedAt.set(assistant.sessionId, now());
777
832
  // A completed reply without a following idle status (missed event)
778
833
  // must still drain the queue; the tick verifies idleness itself.
779
834
  if (assistant.completed && !timers.has(assistant.sessionId)) armDispatch(assistant.sessionId);
@@ -781,8 +836,8 @@ export function createMessageQueueRuntime({
781
836
  };
782
837
 
783
838
  const processEvent = (event) => {
784
- const raw = asRecord(asRecord(event)?.payload);
785
- processPayload(asRecord(raw?.payload) ?? raw);
839
+ // The hub translates v2 wire events into the server's vocabulary once.
840
+ for (const payload of event?.translated?.() ?? []) processPayload(payload);
786
841
  };
787
842
 
788
843
  const start = () => {