@vantran-se/openchamber-web 1.24.4 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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-ntXIbhV2.js} +1 -1
  5. package/dist/assets/DiffView-CjxUovbM.js +4 -0
  6. package/dist/assets/FilesView-DFWD0RQR.js +17 -0
  7. package/dist/assets/{GitView-Byu2DY7s.js → GitView-BWa7e5vw.js} +4 -4
  8. package/dist/assets/{GuestAttachDialog-B808E0-d.js → GuestAttachDialog-DdOuyZzp.js} +1 -1
  9. package/dist/assets/GuestSurfacePane-DDfzid3U.js +1 -0
  10. package/dist/assets/{JsonTreeView-VW_7czo3.js → JsonTreeView-3sGwqexh.js} +1 -1
  11. package/dist/assets/LinearIssuesView-C6dpIdjw.js +1 -0
  12. package/dist/assets/MarkdownImageGallery-Q7YR_tl4.js +1 -0
  13. package/dist/assets/MarkdownRendererImpl-DxDV56bL.js +12 -0
  14. package/dist/assets/OnboardingScreen-rK4Stg__.js +1 -0
  15. package/dist/assets/{PatchDiff-DCjGhlYV.js → PatchDiff-DS-IMU1j.js} +1 -1
  16. package/dist/assets/{PierreDiffViewer-CEDZNkU2.js → PierreDiffViewer-DW23KWKZ.js} +1 -1
  17. package/dist/assets/PlanView-BCk_VobP.js +5 -0
  18. package/dist/assets/PluginPane-BPP1dbck.js +3 -0
  19. package/dist/assets/SettingsView-kMmrpn43.js +29 -0
  20. package/dist/assets/SettingsWindow-BpvD6IYQ.js +1 -0
  21. package/dist/assets/SubmoduleDiffSummary-BLttSS1X.js +1 -0
  22. package/dist/assets/ToolOutputDialog-CtqDqbyr.js +15 -0
  23. package/dist/assets/ToolPartDiffPreview-5FcKdyRy.js +8 -0
  24. package/dist/assets/{VirtualizedFileDiff-NU0FHFhT.js → VirtualizedFileDiff-C763hNCR.js} +4 -4
  25. package/dist/assets/{WalkthroughView-BZyjhqHv.js → WalkthroughView-lap5btCF.js} +2 -2
  26. package/dist/assets/appThemeRegistry-u4zw1l0B.js +1 -0
  27. package/dist/assets/{commitAndPush-BDftrjr6.js → commitAndPush-CwGJfJG-.js} +1 -1
  28. package/dist/assets/{computeVirtualFileMetrics-DlWlEM3x.js → computeVirtualFileMetrics-DW5jjX4n.js} +1 -1
  29. package/dist/assets/de-CndEg67T.js +10 -0
  30. package/dist/assets/es-DglvPlaC.js +16 -0
  31. package/dist/assets/fr-DejPCpbS.js +14 -0
  32. package/dist/assets/index-C2r64QfD.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-D47a6hMP.js} +1 -1
  36. package/dist/assets/{isFilePlainText-ue6kCou7.js → isFilePlainText-B-mGgeKl.js} +1 -1
  37. package/dist/assets/ja-CVpQawCd.js +16 -0
  38. package/dist/assets/ko-Bw446h9j.js +16 -0
  39. package/dist/assets/main-Bz4WWXbr.js +2 -0
  40. package/dist/assets/main-oreqDsOV.js +896 -0
  41. package/dist/assets/{markdownCore-CK48LG0z.js → markdownCore-D2e5sp9y.js} +4 -4
  42. package/dist/assets/miniChat-D1v2gsBI.js +2 -0
  43. package/dist/assets/mobile-DBj3lCf2.js +2 -0
  44. package/dist/assets/{patchFileDiff-D7QVlovD.js → patchFileDiff-BpeUOV91.js} +3 -3
  45. package/dist/assets/pl-BYNlPdhm.js +16 -0
  46. package/dist/assets/pt-BR-CL-Yfv9H.js +16 -0
  47. package/dist/assets/renderElectronMiniChatApp-DVtfEB2z.js +2 -0
  48. package/dist/assets/renderMobileApp-DFp9-xbG.js +25 -0
  49. package/dist/assets/runtimeEndpointReset-CsIpUep1.js +27 -0
  50. package/dist/assets/scheduledTasksApi-B5OHVpPM.js +1 -0
  51. package/dist/assets/{shikiHighlight-BPu3JiQs.js → shikiHighlight-DNm2Z_Jc.js} +1 -1
  52. package/dist/assets/{textMateThemeFromAppTheme-DWqRPo9A.js → textMateThemeFromAppTheme-DGF2kG7g.js} +1 -1
  53. package/dist/assets/tr-DzmbxLy-.js +7 -0
  54. package/dist/assets/uk-C7vQnwro.js +16 -0
  55. package/dist/assets/useAppFontEffects-Ci3FEaPf.js +7337 -0
  56. package/dist/assets/{useInlineCommentController-CgS0fnw_.js → useInlineCommentController-CuUuakrt.js} +2 -2
  57. package/dist/assets/useRootScrollLock-CQIsyERq.js +2 -0
  58. package/dist/assets/{vendor-codemirror-language-data-Bx2EHc1O.js → vendor-codemirror-language-data-CQa7_1cr.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-B6tKQyJN.js} +2 -2
  64. package/dist/assets/zh-CN-Cl0srS-z.js +16 -0
  65. package/dist/assets/zh-TW-DtII5bDb.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
@@ -27,8 +27,10 @@ const closeServer = (server) => new Promise((resolve, reject) => {
27
27
  describe('OpenCode proxy SSE forwarding', () => {
28
28
  let upstreamServer;
29
29
  let proxyServer;
30
+ const originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
30
31
 
31
32
  afterEach(async () => {
33
+ Object.defineProperty(process, 'platform', originalPlatform);
32
34
  await closeServer(proxyServer);
33
35
  await closeServer(upstreamServer);
34
36
  proxyServer = undefined;
@@ -39,7 +41,7 @@ describe('OpenCode proxy SSE forwarding', () => {
39
41
  let seenAuthorization = null;
40
42
 
41
43
  const upstream = express();
42
- upstream.get('/global/event', (req, res) => {
44
+ upstream.get('/api/event', (req, res) => {
43
45
  seenAuthorization = req.headers.authorization ?? null;
44
46
  res.setHeader('Content-Type', 'text/event-stream; charset=utf-8');
45
47
  res.setHeader('Cache-Control', 'private, max-age=0');
@@ -85,7 +87,7 @@ describe('OpenCode proxy SSE forwarding', () => {
85
87
  it('closes downstream SSE when the OpenCode upstream stalls despite proxy heartbeats', async () => {
86
88
  let stallTimeoutReads = 0;
87
89
  const upstream = express();
88
- upstream.get('/global/event', (_req, res) => {
90
+ upstream.get('/api/event', (_req, res) => {
89
91
  res.setHeader('Content-Type', 'text/event-stream');
90
92
  res.flushHeaders();
91
93
  setTimeout(() => res.write(':upstream-alive\n\n'), 40);
@@ -133,7 +135,7 @@ describe('OpenCode proxy SSE forwarding', () => {
133
135
 
134
136
  it('holds a request through OpenCode warmup and succeeds once ready (no 503/backoff)', async () => {
135
137
  const upstream = express();
136
- upstream.get('/config/providers', (_req, res) => {
138
+ upstream.get('/api/config/providers', (_req, res) => {
137
139
  res.json({ ok: true });
138
140
  });
139
141
  upstreamServer = await listen(upstream);
@@ -227,7 +229,7 @@ describe('OpenCode proxy SSE forwarding', () => {
227
229
 
228
230
  it('routes generic API requests through external OpenCode base URL', async () => {
229
231
  const upstream = express();
230
- upstream.get('/config/providers', (_req, res) => {
232
+ upstream.get('/api/config/providers', (_req, res) => {
231
233
  res.json({ ok: true, source: 'external-host' });
232
234
  });
233
235
  upstreamServer = await listen(upstream);
@@ -262,7 +264,7 @@ describe('OpenCode proxy SSE forwarding', () => {
262
264
 
263
265
  it('replays parsed urlencoded bodies to generic API proxy requests', async () => {
264
266
  const upstream = express();
265
- upstream.post('/form', express.urlencoded({ extended: true }), (req, res) => {
267
+ upstream.post('/api/form', express.urlencoded({ extended: true }), (req, res) => {
266
268
  res.json({ body: req.body });
267
269
  });
268
270
  upstreamServer = await listen(upstream);
@@ -302,7 +304,7 @@ describe('OpenCode proxy SSE forwarding', () => {
302
304
 
303
305
  it('replays parsed JSON bodies to generic API proxy requests', async () => {
304
306
  const upstream = express();
305
- upstream.post('/session/abc/prompt_async', express.json(), (req, res) => {
307
+ upstream.post('/api/session/abc/prompt', express.json(), (req, res) => {
306
308
  res.json({
307
309
  body: req.body,
308
310
  authorization: req.headers.authorization,
@@ -335,7 +337,7 @@ describe('OpenCode proxy SSE forwarding', () => {
335
337
  const proxyPort = proxyServer.address().port;
336
338
 
337
339
  const payload = { messageID: 'msg_1', parts: [{ type: 'text', text: 'hello' }] };
338
- const response = await fetch(`http://127.0.0.1:${proxyPort}/api/session/abc/prompt_async`, {
340
+ const response = await fetch(`http://127.0.0.1:${proxyPort}/api/session/abc/prompt`, {
339
341
  method: 'POST',
340
342
  headers: { 'content-type': 'application/json' },
341
343
  body: JSON.stringify(payload),
@@ -348,44 +350,44 @@ describe('OpenCode proxy SSE forwarding', () => {
348
350
  expect(Number(data.contentLength)).toBeGreaterThan(0);
349
351
  });
350
352
 
351
- it('sanitizes experimental session list responses and forwards query params', async () => {
353
+ it.each([
354
+ ['win32', ''],
355
+ ['win32', '&directory=%2Flink%2Frepo'],
356
+ ['linux', ''],
357
+ ['linux', '&directory=%2Flink%2Frepo'],
358
+ ])('sanitizes session pages and forwards query params (%s, %s)', async (platform, directoryQuery) => {
359
+ Object.defineProperty(process, 'platform', { value: platform, configurable: true });
352
360
  let seenQuery = null;
353
361
  let seenAuth = null;
354
362
 
355
363
  const upstream = express();
356
- upstream.get('/experimental/session', (req, res) => {
364
+ upstream.get('/api/session', (req, res) => {
357
365
  seenQuery = req.query;
358
366
  seenAuth = req.headers.authorization ?? null;
359
367
  res.setHeader('X-Next-Cursor', '123');
360
- res.json([
361
- {
362
- id: 'ses_1',
363
- slug: 'alpha',
364
- projectID: 'proj_1',
365
- workspaceID: 'ws_1',
366
- directory: '/repo/app',
367
- path: '/repo/app',
368
- parentID: 'ses_parent',
369
- title: 'Alpha',
370
- agent: 'build',
371
- model: { id: 'gpt-5', providerID: 'openai', variant: 'default' },
372
- version: '1.0.0',
373
- time: { created: 1, updated: 2 },
374
- cost: 7,
375
- tokens: { input: 10, output: 20 },
376
- share: { url: 'https://share.example/ses_1' },
377
- project: { id: 'proj_1', worktree: '/repo/app' },
378
- summary: {
379
- additions: 5,
380
- deletions: 3,
381
- files: 2,
382
- diffs: [{ patch: '@@ -1 +1 @@', additions: 5, deletions: 3 }],
368
+ res.json({
369
+ data: [
370
+ {
371
+ id: 'ses_1',
372
+ projectID: 'proj_1',
373
+ location: { directory: '/repo/app', workspaceID: 'ws_1' },
374
+ subpath: 'app',
375
+ parentID: 'ses_parent',
376
+ title: 'Alpha',
377
+ agent: 'build',
378
+ model: { id: 'gpt-5', providerID: 'openai', variant: 'default' },
379
+ time: { created: 1, updated: 2, archived: 3 },
380
+ cost: 7,
381
+ tokens: { input: 10, output: 20 },
382
+ outcome: 'succeeded',
383
+ fork: { sessionID: 'ses_source', boundary: { type: 'through' } },
384
+ metadata: { openchamber: { kind: 'review', originalSessionID: 'ses_original' } },
385
+ permissions: [{ action: 'deny', resources: ['*'] }],
386
+ revert: { messageID: 'msg_1', partID: 'part_1', snapshot: 'abc123', files: ['a.ts'] },
383
387
  },
384
- metadata: { openchamber: { kind: 'review', originalSessionID: 'ses_original' } },
385
- permission: [{ permission: 'todowrite', action: 'deny', pattern: '*' }],
386
- revert: { messageID: 'msg_1', partID: 'part_1', snapshot: 'abc123', diff: 'diff --git a/x b/x' },
387
- },
388
- ]);
388
+ ],
389
+ cursor: { next: '123' },
390
+ });
389
391
  });
390
392
  upstreamServer = await listen(upstream);
391
393
  const upstreamPort = upstreamServer.address().port;
@@ -415,74 +417,104 @@ describe('OpenCode proxy SSE forwarding', () => {
415
417
  proxyServer = await listen(app);
416
418
  const proxyPort = proxyServer.address().port;
417
419
 
418
- const response = await fetch(`http://127.0.0.1:${proxyPort}/api/experimental/session?archived=false&limit=500&cursor=99&roots=true&directory=%2Flink%2Frepo`);
420
+ const response = await fetch(`http://127.0.0.1:${proxyPort}/api/session?archived=false&limit=500&cursor=99&roots=true${directoryQuery}`);
419
421
 
420
422
  expect(response.status).toBe(200);
421
423
  expect(response.headers.get('x-next-cursor')).toBe('123');
422
424
  expect(seenAuth).toBe('Bearer session-token');
423
- expect(seenQuery).toMatchObject({
425
+ const expectedQuery = {
424
426
  archived: 'false',
425
427
  limit: '500',
426
428
  cursor: '99',
427
429
  roots: 'true',
428
- directory: '/real/repo',
429
- });
430
-
431
- await expect(response.json()).resolves.toEqual([
432
- {
433
- id: 'ses_1',
434
- slug: 'alpha',
435
- projectID: 'proj_1',
436
- workspaceID: 'ws_1',
437
- directory: '/repo/app',
438
- path: '/repo/app',
439
- parentID: 'ses_parent',
440
- title: 'Alpha',
441
- agent: 'build',
442
- model: { id: 'gpt-5', providerID: 'openai', variant: 'default' },
443
- version: '1.0.0',
444
- time: { created: 1, updated: 2 },
445
- cost: 7,
446
- tokens: { input: 10, output: 20 },
447
- share: { url: 'https://share.example/ses_1' },
448
- metadata: { openchamber: { kind: 'review', originalSessionID: 'ses_original' } },
449
- project: { id: 'proj_1', worktree: '/repo/app' },
450
- summary: { additions: 5, deletions: 3, files: 2 },
451
- revert: { messageID: 'msg_1', partID: 'part_1' },
452
- },
453
- ]);
430
+ };
431
+ if (directoryQuery) expectedQuery.directory = '/real/repo';
432
+ expect(seenQuery).toEqual(expectedQuery);
433
+
434
+ // The heavy parts of a revert and the per-session permission ruleset are
435
+ // dropped; everything the list view reads survives.
436
+ await expect(response.json()).resolves.toEqual({
437
+ data: [
438
+ {
439
+ id: 'ses_1',
440
+ projectID: 'proj_1',
441
+ location: { directory: '/repo/app', workspaceID: 'ws_1' },
442
+ subpath: 'app',
443
+ parentID: 'ses_parent',
444
+ title: 'Alpha',
445
+ agent: 'build',
446
+ model: { id: 'gpt-5', providerID: 'openai', variant: 'default' },
447
+ time: { created: 1, updated: 2, archived: 3 },
448
+ cost: 7,
449
+ tokens: { input: 10, output: 20 },
450
+ outcome: 'succeeded',
451
+ fork: { sessionID: 'ses_source', boundary: { type: 'through' } },
452
+ metadata: { openchamber: { kind: 'review', originalSessionID: 'ses_original' } },
453
+ revert: { messageID: 'msg_1', partID: 'part_1' },
454
+ },
455
+ ],
456
+ cursor: { next: '123' },
457
+ });
458
+ });
459
+
460
+ it.each([
461
+ [200, { data: [], cursor: {} }],
462
+ [503, { error: 'Upstream unavailable' }],
463
+ ])('preserves Windows global list status and empty/error payload (%s)', async (status, payload) => {
464
+ Object.defineProperty(process, 'platform', { value: 'win32', configurable: true });
465
+ const upstream = express();
466
+ upstream.get('/api/session', (_req, res) => res.status(status).json(payload));
467
+ upstreamServer = await listen(upstream);
468
+ const upstreamPort = upstreamServer.address().port;
469
+ const baseUrl = `http://127.0.0.1:${upstreamPort}`;
470
+ const app = express();
471
+ registerOpenCodeProxy(app, {
472
+ fs: {},
473
+ OPEN_CODE_READY_GRACE_MS: 0,
474
+ getRuntime: () => ({
475
+ openCodePort: upstreamPort,
476
+ openCodeBaseUrl: baseUrl,
477
+ isOpenCodeReady: true,
478
+ openCodeNotReadySince: 0,
479
+ isRestartingOpenCode: false,
480
+ }),
481
+ getOpenCodeAuthHeaders: () => ({}),
482
+ buildOpenCodeUrl: (requestPath) => `${baseUrl}${requestPath}`,
483
+ ensureOpenCodeApiPrefix: () => {},
484
+ });
485
+ proxyServer = await listen(app);
486
+ const response = await fetch(`http://127.0.0.1:${proxyServer.address().port}/api/session?limit=1`);
487
+ expect(response.status).toBe(status);
488
+ expect(await response.json()).toEqual(payload);
454
489
  });
455
490
 
456
491
  it('sanitizes session list responses without sanitizing session detail responses', async () => {
457
492
  let seenListQuery = null;
458
493
 
459
494
  const upstream = express();
460
- upstream.get('/session', (req, res) => {
495
+ upstream.get('/api/session', (req, res) => {
461
496
  seenListQuery = req.query;
462
- res.json([
463
- {
464
- id: 'ses_1',
465
- directory: '/repo/app',
466
- title: 'Alpha',
467
- time: { created: 1, updated: 2 },
468
- summary: {
469
- additions: 5,
470
- deletions: 3,
471
- files: 2,
472
- diffs: [{ patch: '@@ -1 +1 @@', additions: 5, deletions: 3 }],
497
+ res.json({
498
+ data: [
499
+ {
500
+ id: 'ses_1',
501
+ location: { directory: '/repo/app' },
502
+ title: 'Alpha',
503
+ time: { created: 1, updated: 2 },
504
+ metadata: { custom: { value: 'kept' } },
505
+ permissions: [{ action: 'deny', resources: ['*'] }],
506
+ revert: { messageID: 'msg_1', partID: 'part_1', snapshot: 'abc123', files: ['a.ts'] },
473
507
  },
474
- metadata: { custom: { value: 'kept' } },
475
- revert: { messageID: 'msg_1', partID: 'part_1', snapshot: 'abc123', diff: 'diff --git a/x b/x' },
476
- },
477
- ]);
508
+ ],
509
+ cursor: {},
510
+ });
478
511
  });
479
- upstream.get('/session/abc', (_req, res) => {
512
+ upstream.get('/api/session/abc', (_req, res) => {
480
513
  res.json({
481
514
  id: 'abc',
482
- directory: '/repo/app',
515
+ location: { directory: '/repo/app' },
483
516
  title: 'Detail',
484
- summary: { diffs: [{ patch: '@@ -1 +1 @@' }] },
485
- revert: { messageID: 'msg_1', snapshot: 'abc123', diff: 'diff --git a/x b/x' },
517
+ revert: { messageID: 'msg_1', snapshot: 'abc123', files: ['a.ts'] },
486
518
  });
487
519
  });
488
520
  upstreamServer = await listen(upstream);
@@ -517,79 +549,48 @@ describe('OpenCode proxy SSE forwarding', () => {
517
549
 
518
550
  expect(listResponse.status).toBe(200);
519
551
  expect(seenListQuery).toMatchObject({ directory: '/real/repo' });
520
- await expect(listResponse.json()).resolves.toEqual([
521
- {
522
- id: 'ses_1',
523
- directory: '/repo/app',
524
- title: 'Alpha',
525
- time: { created: 1, updated: 2 },
526
- summary: { additions: 5, deletions: 3, files: 2 },
527
- metadata: { custom: { value: 'kept' } },
528
- revert: { messageID: 'msg_1', partID: 'part_1' },
529
- },
530
- ]);
552
+ await expect(listResponse.json()).resolves.toEqual({
553
+ data: [
554
+ {
555
+ id: 'ses_1',
556
+ location: { directory: '/repo/app' },
557
+ title: 'Alpha',
558
+ time: { created: 1, updated: 2 },
559
+ metadata: { custom: { value: 'kept' } },
560
+ revert: { messageID: 'msg_1', partID: 'part_1' },
561
+ },
562
+ ],
563
+ cursor: {},
564
+ });
531
565
 
532
566
  const detailResponse = await fetch(`http://127.0.0.1:${proxyPort}/api/session/abc`);
533
567
 
534
568
  expect(detailResponse.status).toBe(200);
535
569
  await expect(detailResponse.json()).resolves.toEqual({
536
570
  id: 'abc',
537
- directory: '/repo/app',
571
+ location: { directory: '/repo/app' },
538
572
  title: 'Detail',
539
- summary: { diffs: [{ patch: '@@ -1 +1 @@' }] },
540
- revert: { messageID: 'msg_1', snapshot: 'abc123', diff: 'diff --git a/x b/x' },
573
+ revert: { messageID: 'msg_1', snapshot: 'abc123', files: ['a.ts'] },
541
574
  });
542
575
  });
543
576
 
544
- it('forwards unparsed SDK JSON bodies to generic API proxy requests', async () => {
577
+ it('folds OpenChamber-owned archive state and metadata onto sessions it serves', async () => {
545
578
  const upstream = express();
546
- upstream.post('/session/abc/revert', express.json(), (req, res) => {
579
+ upstream.get('/api/session', (_req, res) => {
547
580
  res.json({
548
- body: req.body,
549
- contentLength: req.headers['content-length'],
581
+ data: [
582
+ { id: 'ses_1', location: { directory: '/repo/app' }, title: 'Alpha', time: { created: 1, updated: 2 }, metadata: { fromOpenCode: true, shared: 'theirs', removed: 'stale' } },
583
+ { id: 'ses_2', location: { directory: '/repo/app' }, title: 'Beta', time: { created: 1, updated: 3, archived: 999 }, metadata: { openchamber: { reviewSessionID: 'ses_old' } } },
584
+ { id: 'ses_3', metadata: { untouched: true } },
585
+ ],
586
+ cursor: {},
550
587
  });
551
588
  });
552
- upstreamServer = await listen(upstream);
553
- const upstreamPort = upstreamServer.address().port;
554
- const externalBaseUrl = `http://127.0.0.1:${upstreamPort}`;
555
-
556
- const app = express();
557
- registerOpenCodeProxy(app, {
558
- fs: {},
559
- os: {},
560
- path,
561
- OPEN_CODE_READY_GRACE_MS: 0,
562
- getRuntime: () => ({
563
- openCodePort: upstreamPort,
564
- openCodeBaseUrl: externalBaseUrl,
565
- isOpenCodeReady: true,
566
- openCodeNotReadySince: 0,
567
- isRestartingOpenCode: false,
568
- }),
569
- getOpenCodeAuthHeaders: () => ({}),
570
- buildOpenCodeUrl: (requestPath) => `${externalBaseUrl}${requestPath}`,
571
- ensureOpenCodeApiPrefix: () => {},
572
- });
573
- proxyServer = await listen(app);
574
- const proxyPort = proxyServer.address().port;
575
-
576
- const payload = { messageID: 'msg_1' };
577
- const response = await fetch(`http://127.0.0.1:${proxyPort}/api/session/abc/revert`, {
578
- method: 'POST',
579
- headers: { 'content-type': 'application/json' },
580
- body: JSON.stringify(payload),
589
+ upstream.get('/api/session/ses_1', (_req, res) => {
590
+ res.json({ id: 'ses_1', location: { directory: '/repo/app' }, title: 'Alpha', metadata: { fromOpenCode: true, shared: 'theirs', removed: 'stale' } });
581
591
  });
582
-
583
- expect(response.status).toBe(200);
584
- const data = await response.json();
585
- expect(data.body).toEqual(payload);
586
- expect(Number(data.contentLength)).toBeGreaterThan(0);
587
- });
588
-
589
- it('uses the long proxy timeout budget for slow upstream responses', async () => {
590
- const upstream = express();
591
- upstream.get('/slow', (_req, _res) => {
592
- // Leave the response open so the proxy timeout path is exercised.
592
+ upstream.get('/api/session/ses_2', (_req, res) => {
593
+ res.json({ id: 'ses_2', metadata: { openchamber: { reviewSessionID: 'ses_old' } } });
593
594
  });
594
595
  upstreamServer = await listen(upstream);
595
596
  const upstreamPort = upstreamServer.address().port;
@@ -601,7 +602,6 @@ describe('OpenCode proxy SSE forwarding', () => {
601
602
  os: {},
602
603
  path,
603
604
  OPEN_CODE_READY_GRACE_MS: 0,
604
- LONG_REQUEST_TIMEOUT_MS: 50,
605
605
  getRuntime: () => ({
606
606
  openCodePort: upstreamPort,
607
607
  openCodeBaseUrl: externalBaseUrl,
@@ -612,24 +612,48 @@ describe('OpenCode proxy SSE forwarding', () => {
612
612
  getOpenCodeAuthHeaders: () => ({}),
613
613
  buildOpenCodeUrl: (requestPath) => `${externalBaseUrl}${requestPath}`,
614
614
  ensureOpenCodeApiPrefix: () => {},
615
+ getArchivedSessions: async () => ({ ses_1: 4242 }),
616
+ getStoredSessionMetadata: async () => ({
617
+ ses_1: { fromOpenCode: true, openchamber: { goal: { status: 'active' } }, shared: 'ours' },
618
+ ses_2: {},
619
+ }),
615
620
  });
616
621
  proxyServer = await listen(app);
617
622
  const proxyPort = proxyServer.address().port;
618
623
 
619
- const response = await fetch(`http://127.0.0.1:${proxyPort}/api/slow`, {
620
- signal: AbortSignal.timeout(2000),
621
- });
622
-
623
- expect(response.status).toBe(504);
624
- await expect(response.json()).resolves.toMatchObject({ error: 'OpenCode upstream timed out' });
624
+ const list = await (await fetch(`http://127.0.0.1:${proxyPort}/api/session`)).json();
625
+ // The seeded metadata includes unchanged upstream fields but excludes
626
+ // deleted keys. Empty metadata is authoritative too.
627
+ expect(list.data[0]).toMatchObject({
628
+ id: 'ses_1',
629
+ time: { created: 1, updated: 2, archived: 4242 },
630
+ metadata: { fromOpenCode: true, shared: 'ours', openchamber: { goal: { status: 'active' } } },
631
+ });
632
+ expect(list.data[0].metadata).not.toHaveProperty('removed');
633
+ expect(list.data[1].metadata).toEqual({});
634
+ expect(list.data[2].metadata).toEqual({ untouched: true });
635
+ // The archive file does not mention ses_2, so the stamp OpenCode carries
636
+ // (a session migrated from v1) stays as it is.
637
+ expect(list.data[1].time).toEqual({ created: 1, updated: 3, archived: 999 });
638
+
639
+ const detail = await (await fetch(`http://127.0.0.1:${proxyPort}/api/session/ses_1`)).json();
640
+ expect(detail).toMatchObject({
641
+ id: 'ses_1',
642
+ time: { archived: 4242 },
643
+ metadata: { fromOpenCode: true, shared: 'ours', openchamber: { goal: { status: 'active' } } },
644
+ });
645
+ expect(detail.metadata).not.toHaveProperty('removed');
646
+ const cleared = await (await fetch(`http://127.0.0.1:${proxyPort}/api/session/ses_2`)).json();
647
+ expect(cleared.metadata).toEqual({});
625
648
  });
626
649
 
627
- it('exempts interactive provider OAuth callbacks from the request deadline', async () => {
650
+ it('forwards unparsed SDK JSON bodies to generic API proxy requests', async () => {
628
651
  const upstream = express();
629
- // Stands in for upstream blocking until the user finishes signing in.
630
- upstream.post('/provider/:providerID/oauth/callback', async (_req, res) => {
631
- await new Promise((resolve) => setTimeout(resolve, 250));
632
- res.json(true);
652
+ upstream.post('/api/session/abc/revert', express.json(), (req, res) => {
653
+ res.json({
654
+ body: req.body,
655
+ contentLength: req.headers['content-length'],
656
+ });
633
657
  });
634
658
  upstreamServer = await listen(upstream);
635
659
  const upstreamPort = upstreamServer.address().port;
@@ -641,7 +665,6 @@ describe('OpenCode proxy SSE forwarding', () => {
641
665
  os: {},
642
666
  path,
643
667
  OPEN_CODE_READY_GRACE_MS: 0,
644
- LONG_REQUEST_TIMEOUT_MS: 50,
645
668
  getRuntime: () => ({
646
669
  openCodePort: upstreamPort,
647
670
  openCodeBaseUrl: externalBaseUrl,
@@ -656,20 +679,22 @@ describe('OpenCode proxy SSE forwarding', () => {
656
679
  proxyServer = await listen(app);
657
680
  const proxyPort = proxyServer.address().port;
658
681
 
659
- const response = await fetch(`http://127.0.0.1:${proxyPort}/api/provider/github-copilot/oauth/callback`, {
682
+ const payload = { messageID: 'msg_1' };
683
+ const response = await fetch(`http://127.0.0.1:${proxyPort}/api/session/abc/revert`, {
660
684
  method: 'POST',
661
685
  headers: { 'content-type': 'application/json' },
662
- body: JSON.stringify({ method: 0 }),
663
- signal: AbortSignal.timeout(5000),
686
+ body: JSON.stringify(payload),
664
687
  });
665
688
 
666
689
  expect(response.status).toBe(200);
667
- await expect(response.json()).resolves.toBe(true);
690
+ const data = await response.json();
691
+ expect(data.body).toEqual(payload);
692
+ expect(Number(data.contentLength)).toBeGreaterThan(0);
668
693
  });
669
694
 
670
- it('still applies the request deadline to the OAuth authorize call', async () => {
695
+ it('uses the long proxy timeout budget for slow upstream responses', async () => {
671
696
  const upstream = express();
672
- upstream.post('/provider/:providerID/oauth/authorize', (_req, _res) => {
697
+ upstream.get('/api/slow', (_req, _res) => {
673
698
  // Leave the response open so the proxy timeout path is exercised.
674
699
  });
675
700
  upstreamServer = await listen(upstream);
@@ -697,13 +722,12 @@ describe('OpenCode proxy SSE forwarding', () => {
697
722
  proxyServer = await listen(app);
698
723
  const proxyPort = proxyServer.address().port;
699
724
 
700
- const response = await fetch(`http://127.0.0.1:${proxyPort}/api/provider/github-copilot/oauth/authorize`, {
701
- method: 'POST',
702
- headers: { 'content-type': 'application/json' },
703
- body: JSON.stringify({ method: 0 }),
725
+ const response = await fetch(`http://127.0.0.1:${proxyPort}/api/slow`, {
704
726
  signal: AbortSignal.timeout(2000),
705
727
  });
706
728
 
707
729
  expect(response.status).toBe(504);
730
+ await expect(response.json()).resolves.toMatchObject({ error: 'OpenCode upstream timed out' });
708
731
  });
732
+
709
733
  });
@@ -36,11 +36,12 @@ async function createFixture({ timeoutMs = 1000 } = {}) {
36
36
  instance ??= bootstrap.phase === 'directory-created'
37
37
  ? { projectID: 'global', config: {} }
38
38
  : { projectID: 'project-3464', config: projectConfig };
39
- if (req.path === '/config') return res.json(instance.config);
40
- if (req.path === '/session' && req.method === 'POST') {
39
+ if (req.path === '/api/config') return res.json(instance.config);
40
+ if (req.path === '/api/session' && req.method === 'POST') {
41
41
  return res.json({ projectID: instance.projectID, directory: req.query.directory, title: req.body.title });
42
42
  }
43
- res.json([]);
43
+ // v2 pages the session list as `{ data, cursor }`.
44
+ res.json({ data: [], cursor: {} });
44
45
  });
45
46
  const upstreamUrl = await listen(upstream);
46
47
  const app = express();
@@ -91,7 +92,7 @@ describe('issue #3464 worktree OpenCode initialization', () => {
91
92
  expect(fixture.forwarded).toEqual([]);
92
93
  fixture.setBootstrap({ status: 'ready', phase: 'setup-ready', error: null });
93
94
  expect((await response).status).toBe(200);
94
- expect(fixture.forwarded).toEqual(['/session']);
95
+ expect(fixture.forwarded).toEqual(['/api/session']);
95
96
  });
96
97
 
97
98
  it('does not block unrelated directories while a worktree is pending', async () => {