@vantran-se/openchamber-web 2.1.1 → 2.2.0

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 (442) hide show
  1. package/README.md +32 -24
  2. package/bin/cli.js +1 -3
  3. package/bin/cli.test.js +40 -16
  4. package/bin/lib/DOCUMENTATION.md +6 -5
  5. package/bin/lib/cli-args.js +6 -1
  6. package/bin/lib/cli-args.test.js +34 -0
  7. package/bin/lib/cli-lifecycle.js +0 -1
  8. package/bin/lib/cli-network.js +8 -2
  9. package/bin/lib/cli-process.js +1 -1
  10. package/bin/lib/cli-settings-accessors.test.js +21 -13
  11. package/bin/lib/cli-startup.js +17 -11
  12. package/bin/lib/cli-startup.test.js +92 -2
  13. package/bin/lib/commands-connect-url.js +8 -1
  14. package/bin/lib/commands-schedule.js +8 -2
  15. package/bin/lib/commands-serve.js +15 -21
  16. package/bin/lib/commands-update.js +12 -24
  17. package/bin/lib/commands-update.test.js +14 -46
  18. package/dist/assets/DiffView-Cv9MSXl1.js +4 -0
  19. package/dist/assets/FilePreviewCommentMenu-D4kLseHj.js +4 -0
  20. package/dist/assets/FilesView-BVoD8I2x.js +14 -0
  21. package/dist/assets/{GitView-DzuzhIPx.js → GitView-Bzb8p-ew.js} +4 -4
  22. package/dist/assets/GuestSurfacePane-Crdbvsxo.js +1 -0
  23. package/dist/assets/InProgressOperationBanner-CwMjNQgk.js +2 -0
  24. package/dist/assets/{JsonTreeView-B_EPRjzy.js → JsonTreeView-DRKHZfsn.js} +1 -1
  25. package/dist/assets/MarkdownImageGallery-DZtqT1Zn.js +1 -0
  26. package/dist/assets/MarkdownRendererImpl-CqG7HCNd.js +10 -0
  27. package/dist/assets/OnboardingScreen-DMIxwYK5.js +1 -0
  28. package/dist/assets/{PatchDiff-6yh1csza.js → PatchDiff-CUcCg1jk.js} +1 -1
  29. package/dist/assets/PierreDiffViewer-CnnR-dnD.js +228 -0
  30. package/dist/assets/PlanView-RCBadcY7.js +5 -0
  31. package/dist/assets/SettingsView-CjBjZFRO.js +30 -0
  32. package/dist/assets/SettingsWindow-DyM7QuhI.js +1 -0
  33. package/dist/assets/SubmoduleDiffSummary-BWIfgMED.js +1 -0
  34. package/dist/assets/ToolOutputDialog-Q0P3FuAi.js +15 -0
  35. package/dist/assets/ToolPartDiffPreview-p7qR9FpU.js +8 -0
  36. package/dist/assets/{VirtualizedFileDiff-BTJVRkyo.js → VirtualizedFileDiff-CFpjL8Ns.js} +3 -3
  37. package/dist/assets/{Virtualizer-xCEYz34p.js → Virtualizer-C0IsclZn.js} +1 -1
  38. package/dist/assets/WalkthroughView-DI31zD02.js +4 -0
  39. package/dist/assets/appThemeRegistry-B9gkFq9i.js +1 -0
  40. package/dist/assets/{computeVirtualFileMetrics-CmPe29DM.js → computeVirtualFileMetrics-C2WM6JC2.js} +2 -2
  41. package/dist/assets/de-YKfk5MmC.js +14 -0
  42. package/dist/assets/es-_gwT0kr-.js +20 -0
  43. package/dist/assets/fileTreeStatus-D438yi8M.js +1 -0
  44. package/dist/assets/fr-DqzvXmIm.js +18 -0
  45. package/dist/assets/index-BLaHKdtx.js +1 -0
  46. package/dist/assets/index-BkMXRrVQ.css +1 -0
  47. package/dist/assets/index-DxNa7xYB.js +65 -0
  48. package/dist/assets/initializeSharedPreferences-Bck5EAWP.js +1 -0
  49. package/dist/assets/{isDiffPlainText-CQmDCnEv.js → isDiffPlainText-Dgbw8VKk.js} +1 -1
  50. package/dist/assets/{isFilePlainText-CYBUzW4I.js → isFilePlainText-_ZS5UYRj.js} +1 -1
  51. package/dist/assets/ja-B-GFYhQE.js +20 -0
  52. package/dist/assets/ko-mzksfqDC.js +20 -0
  53. package/dist/assets/main-C5Xx8dn_.js +2 -0
  54. package/dist/assets/main-CfBSQM1H.js +990 -0
  55. package/dist/assets/markdownCore-BmWwW1ll.js +7 -0
  56. package/dist/assets/miniChat-mnKwy4vQ.js +2 -0
  57. package/dist/assets/mobile-DeEQd0wZ.js +2 -0
  58. package/dist/assets/nl-CWQr6NSq.js +20 -0
  59. package/dist/assets/{parseDiffFromFile-Cy0PNxun.js → parseDiffFromFile-BUgn-T9p.js} +2 -2
  60. package/dist/assets/patchFileDiff-Dt8LhgBh.js +13 -0
  61. package/dist/assets/pl-UmRcDUX2.js +20 -0
  62. package/dist/assets/pt-BR-BSLybvVF.js +20 -0
  63. package/dist/assets/relocateRestoredSession-B5E9xb3T.js +1 -0
  64. package/dist/assets/renderElectronMiniChatApp-C0a9A5_J.js +2 -0
  65. package/dist/assets/renderMobileApp-BNncg3Pk.js +25 -0
  66. package/dist/assets/runtimeEndpointReset-CZ5aafpl.js +62 -0
  67. package/dist/assets/{selectionMarkdown-TkYk5h9l.js → selectionMarkdown-CUN3wUld.js} +9 -9
  68. package/dist/assets/{sessionOwnership-Bs1xbRfB.js → sessionOwnership-BSuxCEhb.js} +1 -1
  69. package/dist/assets/shikiHighlight-DHDx-6eM.js +1 -0
  70. package/dist/assets/space-apply-DM_2pRW7.js +1 -0
  71. package/dist/assets/space-close-Bpomt8z0.js +1 -0
  72. package/dist/assets/{surface-B6n7wJtt.js → surface-C-jQaGnL.js} +1 -1
  73. package/dist/assets/{textMateThemeFromAppTheme-CDlKffWz.js → textMateThemeFromAppTheme-DlsTphbY.js} +1 -1
  74. package/dist/assets/tr-gaTrX_HK.js +11 -0
  75. package/dist/assets/uk-CnJF6ykl.js +20 -0
  76. package/dist/assets/{useAppFontEffects-DCqCVGlT.js → useAppFontEffects-DGlvOqP_.js} +194 -233
  77. package/dist/assets/useInlineCommentController-kMN4Wg_D.js +2 -0
  78. package/dist/assets/{useRootScrollLock-BowwS8kq.js → useRootScrollLock-DMPpvpNP.js} +2 -2
  79. package/dist/assets/{vendor-base-ui-DX96QhTP.js → vendor-base-ui-Det7U81h.js} +1 -1
  80. package/dist/assets/{vendor-codemirror-autocomplete-DW1FQz9_.js → vendor-codemirror-autocomplete-BSHQHbKu.js} +1 -1
  81. package/dist/assets/{vendor-codemirror-commands-DpmhalwN.js → vendor-codemirror-commands-C4G_dPWe.js} +1 -1
  82. package/dist/assets/{vendor-codemirror-lang-angular-BqExbN1M.js → vendor-codemirror-lang-angular-B6LbBGHB.js} +1 -1
  83. package/dist/assets/{vendor-codemirror-lang-cpp-DZA36HfS.js → vendor-codemirror-lang-cpp-BWWXBx7W.js} +1 -1
  84. package/dist/assets/{vendor-codemirror-lang-css-B07blnnZ.js → vendor-codemirror-lang-css-Cayfb29q.js} +1 -1
  85. package/dist/assets/{vendor-codemirror-lang-go-BM8K9D1-.js → vendor-codemirror-lang-go-BoKlCNKw.js} +1 -1
  86. package/dist/assets/{vendor-codemirror-lang-html-DaH9adfE.js → vendor-codemirror-lang-html-BQWerHsJ.js} +1 -1
  87. package/dist/assets/{vendor-codemirror-lang-java-CsdC0viz.js → vendor-codemirror-lang-java-DWX7Fq_K.js} +1 -1
  88. package/dist/assets/{vendor-codemirror-lang-javascript-CpGYXGuo.js → vendor-codemirror-lang-javascript-DbpEcZM0.js} +2 -2
  89. package/dist/assets/{vendor-codemirror-lang-jinja-BBeGzXw5.js → vendor-codemirror-lang-jinja-D1JIJRA7.js} +1 -1
  90. package/dist/assets/{vendor-codemirror-lang-json-58T70Hqs.js → vendor-codemirror-lang-json-BzgckzmB.js} +1 -1
  91. package/dist/assets/{vendor-codemirror-lang-less-BI-xCA59.js → vendor-codemirror-lang-less-B9EpDXFi.js} +1 -1
  92. package/dist/assets/{vendor-codemirror-lang-liquid-zEcMa-zy.js → vendor-codemirror-lang-liquid-9U7kRbSf.js} +1 -1
  93. package/dist/assets/{vendor-codemirror-lang-markdown-BLKnlLP4.js → vendor-codemirror-lang-markdown-D2TEBIvZ.js} +1 -1
  94. package/dist/assets/{vendor-codemirror-lang-php-9f35M83-.js → vendor-codemirror-lang-php-BT6sDVzE.js} +1 -1
  95. package/dist/assets/vendor-codemirror-lang-python-jAMtYiA9.js +3 -0
  96. package/dist/assets/{vendor-codemirror-lang-rust-MNDL_jZQ.js → vendor-codemirror-lang-rust-CVO56EiL.js} +1 -1
  97. package/dist/assets/{vendor-codemirror-lang-sass-p9epsSNm.js → vendor-codemirror-lang-sass-DZlOoUWu.js} +1 -1
  98. package/dist/assets/{vendor-codemirror-lang-sql-Bqzh0EXX.js → vendor-codemirror-lang-sql-fZ6t1DPw.js} +1 -1
  99. package/dist/assets/{vendor-codemirror-lang-vue-BnNUWV-p.js → vendor-codemirror-lang-vue-DxbqrLiE.js} +1 -1
  100. package/dist/assets/{vendor-codemirror-lang-wast-C2a-oLmk.js → vendor-codemirror-lang-wast-DyU1Gt-I.js} +1 -1
  101. package/dist/assets/vendor-codemirror-lang-xml-C9a_K5_p.js +1 -0
  102. package/dist/assets/{vendor-codemirror-lang-yaml-C0sjswB0.js → vendor-codemirror-lang-yaml-Cptq8l0e.js} +1 -1
  103. package/dist/assets/{vendor-codemirror-language-ByBn5zIW.js → vendor-codemirror-language-DufXoQvE.js} +2 -2
  104. package/dist/assets/vendor-codemirror-language-data-CtwSWKtX.js +2 -0
  105. package/dist/assets/{vendor-codemirror-search-ib-sHD5W.js → vendor-codemirror-search-CvXM_pZg.js} +1 -1
  106. package/dist/assets/{vendor-codemirror-state-G3UuR-be.js → vendor-codemirror-state-Dek9sMtw.js} +1 -1
  107. package/dist/assets/{vendor-codemirror-view-Bniqp7p5.js → vendor-codemirror-view-1e0FQ6Wn.js} +1 -1
  108. package/dist/assets/vendor-framer-motion-DxDVhOLc.js +9 -0
  109. package/dist/assets/vendor-katex-CuQvj9-L.js +257 -0
  110. package/dist/assets/vendor-katex-DdZNUVNG.css +1 -0
  111. package/dist/assets/{vendor-motion-dom-DcCgeG69.js → vendor-motion-dom-HXPOMxb7.js} +1 -1
  112. package/dist/assets/{vendor-opencode-client-DHzhmLwV.js → vendor-opencode-client-BmFcUkbQ.js} +1 -1
  113. package/dist/assets/{vendor-replit-codemirror-vim-DkzqxN2H.js → vendor-replit-codemirror-vim-BlJRn-cW.js} +2 -2
  114. package/dist/assets/{vendor-tanstack-react-virtual-H_JmXOFV.js → vendor-tanstack-react-virtual-CvuLsk7D.js} +1 -1
  115. package/dist/assets/{vendor-tanstack-virtual-core-Dxc8hSTB.js → vendor-tanstack-virtual-core-DPaNcJcT.js} +1 -1
  116. package/dist/assets/zh-CN-t2vigSB1.js +20 -0
  117. package/dist/assets/zh-TW-jAgqBokB.js +20 -0
  118. package/dist/index.html +6 -6
  119. package/dist/mini-chat.html +6 -6
  120. package/dist/mobile.html +6 -6
  121. package/package.json +8 -5
  122. package/server/index.js +80 -36
  123. package/server/lib/agent-memory/actions.js +1 -6
  124. package/server/lib/agent-memory/routes.js +1 -2
  125. package/server/lib/agent-memory/runtime.js +1 -8
  126. package/server/lib/agent-tool/DOCUMENTATION.md +7 -3
  127. package/server/lib/agent-tool/runtime.js +3 -6
  128. package/server/lib/agent-tool/runtime.test.js +0 -2
  129. package/server/lib/browser-control/DOCUMENTATION.md +6 -0
  130. package/server/lib/changelog/update-notes.js +1 -1
  131. package/server/lib/context-obligatory/runtime.js +1 -2
  132. package/server/lib/dev-tunnel/DOCUMENTATION.md +8 -0
  133. package/server/lib/dev-tunnel/client.js +21 -10
  134. package/server/lib/dev-tunnel/tunnel.test.js +34 -0
  135. package/server/lib/dispatch-results/runtime.js +1 -1
  136. package/server/lib/enterprise-mode.d.ts +1 -0
  137. package/server/lib/enterprise-mode.js +13 -2
  138. package/server/lib/enterprise-mode.test.js +21 -0
  139. package/server/lib/event-stream/DOCUMENTATION.md +2 -2
  140. package/server/lib/event-stream/index.js +1 -3
  141. package/server/lib/event-stream/translate-v2.js +1 -9
  142. package/server/lib/event-stream/translate-v2.test.js +0 -11
  143. package/server/lib/fs/DOCUMENTATION.md +5 -2
  144. package/server/lib/fs/routes.js +62 -15
  145. package/server/lib/fs/routes.test.js +278 -48
  146. package/server/lib/fs/workspace-file-names.js +104 -0
  147. package/server/lib/fs/workspace-file-names.test.js +62 -0
  148. package/server/lib/git/DOCUMENTATION.md +17 -5
  149. package/server/lib/git/contributor-provenance-storage.js +9 -6
  150. package/server/lib/git/contributor-provenance-storage.test.js +29 -0
  151. package/server/lib/git/credential-broker.js +1 -1
  152. package/server/lib/git/credential-resolver.js +1 -4
  153. package/server/lib/git/credentials.js +1 -0
  154. package/server/lib/git/discovery-endpoint.js +1 -1
  155. package/server/lib/git/identity-provisioning.js +2 -1
  156. package/server/lib/git/identity-storage.js +3 -4
  157. package/server/lib/git/lfs-discovery.js +14 -14
  158. package/server/lib/git/lfs-discovery.test.js +16 -6
  159. package/server/lib/git/network-operation-plan.js +50 -62
  160. package/server/lib/git/network-operation-plan.test.js +103 -1
  161. package/server/lib/git/network-operation-registry.js +4 -6
  162. package/server/lib/git/network-operation-storage.js +4 -6
  163. package/server/lib/git/network-operations.js +12 -4
  164. package/server/lib/git/network-operations.test.js +19 -6
  165. package/server/lib/git/redaction.js +2 -1
  166. package/server/lib/git/repository-credential-runtime.js +5 -3
  167. package/server/lib/git/repository-credential-runtime.test.js +22 -0
  168. package/server/lib/git/routes.js +31 -137
  169. package/server/lib/git/routes.test.js +2 -2
  170. package/server/lib/git/service.js +143 -27
  171. package/server/lib/git/service.test.js +215 -1
  172. package/server/lib/git/ssh-credential-storage.js +1 -4
  173. package/server/lib/git/submodule-discovery.js +1 -1
  174. package/server/lib/git/worktree-bootstrap-storage.js +3 -4
  175. package/server/lib/git/worktree-bootstrap-storage.test.js +15 -0
  176. package/server/lib/git/worktree-creation.js +194 -0
  177. package/server/lib/git/worktree-creation.test.js +155 -0
  178. package/server/lib/github/DOCUMENTATION.md +11 -6
  179. package/server/lib/github/auth.js +2 -4
  180. package/server/lib/github/device-flow.js +2 -2
  181. package/server/lib/github/gh-cli-credential.js +1 -0
  182. package/server/lib/github/octokit.js +31 -0
  183. package/server/lib/github/pr-status.js +35 -18
  184. package/server/lib/github/pr-status.test.js +271 -3
  185. package/server/lib/github/reference-search.js +102 -13
  186. package/server/lib/github/reference-search.test.js +48 -7
  187. package/server/lib/github/routes.auth.test.js +18 -0
  188. package/server/lib/github/routes.js +360 -6
  189. package/server/lib/github/routes.mutations.test.js +239 -0
  190. package/server/lib/github/routes.test.js +134 -2
  191. package/server/lib/gitlab/DOCUMENTATION.md +5 -1
  192. package/server/lib/gitlab/auth-storage.test.js +1 -0
  193. package/server/lib/gitlab/mappers.js +30 -1
  194. package/server/lib/gitlab/resources.js +230 -6
  195. package/server/lib/gitlab/resources.test.js +179 -0
  196. package/server/lib/gitlab/routes.js +200 -6
  197. package/server/lib/gitlab/routes.test.js +186 -2
  198. package/server/lib/gitlab/validation.js +1 -5
  199. package/server/lib/guests/DOCUMENTATION.md +1 -1
  200. package/server/lib/guests/oauth.js +2 -2
  201. package/server/lib/guests/service.js +1 -1
  202. package/server/lib/guests/sockets.js +1 -1
  203. package/server/lib/injected-env.d.ts +8 -0
  204. package/server/lib/injected-env.js +50 -0
  205. package/server/lib/injected-env.test.js +56 -0
  206. package/server/lib/linear/DOCUMENTATION.md +5 -6
  207. package/server/lib/linear/issues.js +62 -4
  208. package/server/lib/linear/issues.test.js +68 -0
  209. package/server/lib/linear/oauth.js +5 -5
  210. package/server/lib/linear/parse.js +2 -9
  211. package/server/lib/message-queue/DOCUMENTATION.md +23 -1
  212. package/server/lib/message-queue/runtime.js +85 -12
  213. package/server/lib/message-queue/runtime.test.js +172 -2
  214. package/server/lib/notifications/apns-runtime.js +5 -6
  215. package/server/lib/notifications/apns-runtime.test.js +20 -4
  216. package/server/lib/openchamber-control/DOCUMENTATION.md +19 -1
  217. package/server/lib/openchamber-control/actions.js +2 -1
  218. package/server/lib/openchamber-control/service.js +119 -20
  219. package/server/lib/openchamber-control/service.test.js +166 -0
  220. package/server/lib/openchamber-sessions/archive-store.js +1 -6
  221. package/server/lib/openchamber-sessions/routes.js +47 -12
  222. package/server/lib/openchamber-sessions/routes.test.js +65 -2
  223. package/server/lib/openchamber-sessions/session-metadata-store.js +1 -6
  224. package/server/lib/opencode/DOCUMENTATION.md +22 -8
  225. package/server/lib/opencode/agents.js +62 -0
  226. package/server/lib/opencode/auth-state-runtime.js +3 -1
  227. package/server/lib/opencode/auth.d.ts +1 -1
  228. package/server/lib/opencode/auth.js +8 -0
  229. package/server/lib/opencode/auth.test.js +31 -0
  230. package/server/lib/opencode/config-entity-routes.js +16 -0
  231. package/server/lib/opencode/config-entity-v2.test.js +16 -1
  232. package/server/lib/opencode/config-paths.test.js +2 -2
  233. package/server/lib/opencode/config-v2.js +2 -4
  234. package/server/lib/opencode/feature-routes-runtime.js +89 -49
  235. package/server/lib/opencode/lifecycle.js +41 -21
  236. package/server/lib/opencode/lifecycle.test.js +50 -2
  237. package/server/lib/opencode/model-discovery.js +1 -1
  238. package/server/lib/opencode/model-discovery.test.js +17 -0
  239. package/server/lib/opencode/models-metadata.js +0 -2
  240. package/server/lib/opencode/openchamber-routes.test.js +3 -3
  241. package/server/lib/opencode/plugins.js +6 -9
  242. package/server/lib/opencode/provider-source-route.test.js +101 -3
  243. package/server/lib/opencode/providers-disabled.test.js +59 -0
  244. package/server/lib/opencode/providers.js +34 -0
  245. package/server/lib/opencode/proxy.js +11 -3
  246. package/server/lib/opencode/routes.js +40 -2
  247. package/server/lib/opencode/settings-helpers.js +27 -1
  248. package/server/lib/opencode/settings-helpers.test.js +19 -7
  249. package/server/lib/opencode/settings-registry.json +27 -16
  250. package/server/lib/opencode/settings-runtime.test.js +18 -0
  251. package/server/lib/opencode/shared-service-runtime.js +23 -104
  252. package/server/lib/opencode/shared.js +77 -46
  253. package/server/lib/opencode/shared.test.js +12 -12
  254. package/server/lib/opencode/shutdown-runtime.test.js +2 -3
  255. package/server/lib/opencode/skill-routes.js +123 -38
  256. package/server/lib/opencode/skill-routes.test.js +201 -0
  257. package/server/lib/opencode/skills.js +81 -34
  258. package/server/lib/opencode/skills.test.js +176 -21
  259. package/server/lib/opencode/startup-pipeline-runtime.js +6 -3
  260. package/server/lib/opencode/startup-pipeline-runtime.test.js +2 -1
  261. package/server/lib/opencode/watcher.test.js +0 -54
  262. package/server/lib/outbound-proxy.js +52 -0
  263. package/server/lib/outbound-proxy.test.js +55 -0
  264. package/server/lib/package-manager.js +23 -17
  265. package/server/lib/package-manager.test.js +5 -18
  266. package/server/lib/permission-auto-accept/DOCUMENTATION.md +1 -1
  267. package/server/lib/permission-auto-accept/runtime.js +19 -47
  268. package/server/lib/permission-auto-accept/runtime.test.js +2 -2
  269. package/server/lib/project-context/DOCUMENTATION.md +7 -1
  270. package/server/lib/project-context/routes.js +1 -2
  271. package/server/lib/project-context/runtime.js +12 -14
  272. package/server/lib/project-context/runtime.test.js +78 -2
  273. package/server/lib/projects/project-config.js +30 -15
  274. package/server/lib/projects/project-config.test.js +30 -0
  275. package/server/lib/projects/project-setup.js +1 -2
  276. package/server/lib/projects/routes.js +1 -2
  277. package/server/lib/quota/DOCUMENTATION.md +35 -7
  278. package/server/lib/quota/index.js +1 -0
  279. package/server/lib/quota/providers/claude/index.js +1 -1
  280. package/server/lib/quota/providers/cline-pass.js +1 -1
  281. package/server/lib/quota/providers/exe-dev.js +1 -1
  282. package/server/lib/quota/providers/google/index.js +1 -1
  283. package/server/lib/quota/providers/hyper.js +1 -1
  284. package/server/lib/quota/providers/kimi.js +116 -36
  285. package/server/lib/quota/providers/kimi.test.js +128 -3
  286. package/server/lib/quota/providers/opencode-go.js +144 -21
  287. package/server/lib/quota/providers/opencode-go.test.js +229 -6
  288. package/server/lib/quota/providers/openrouter.js +1 -1
  289. package/server/lib/quota/providers/zenmux.js +1 -1
  290. package/server/lib/quota/utils/auth.js +1 -0
  291. package/server/lib/quota/utils/transformers.js +2 -6
  292. package/server/lib/relay/DOCUMENTATION.md +18 -3
  293. package/server/lib/relay/e2ee.js +7 -7
  294. package/server/lib/relay/host-client.js +84 -13
  295. package/server/lib/relay/host-client.test.js +201 -1
  296. package/server/lib/relay/identity.js +6 -29
  297. package/server/lib/relay/identity.test.js +18 -28
  298. package/server/lib/relay/key-store.js +141 -0
  299. package/server/lib/relay/key-store.test.js +138 -0
  300. package/server/lib/relay/service.js +8 -8
  301. package/server/lib/relay/service.test.js +10 -5
  302. package/server/lib/relay/signing-key.js +13 -36
  303. package/server/lib/relay/tunnel-codec.js +10 -10
  304. package/server/lib/route-module-exports.test.js +22 -0
  305. package/server/lib/routing/DOCUMENTATION.md +23 -3
  306. package/server/lib/routing/cache.js +87 -0
  307. package/server/lib/routing/defaults.js +11 -0
  308. package/server/lib/routing/history.js +12 -4
  309. package/server/lib/routing/runtime.js +39 -3
  310. package/server/lib/routing/runtime.test.js +81 -2
  311. package/server/lib/routing/store.js +12 -1
  312. package/server/lib/routing/store.test.js +13 -0
  313. package/server/lib/scheduled-tasks/DOCUMENTATION.md +59 -1
  314. package/server/lib/scheduled-tasks/existing-session.js +119 -0
  315. package/server/lib/scheduled-tasks/existing-session.test.js +350 -0
  316. package/server/lib/scheduled-tasks/loops.js +1 -8
  317. package/server/lib/scheduled-tasks/routes.js +8 -8
  318. package/server/lib/scheduled-tasks/runtime.js +103 -13
  319. package/server/lib/scheduled-tasks/runtime.test.js +48 -0
  320. package/server/lib/scheduled-tasks/service.js +33 -11
  321. package/server/lib/scheduled-tasks/service.test.js +128 -2
  322. package/server/lib/scheduled-tasks/session-defaults.js +27 -0
  323. package/server/lib/scheduled-tasks/session-defaults.test.js +19 -0
  324. package/server/lib/session-assist/context.js +1 -0
  325. package/server/lib/session-folders/routes.js +2 -2
  326. package/server/lib/session-goal/objectives.js +1 -1
  327. package/server/lib/session-knowledge/routes.js +2 -2
  328. package/server/lib/session-knowledge/runtime.js +1 -2
  329. package/server/lib/session-work/DOCUMENTATION.md +39 -14
  330. package/server/lib/session-work/questions.js +31 -2
  331. package/server/lib/session-work/runtime.js +22 -13
  332. package/server/lib/session-work/runtime.test.js +43 -26
  333. package/server/lib/session-work/state.js +10 -4
  334. package/server/lib/session-work/state.test.js +8 -1
  335. package/server/lib/shared/DOCUMENTATION.md +89 -0
  336. package/server/lib/shared/guards.js +53 -0
  337. package/server/lib/shared/guards.test.js +112 -0
  338. package/server/lib/skills-catalog/DOCUMENTATION.md +10 -8
  339. package/server/lib/skills-catalog/cache.js +3 -2
  340. package/server/lib/skills-catalog/curated-sources.js +5 -1
  341. package/server/lib/skills-catalog/git.js +107 -20
  342. package/server/lib/skills-catalog/git.test.js +78 -0
  343. package/server/lib/skills-catalog/install.js +21 -12
  344. package/server/lib/skills-catalog/scan.js +25 -15
  345. package/server/lib/skills-catalog/source.js +26 -1
  346. package/server/lib/skills-catalog/source.test.js +27 -0
  347. package/server/lib/source-control/DOCUMENTATION.md +2 -1
  348. package/server/lib/source-control/audit-storage.js +7 -6
  349. package/server/lib/source-control/audit-storage.test.js +11 -0
  350. package/server/lib/source-control/binding-service.js +2 -5
  351. package/server/lib/source-control/change-request-worktree.js +90 -0
  352. package/server/lib/source-control/change-request-worktree.test.js +121 -0
  353. package/server/lib/source-control/mutation-executor.js +1 -1
  354. package/server/lib/source-control/mutation-storage.js +11 -5
  355. package/server/lib/source-control/provider-instance.js +1 -2
  356. package/server/lib/source-control/repository-identity.js +1 -1
  357. package/server/lib/source-control/routes.js +14 -2
  358. package/server/lib/spaces/DOCUMENTATION.md +42 -17
  359. package/server/lib/spaces/command-stream.test.js +15 -0
  360. package/server/lib/spaces/dispatcher.js +7 -0
  361. package/server/lib/spaces/dispatcher.test.js +17 -0
  362. package/server/lib/spaces/hardening.js +2 -2
  363. package/server/lib/spaces/hardening.test.js +1 -1
  364. package/server/lib/spaces/host.js +2 -0
  365. package/server/lib/spaces/journey.js +66 -5
  366. package/server/lib/spaces/journey.test.js +95 -4
  367. package/server/lib/spaces/layout.js +1 -1
  368. package/server/lib/spaces/places/docker-disk.js +38 -14
  369. package/server/lib/spaces/places/docker-disk.test.js +80 -1
  370. package/server/lib/spaces/places/docker.js +35 -11
  371. package/server/lib/spaces/places/fake-docker.js +22 -3
  372. package/server/lib/spaces/places/memory-place.js +3 -0
  373. package/server/lib/spaces/places/packed.docker.live.test.js +1 -1
  374. package/server/lib/spaces/routes.js +5 -0
  375. package/server/lib/spaces/routes.test.js +4 -2
  376. package/server/lib/spaces/run-command.js +9 -2
  377. package/server/lib/spaces/tools.js +4 -5
  378. package/server/lib/spaces/tools.test.js +2 -2
  379. package/server/lib/terminal/runtime.js +18 -6
  380. package/server/lib/terminal/runtime.test.js +66 -0
  381. package/server/lib/tts/index.js +3 -0
  382. package/server/lib/tts/service.js +4 -2
  383. package/server/lib/walkthrough/DOCUMENTATION.md +3 -1
  384. package/server/lib/walkthrough/index.js +2 -3
  385. package/server/lib/walkthrough/pr-source.test.js +22 -0
  386. package/server/lib/walkthrough/sources.js +6 -1
  387. package/server/opencode-proxy.test.js +127 -0
  388. package/bin/lib/commands-startup.test.js +0 -15
  389. package/dist/assets/CodeMirrorCommentWidgets-CVDSjcrP.js +0 -1
  390. package/dist/assets/DiffView-Ct7vL3fD.js +0 -4
  391. package/dist/assets/FilesView-DT0uEYgT.js +0 -17
  392. package/dist/assets/GuestSurfacePane-DVvk1VPu.js +0 -1
  393. package/dist/assets/LinearIssuesView-C10MwA9h.js +0 -1
  394. package/dist/assets/MarkdownImageGallery-BbN_K_3d.js +0 -1
  395. package/dist/assets/MarkdownRendererImpl-BLt2Tkk9.js +0 -10
  396. package/dist/assets/OnboardingScreen-Bgp5A3WB.js +0 -1
  397. package/dist/assets/PierreDiffViewer-CWJLj-S-.js +0 -210
  398. package/dist/assets/PlanView-DsRWnsOI.js +0 -5
  399. package/dist/assets/PublishDialog-CCeKloRu.js +0 -2
  400. package/dist/assets/SettingsView-BuPPsNPp.js +0 -30
  401. package/dist/assets/SettingsWindow-CM5fL8Ot.js +0 -1
  402. package/dist/assets/SubmoduleDiffSummary-CfsMcfiQ.js +0 -1
  403. package/dist/assets/ToolOutputDialog-mZrfSofz.js +0 -15
  404. package/dist/assets/ToolPartDiffPreview-BUGCRYEL.js +0 -8
  405. package/dist/assets/WalkthroughView-ClBo7PPd.js +0 -4
  406. package/dist/assets/appThemeRegistry-CxzMxR-H.js +0 -1
  407. package/dist/assets/de-CBla4hjd.js +0 -14
  408. package/dist/assets/es-BmnZtxTD.js +0 -20
  409. package/dist/assets/fileTreeStatus-BSHFIGEg.js +0 -1
  410. package/dist/assets/fr-OVKIBUZO.js +0 -18
  411. package/dist/assets/index-CKCFKmjF.js +0 -1
  412. package/dist/assets/index-Dbx4V4GN.css +0 -1
  413. package/dist/assets/index-vQ1Pg1cr.js +0 -61
  414. package/dist/assets/ja-6v-yr-gE.js +0 -20
  415. package/dist/assets/ko-I_ZLvgQ9.js +0 -20
  416. package/dist/assets/main-CmO4dRtR.js +0 -2
  417. package/dist/assets/main-b9vqhlYM.js +0 -999
  418. package/dist/assets/markdownCore-BPEZRQfP.js +0 -7
  419. package/dist/assets/miniChat-B5Oi7B-6.js +0 -2
  420. package/dist/assets/mobile-CVtShif9.js +0 -2
  421. package/dist/assets/nl-DcvIJf46.js +0 -20
  422. package/dist/assets/patchFileDiff-CW3wCH1O.js +0 -13
  423. package/dist/assets/pl-JxCUl0sd.js +0 -20
  424. package/dist/assets/pt-BR-L89mjja2.js +0 -20
  425. package/dist/assets/relocateRestoredSession-DYh_9oBa.js +0 -1
  426. package/dist/assets/renderElectronMiniChatApp-BD-1JHSg.js +0 -2
  427. package/dist/assets/renderMobileApp-7s5InXt1.js +0 -25
  428. package/dist/assets/runtimeEndpointReset-DqLJC6L1.js +0 -53
  429. package/dist/assets/shikiHighlight-CXgZnvHh.js +0 -1
  430. package/dist/assets/space-apply-1trGVIl8.js +0 -1
  431. package/dist/assets/space-close-y7j-NuBv.js +0 -1
  432. package/dist/assets/tr-ka5J1flt.js +0 -11
  433. package/dist/assets/uk-PyGe6Q_u.js +0 -20
  434. package/dist/assets/useInlineCommentController-CrjSGCpi.js +0 -2
  435. package/dist/assets/vendor-codemirror-lang-python-B7ClrMIT.js +0 -3
  436. package/dist/assets/vendor-codemirror-lang-xml-C8tGnS64.js +0 -1
  437. package/dist/assets/vendor-codemirror-language-data-q2bKO1EM.js +0 -2
  438. package/dist/assets/vendor-framer-motion-Bq3iTZ6r.js +0 -1
  439. package/dist/assets/vendor-katex-CHD9BdDO.js +0 -257
  440. package/dist/assets/vendor-katex-Cp579UoJ.css +0 -1
  441. package/dist/assets/zh-CN-B0P2tybJ.js +0 -20
  442. package/dist/assets/zh-TW-Bs9C5cN8.js +0 -20
package/dist/index.html CHANGED
@@ -492,17 +492,17 @@
492
492
  pointer-events: none;
493
493
  }
494
494
  </style>
495
- <script type="module" crossorigin src="/assets/main-CmO4dRtR.js"></script>
495
+ <script type="module" crossorigin src="/assets/main-C5Xx8dn_.js"></script>
496
496
  <link rel="modulepreload" crossorigin href="/assets/vendor-vite-runtime-DD1OZmLC.js">
497
497
  <link rel="modulepreload" crossorigin href="/assets/vendor-zod-CxRSdNoV.js">
498
498
  <link rel="modulepreload" crossorigin href="/assets/vendor-scheduler-7OC5HNn7.js">
499
499
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-BUCujlKS.js">
500
500
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-BAGL70zf.js">
501
- <link rel="modulepreload" crossorigin href="/assets/vendor-opencode-client-DHzhmLwV.js">
502
- <link rel="modulepreload" crossorigin href="/assets/index-vQ1Pg1cr.js">
503
- <link rel="modulepreload" crossorigin href="/assets/vendor-katex-CHD9BdDO.js">
504
- <link rel="stylesheet" crossorigin href="/assets/index-Dbx4V4GN.css">
505
- <link rel="stylesheet" crossorigin href="/assets/vendor-katex-Cp579UoJ.css">
501
+ <link rel="modulepreload" crossorigin href="/assets/vendor-opencode-client-BmFcUkbQ.js">
502
+ <link rel="modulepreload" crossorigin href="/assets/index-DxNa7xYB.js">
503
+ <link rel="modulepreload" crossorigin href="/assets/vendor-katex-CuQvj9-L.js">
504
+ <link rel="stylesheet" crossorigin href="/assets/index-BkMXRrVQ.css">
505
+ <link rel="stylesheet" crossorigin href="/assets/vendor-katex-DdZNUVNG.css">
506
506
  </head>
507
507
  <body class="h-full bg-background text-foreground">
508
508
  <div id="root" class="h-full">
@@ -74,17 +74,17 @@
74
74
  }
75
75
  </style>
76
76
 
77
- <script type="module" crossorigin src="/assets/miniChat-B5Oi7B-6.js"></script>
77
+ <script type="module" crossorigin src="/assets/miniChat-mnKwy4vQ.js"></script>
78
78
  <link rel="modulepreload" crossorigin href="/assets/vendor-vite-runtime-DD1OZmLC.js">
79
79
  <link rel="modulepreload" crossorigin href="/assets/vendor-zod-CxRSdNoV.js">
80
80
  <link rel="modulepreload" crossorigin href="/assets/vendor-scheduler-7OC5HNn7.js">
81
81
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-BUCujlKS.js">
82
82
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-BAGL70zf.js">
83
- <link rel="modulepreload" crossorigin href="/assets/vendor-opencode-client-DHzhmLwV.js">
84
- <link rel="modulepreload" crossorigin href="/assets/index-vQ1Pg1cr.js">
85
- <link rel="modulepreload" crossorigin href="/assets/vendor-katex-CHD9BdDO.js">
86
- <link rel="stylesheet" crossorigin href="/assets/index-Dbx4V4GN.css">
87
- <link rel="stylesheet" crossorigin href="/assets/vendor-katex-Cp579UoJ.css">
83
+ <link rel="modulepreload" crossorigin href="/assets/vendor-opencode-client-BmFcUkbQ.js">
84
+ <link rel="modulepreload" crossorigin href="/assets/index-DxNa7xYB.js">
85
+ <link rel="modulepreload" crossorigin href="/assets/vendor-katex-CuQvj9-L.js">
86
+ <link rel="stylesheet" crossorigin href="/assets/index-BkMXRrVQ.css">
87
+ <link rel="stylesheet" crossorigin href="/assets/vendor-katex-DdZNUVNG.css">
88
88
  </head>
89
89
  <body class="h-full bg-background text-foreground">
90
90
  <div id="root" class="h-full">
package/dist/mobile.html CHANGED
@@ -63,17 +63,17 @@
63
63
  })();
64
64
  </script>
65
65
 
66
- <script type="module" crossorigin src="/assets/mobile-CVtShif9.js"></script>
66
+ <script type="module" crossorigin src="/assets/mobile-DeEQd0wZ.js"></script>
67
67
  <link rel="modulepreload" crossorigin href="/assets/vendor-vite-runtime-DD1OZmLC.js">
68
68
  <link rel="modulepreload" crossorigin href="/assets/vendor-zod-CxRSdNoV.js">
69
69
  <link rel="modulepreload" crossorigin href="/assets/vendor-scheduler-7OC5HNn7.js">
70
70
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-BUCujlKS.js">
71
71
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-BAGL70zf.js">
72
- <link rel="modulepreload" crossorigin href="/assets/vendor-opencode-client-DHzhmLwV.js">
73
- <link rel="modulepreload" crossorigin href="/assets/index-vQ1Pg1cr.js">
74
- <link rel="modulepreload" crossorigin href="/assets/vendor-katex-CHD9BdDO.js">
75
- <link rel="stylesheet" crossorigin href="/assets/index-Dbx4V4GN.css">
76
- <link rel="stylesheet" crossorigin href="/assets/vendor-katex-Cp579UoJ.css">
72
+ <link rel="modulepreload" crossorigin href="/assets/vendor-opencode-client-BmFcUkbQ.js">
73
+ <link rel="modulepreload" crossorigin href="/assets/index-DxNa7xYB.js">
74
+ <link rel="modulepreload" crossorigin href="/assets/vendor-katex-CuQvj9-L.js">
75
+ <link rel="stylesheet" crossorigin href="/assets/index-BkMXRrVQ.css">
76
+ <link rel="stylesheet" crossorigin href="/assets/vendor-katex-DdZNUVNG.css">
77
77
  </head>
78
78
  <body class="h-full bg-background text-foreground">
79
79
  <div id="root" class="h-full"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vantran-se/openchamber-web",
3
- "version": "2.1.1",
3
+ "version": "2.2.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./server/index.js",
@@ -11,6 +11,9 @@
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
14
+ "engines": {
15
+ "node": ">=24.14.0"
16
+ },
14
17
  "scripts": {
15
18
  "dev": "bun run build:watch",
16
19
  "dev:server": "bun ../../scripts/build-builtin-extensions.mjs && OPENCHAMBER_RELAY_HOST=${OPENCHAMBER_RELAY_HOST:-off} OPENCHAMBER_ALLOW_DEV_ORIGINS=1 bun server/index.js --port ${OPENCHAMBER_PORT:-3001}",
@@ -18,7 +21,7 @@
18
21
  "build": "bun ../../scripts/build-builtin-extensions.mjs && NODE_OPTIONS=--max-old-space-size=6144 vite build",
19
22
  "build:watch": "bun ../../scripts/build-builtin-extensions.mjs && vite build --watch",
20
23
  "prepack": "bun ../../scripts/build-builtin-extensions.mjs",
21
- "type-check": "tsc --noEmit",
24
+ "type-check": "tsc -b",
22
25
  "lint": "eslint \"./src/**/*.{ts,tsx}\" --config ../../eslint.config.js",
23
26
  "test": "vitest run",
24
27
  "start": "node bin/cli.js serve"
@@ -27,9 +30,9 @@
27
30
  "@clack/prompts": "^1.1.0",
28
31
  "@gitbeaker/rest": "43.8.0",
29
32
  "@octokit/rest": "^22.0.1",
30
- "@openchamber/sdk": "2.1.1",
31
- "@opencode/client": "2.0.23",
32
- "@opencode/schema": "2.0.23",
33
+ "@openchamber/sdk": "2.2.0",
34
+ "@opencode/client": "2.0.25",
35
+ "@opencode/schema": "2.0.25",
33
36
  "@simplewebauthn/server": "13.3.3",
34
37
  "bun-pty": "^0.4.5",
35
38
  "compression": "^1.8.1",
package/server/index.js CHANGED
@@ -98,6 +98,7 @@ import { createLinearSessionStatusRuntime } from './lib/linear/status-runtime.js
98
98
  import { createSessionKnowledgeRuntime } from './lib/session-knowledge/runtime.js';
99
99
  import { createMessageSearchRuntime } from './lib/message-search/runtime.js';
100
100
  import { createScheduledTasksRuntime } from './lib/scheduled-tasks/runtime.js';
101
+ import { resolveSessionDefaults } from './lib/scheduled-tasks/session-defaults.js';
101
102
  import { createChatsScope } from './lib/scheduled-tasks/chats-scope.js';
102
103
  import { createServerStartupRuntime } from './lib/opencode/server-startup-runtime.js';
103
104
  import { createTunnelWiringRuntime } from './lib/opencode/tunnel-wiring-runtime.js';
@@ -145,6 +146,7 @@ import { createClientPairingRuntime } from './lib/client-auth/pairing.js';
145
146
  import { attachRealtimeProxy } from './lib/realtime-proxy.js';
146
147
  import { createRelayService, relayBlockedByEnterprise } from './lib/relay/service.js';
147
148
  import { createRelayHostLock } from './lib/relay/host-lock.js';
149
+ import { createRelayKeyStore } from './lib/relay/key-store.js';
148
150
  import { createAgentToolRuntime } from './lib/agent-tool/runtime.js';
149
151
  import { createBrowserControlBroker } from './lib/browser-control/broker.js';
150
152
  import { createBrowserControlRouter } from './lib/browser-control/provider.js';
@@ -162,9 +164,11 @@ import { OpenChamberControlError } from './lib/openchamber-control/error.js';
162
164
  import { createSessionLinker } from './lib/openchamber-sessions/session-link.js';
163
165
  import { createFileOpenRequester } from './lib/openchamber-control/file-open.js';
164
166
  import { applyConnectAttemptTimeout } from './lib/network-defaults.js';
167
+ import { applyOutboundProxyFromEnv } from './lib/outbound-proxy.js';
165
168
 
166
169
  // Background CLI launches enter here in a fresh process, without CLI defaults.
167
170
  applyConnectAttemptTimeout();
171
+ applyOutboundProxyFromEnv();
168
172
 
169
173
  const __filename = fileURLToPath(import.meta.url);
170
174
  const __dirname = path.dirname(__filename);
@@ -493,6 +497,16 @@ const isUiVisible = (...args) => pushRuntime.isUiVisible(...args);
493
497
  const ensurePushInitialized = (...args) => pushRuntime.ensurePushInitialized(...args);
494
498
  const setPushInitialized = (...args) => pushRuntime.setPushInitialized(...args);
495
499
 
500
+ // Host relay identity keys, shared by the push relay and the private relay.
501
+ const relayKeyStore = createRelayKeyStore({
502
+ fsPromises,
503
+ path,
504
+ dataDir: OPENCHAMBER_DATA_DIR,
505
+ readSettingsFromDiskMigrated,
506
+ readSettingsStrict: readSettingsFromDiskStrict,
507
+ writeSettingsToDisk,
508
+ });
509
+
496
510
  const apnsRuntime = createApnsRuntime({
497
511
  fsPromises,
498
512
  path,
@@ -500,8 +514,7 @@ const apnsRuntime = createApnsRuntime({
500
514
  http2,
501
515
  APNS_TOKENS_FILE_PATH,
502
516
  readSettingsFromDiskMigrated,
503
- writeSettingsToDisk,
504
- readSettingsStrict: readSettingsFromDiskStrict,
517
+ relayKeyStore,
505
518
  });
506
519
 
507
520
  const addOrUpdateApnsToken = (...args) => apnsRuntime.addOrUpdateApnsToken(...args);
@@ -628,6 +641,10 @@ const projectContextRuntime = createProjectContextRuntime({
628
641
  path,
629
642
  projectsDirPath: OPENCHAMBER_PROJECTS_CONFIG_DIR,
630
643
  resolveSharedPlansDir: (projectId) => projectConfigRuntime.resolveSharedPlansDir(projectId),
644
+ onChanged: (projectId) => broadcastOpenChamberUiEvent({
645
+ type: 'openchamber:project-context-changed',
646
+ properties: { projectId },
647
+ }),
631
648
  });
632
649
 
633
650
  const agentMemoryRuntime = createAgentMemoryRuntime({
@@ -797,6 +814,7 @@ const getManagedOpenCodeAuthHeaders = (...args) => openCodeAuthStateRuntime.getO
797
814
  const getConnectionOpenCodeAuthHeaders = (...args) => (
798
815
  openCodeConnectionAdapter?.getOpenCodeAuthHeaders(...args) ?? getManagedOpenCodeAuthHeaders(...args)
799
816
  );
817
+ const getOpenCodeAuthHeaders = (...args) => getConnectionOpenCodeAuthHeaders(...args);
800
818
  const getOpenCodeBaseUrl = () => openCodeConnectionAdapter?.getOpenCodeBaseUrl() ?? openCodeBaseUrl;
801
819
  const getOpenCodeConnectionKind = () => (
802
820
  openCodeConnectionAdapter?.getOpenCodeConnectionKind() ?? 'managed-owned'
@@ -829,7 +847,6 @@ const openCodeNetworkRuntime = createOpenCodeNetworkRuntime({
829
847
  configuredOpenCodeHostname: ENV_CONFIGURED_OPENCODE_HOSTNAME,
830
848
  });
831
849
 
832
- const getOpenCodeAuthHeaders = (...args) => openCodeNetworkRuntime.getOpenCodeAuthHeaders(...args);
833
850
  const waitForReady = (...args) => openCodeNetworkRuntime.waitForReady(...args);
834
851
  const normalizeApiPrefix = (...args) => openCodeNetworkRuntime.normalizeApiPrefix(...args);
835
852
  const setDetectedOpenCodeApiPrefix = (...args) => openCodeNetworkRuntime.setDetectedOpenCodeApiPrefix(...args);
@@ -1106,6 +1123,9 @@ const messageQueueRuntime = createMessageQueueRuntime({
1106
1123
  broadcastGlobalUiEvent: broadcastOpenChamberUiEvent,
1107
1124
  resolveAutoSelection: (send) => routingRuntime.resolveAutoSelection(send),
1108
1125
  onPromptSent: (sessionId) => sessionRuntime.markUserMessageSent(sessionId),
1126
+ beforeScheduledTaskSend: (...args) => scheduledTasksRuntime.beforeScheduledTaskSend(...args),
1127
+ validateScheduledTaskTarget: (...args) => scheduledTasksRuntime.validateTarget(...args),
1128
+ onScheduledTaskResult: (...args) => scheduledTasksRuntime.onScheduledTaskResult(...args),
1109
1129
  dataDir: OPENCHAMBER_DATA_DIR,
1110
1130
  });
1111
1131
  messageQueueRuntime.start();
@@ -1492,13 +1512,40 @@ const openCodeLifecycleRuntime = createOpenCodeLifecycleRuntime({
1492
1512
  )));
1493
1513
  return existing.filter(Boolean);
1494
1514
  },
1515
+ noProjectDirectory: OPENCHAMBER_CHATS_DIR,
1495
1516
  // A managed restart can move OpenCode to a NEW port (the old one may stay
1496
1517
  // occupied if killProcessOnPort/waitForPortRelease didn't free it in time,
1497
1518
  // on any platform). Rebind the message-stream upstream readers to the current port
1498
1519
  // so the UI keeps receiving events instead of staying pinned to the old
1499
1520
  // process (#2638). The runtime is created later by the startup pipeline;
1500
1521
  // by the time any restart runs, it is assigned.
1501
- onOpenCodeRestarted: () => openCodeRecoveryCallbacks.onManagedRestarted(),
1522
+ onOpenCodeRestarted: () => {
1523
+ // A restart reloads plugins: provider ports, credentials and the provider
1524
+ // list itself can all differ from what was cached.
1525
+ resetOpenCodeRuntimeProviders();
1526
+ try {
1527
+ messageStreamRuntime?.rebindUpstream();
1528
+ } catch (error) {
1529
+ console.warn('Failed to rebind message stream after OpenCode restart:', error?.message ?? error);
1530
+ }
1531
+ try {
1532
+ const { sessionIds } = sessionRuntime.interruptBusySessionsAfterRestart();
1533
+ if (sessionIds.length > 0) {
1534
+ const multiple = sessionIds.length > 1;
1535
+ broadcastUiNotification({
1536
+ title: multiple ? 'Chats interrupted' : 'Chat interrupted',
1537
+ body: multiple
1538
+ ? 'OpenCode restarted during running responses. Send a message in each chat to continue.'
1539
+ : 'OpenCode restarted during a running response. Send a message to continue.',
1540
+ tag: 'opencode-restart-interrupted',
1541
+ kind: 'opencode-restart-interrupted',
1542
+ sessionId: sessionIds[0],
1543
+ });
1544
+ }
1545
+ } catch (error) {
1546
+ console.warn('Failed to reconcile sessions after OpenCode restart:', error?.message ?? error);
1547
+ }
1548
+ },
1502
1549
  getManagedOpenCodeEnv: async () => (managedConfigRuntime ? managedConfigRuntime.buildManagedChildEnv() : {}),
1503
1550
  getUserEnvironment: () => environmentRuntime.forOpenCode(),
1504
1551
  });
@@ -1514,11 +1561,10 @@ configureOpenCodeCredentials(openCodeCredentialSource({
1514
1561
  }));
1515
1562
 
1516
1563
  const getOpenCodeCompatibility = async () => {
1517
- if (getOpenCodeConnectionKind() !== 'managed-owned' || ENV_SKIP_OPENCODE_START) {
1518
- const base = ENV_CONFIGURED_OPENCODE_HOST?.origin || getOpenCodeBaseUrl() || `http://127.0.0.1:${openCodePort || ENV_EFFECTIVE_PORT}`;
1564
+ if (isExternalOpenCode || ENV_SKIP_OPENCODE_START) {
1565
+ const base = ENV_CONFIGURED_OPENCODE_HOST?.origin || openCodeBaseUrl || `http://127.0.0.1:${openCodePort || ENV_EFFECTIVE_PORT}`;
1519
1566
  const version = await readExternalOpenCodeVersion(base, getOpenCodeAuthHeaders()).catch(() => null);
1520
- const installation = getOpenCodeConnectionKind() === 'shared-local' ? 'shared' : 'external';
1521
- return describeOpenCodeCompatibility(version, installation, false);
1567
+ return describeOpenCodeCompatibility(version, 'external', false);
1522
1568
  }
1523
1569
  const binary = ensureOpencodeCliEnv();
1524
1570
  const installation = isBundledOpenCodeCliPath(binary) ? 'bundled' : 'managed';
@@ -1566,6 +1612,14 @@ const scheduledChatsScope = createChatsScope(OPENCHAMBER_CHATS_DIR);
1566
1612
  const scheduledTasksRuntime = createScheduledTasksRuntime({
1567
1613
  projectConfigRuntime,
1568
1614
  chatsScope: scheduledChatsScope,
1615
+ messageQueueRuntime,
1616
+ resolvePrimaryWorktreeRoot,
1617
+ isSessionArchived: (sessionID) => openChamberSessionService.archiveStore.isArchived(sessionID),
1618
+ readSessionDefaults: async (projectID) => {
1619
+ const settings = await readSettingsFromDiskMigrated();
1620
+ const project = sanitizeProjects(settings?.projects || []).find((entry) => entry.id === projectID) ?? null;
1621
+ return resolveSessionDefaults({ settings, project });
1622
+ },
1569
1623
  listProjects: async () => {
1570
1624
  const settings = await readSettingsFromDiskMigrated();
1571
1625
  return sanitizeProjects(settings?.projects || []);
@@ -1667,6 +1721,7 @@ const openChamberSessionService = createOpenChamberSessionService({
1667
1721
  sessionKnowledgeRuntime,
1668
1722
  worktreeBootstrapStore,
1669
1723
  hydrateWorktreeCheckout: featureRoutesRuntime.hydrateBoundCheckout,
1724
+ createChangeRequestWorktree: featureRoutesRuntime.createChangeRequestWorktree,
1670
1725
  // OpenCode 2.x has no archive route, so the state is OpenChamber's own and
1671
1726
  // lives beside the instance it describes.
1672
1727
  dataDir: OPENCHAMBER_DATA_DIR,
@@ -1859,7 +1914,6 @@ const gracefulShutdownRuntime = createGracefulShutdownRuntime({
1859
1914
  dispatchResultsRuntime,
1860
1915
  messageSearchRuntime,
1861
1916
  sessionRuntime,
1862
- globalEventHub: globalMessageStreamHub,
1863
1917
  getHealthCheckInterval: () => healthCheckInterval,
1864
1918
  clearHealthCheckInterval: (value) => clearInterval(value),
1865
1919
  getTerminalRuntime: () => terminalRuntime,
@@ -1870,7 +1924,7 @@ const gracefulShutdownRuntime = createGracefulShutdownRuntime({
1870
1924
  setMessageStreamRuntime: (value) => {
1871
1925
  messageStreamRuntime = value;
1872
1926
  },
1873
- getOpenCodeConnectionKind,
1927
+ shouldSkipOpenCodeStop: () => !ownsOpenCodeProcess(),
1874
1928
  getOpenCodePort: () => openCodePort,
1875
1929
  getOpenCodeProcess: () => openCodeProcess,
1876
1930
  setOpenCodeProcess: (value) => {
@@ -1878,7 +1932,6 @@ const gracefulShutdownRuntime = createGracefulShutdownRuntime({
1878
1932
  },
1879
1933
  killProcessOnPort,
1880
1934
  waitForPortRelease,
1881
- disposeSharedOpenCodeService: () => sharedOpenCodeServiceRuntime?.dispose(),
1882
1935
  getServer: () => server,
1883
1936
  getUiAuthController: () => uiAuthController,
1884
1937
  setUiAuthController: (value) => {
@@ -1904,11 +1957,9 @@ const gracefulShutdown = (...args) => gracefulShutdownRuntime.gracefulShutdown(.
1904
1957
 
1905
1958
  async function main(options = {}) {
1906
1959
  beginGuestServiceHost();
1907
- const runtimeName = process.env.OPENCHAMBER_RUNTIME || 'web';
1908
- const lifecycleMode = options.openCodeLifecycleMode === 'managed'
1909
- || options.openCodeLifecycleMode === 'shared'
1910
- ? options.openCodeLifecycleMode
1911
- : undefined;
1960
+ // Again at start: the desktop shell merges the login shell's environment,
1961
+ // where proxy variables often live, after this module first loaded.
1962
+ applyOutboundProxyFromEnv();
1912
1963
  const port = Number.isFinite(options.port) && options.port >= 0 ? Math.trunc(options.port) : DEFAULT_PORT;
1913
1964
  const host = typeof options.host === 'string' && options.host.length > 0 ? options.host : undefined;
1914
1965
  const effectiveBindHost = host
@@ -1930,24 +1981,20 @@ async function main(options = {}) {
1930
1981
  // A pipe listener reports a string here, which has no address to bind back to.
1931
1982
  getActiveHost: () => server?.address?.()?.address ?? null,
1932
1983
  });
1984
+ const runtimeName = process.env.OPENCHAMBER_RUNTIME || 'web';
1933
1985
  const openCodeComposition = createOpenCodeServerComposition({
1934
1986
  runtime: runtimeName,
1935
1987
  configuredHost: ENV_CONFIGURED_OPENCODE_HOST,
1936
- lifecycleMode,
1937
- createSharedRuntime: () => {
1938
- const binary = ensureOpencodeCliEnv();
1939
- return createSharedOpenCodeServiceRuntime({
1940
- ensureOptions: binary ? { command: [binary, 'serve', '--service'] } : undefined,
1941
- });
1942
- },
1988
+ lifecycleMode: options.openCodeLifecycleMode,
1989
+ createSharedRuntime: () => createSharedOpenCodeServiceRuntime({
1990
+ ensureOptions: (() => {
1991
+ const binary = ensureOpencodeCliEnv();
1992
+ return binary ? { command: [binary, 'serve', '--service'] } : undefined;
1993
+ })(),
1994
+ }),
1943
1995
  createManagedPluginRuntime: () => createManagedConfigRuntime({
1944
- fsPromises,
1945
- path,
1946
- dataDir: OPENCHAMBER_DATA_DIR,
1947
- env: process.env,
1948
- agentToolRuntime,
1949
- readSettings: () => readSettingsFromDiskMigrated(),
1950
- isAgentMemoryAvailable: isAgentMemoryFeatureAvailable,
1996
+ fsPromises, path, dataDir: OPENCHAMBER_DATA_DIR, env: process.env, agentToolRuntime,
1997
+ readSettings: () => readSettingsFromDiskMigrated(), isAgentMemoryAvailable: isAgentMemoryFeatureAvailable,
1951
1998
  }),
1952
1999
  getManagedBaseUrl: () => openCodeBaseUrl,
1953
2000
  getManagedAuthHeaders: getManagedOpenCodeAuthHeaders,
@@ -1955,11 +2002,7 @@ async function main(options = {}) {
1955
2002
  sharedOpenCodeServiceRuntime = openCodeComposition.sharedRuntime;
1956
2003
  managedConfigRuntime = openCodeComposition.managedPluginRuntime;
1957
2004
  openCodeConnectionAdapter = openCodeComposition.connection;
1958
- await ensureChatsDir({
1959
- fsPromises,
1960
- chatsDir: OPENCHAMBER_CHATS_DIR,
1961
- warn: (message) => console.warn(`[data-dir] ${message}`),
1962
- });
2005
+ await ensureChatsDir({ fsPromises, chatsDir: OPENCHAMBER_CHATS_DIR, warn: (message) => console.warn(`[data-dir] ${message}`) });
1963
2006
 
1964
2007
  // Pairing transports advertised to the create-device dialog. LAN reachability is
1965
2008
  // derived from the SERVER's actual bind (a wildcard bind → the machine's LAN IP;
@@ -2401,7 +2444,7 @@ async function main(options = {}) {
2401
2444
  os,
2402
2445
  readSettingsFromDiskMigrated,
2403
2446
  writeSettingsToDisk,
2404
- readSettingsStrict: readSettingsFromDiskStrict,
2447
+ relayKeyStore,
2405
2448
  remoteClientAuthRuntime,
2406
2449
  getLocalPort: () => tunnelRuntimeContext.getActivePort(),
2407
2450
  // One relay host per machine: every instance sharing this data dir shares
@@ -2580,6 +2623,7 @@ async function main(options = {}) {
2580
2623
  terminalMaxRebindsPerWindow: TERMINAL_INPUT_WS_MAX_REBINDS_PER_WINDOW,
2581
2624
  environmentRuntime,
2582
2625
  setupProxy,
2626
+ scheduleOpenCodeApiDetection,
2583
2627
  bootstrapOpenCodeAtStartup,
2584
2628
  // Git's credential helper reaches the server through a file that names
2585
2629
  // the port, so it is written once the port is known and before OpenCode,
@@ -17,16 +17,11 @@
17
17
  * which is also what the user means by "this project".
18
18
  */
19
19
 
20
+ import { asNonEmptyString } from '../shared/guards.js';
20
21
  import { MEMORY_BODY_MAX_LENGTH } from './runtime.js';
21
22
 
22
23
  const MEMORY_TYPES = new Set(['fact', 'preference', 'reference']);
23
24
 
24
- const asNonEmptyString = (value) => {
25
- if (typeof value !== 'string') return null;
26
- const trimmed = value.trim();
27
- return trimmed.length > 0 ? trimmed : null;
28
- };
29
-
30
25
  /** Everything the agent is told about an entry it has not opened yet. */
31
26
  const toSummary = (entry, scope) => ({
32
27
  memoryId: entry.id,
@@ -16,14 +16,13 @@
16
16
  * `req.body` as undefined and rejects every write as a malformed body.
17
17
  */
18
18
 
19
+ import { isRecord as isObjectRecord } from '../shared/guards.js';
19
20
  import express from 'express';
20
21
 
21
22
  const parseJsonBody = express.json({ limit: '1mb' });
22
23
 
23
24
  const MEMORY_TYPES = new Set(['fact', 'preference', 'reference']);
24
25
 
25
- const isObjectRecord = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
26
-
27
26
  const isValidationError = (error) => {
28
27
  const message = error instanceof Error ? error.message : '';
29
28
  return message.includes('is required')
@@ -55,6 +55,7 @@ const PROJECT_MEMORY_MAX_ITEMS = 200;
55
55
  */
56
56
  const MEMORY_TYPES = new Set(['fact', 'preference', 'reference']);
57
57
 
58
+ import { asNonEmptyString, isRecord as isObjectRecord } from '../shared/guards.js';
58
59
  import { projectConfigFileStemOf } from '../projects/project-id.js';
59
60
  import { findThreatPattern } from './threat-patterns.js';
60
61
 
@@ -133,12 +134,6 @@ const findSupersededEntry = (entries, title, body) => {
133
134
  return best;
134
135
  };
135
136
 
136
- const asNonEmptyString = (value) => {
137
- if (typeof value !== 'string') return null;
138
- const trimmed = value.trim();
139
- return trimmed.length > 0 ? trimmed : null;
140
- };
141
-
142
137
  const clampLength = (value, maxLength) => {
143
138
  if (typeof value !== 'string') return '';
144
139
  return value.length > maxLength ? value.slice(0, maxLength) : value;
@@ -151,8 +146,6 @@ const clampLength = (value, maxLength) => {
151
146
  */
152
147
  const bodyFitsLimit = (value) => (asNonEmptyString(value)?.length ?? 0) <= MEMORY_BODY_MAX_LENGTH;
153
148
 
154
- const isObjectRecord = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
155
-
156
149
  const limitForScope = (scope) => (scope === 'global' ? GLOBAL_MEMORY_MAX_ITEMS : PROJECT_MEMORY_MAX_ITEMS);
157
150
 
158
151
  const sanitizeEntries = (value, now, scope) => {
@@ -101,10 +101,14 @@ both settings are `false`.
101
101
  create, send, or schedule always wins, even when it relates to the current
102
102
  task (strict models otherwise read the old unconditional "never delegate" as
103
103
  a hard ban and refused user-requested sends).
104
- - Optional behavior switches (`worktree`, `goal`, `agent`, `variant`,
105
- `returnResult`) state their default and an explicit "only when the user
106
- asks" rule so agents do not invent worktrees, goal mode, or result
104
+ - Optional behavior switches (`worktree`, `pullRequest`, `goal`, `agent`,
105
+ `variant`, `returnResult`) state their default and an explicit "only when
106
+ the user asks" rule so agents do not invent worktrees, goal mode, or result
107
107
  deliveries the user never requested.
108
+ - `pullRequest` is a pull or merge request number in the project. The session
109
+ starts in a worktree made from it the way the New worktree dialog makes one
110
+ (`../git/DOCUMENTATION.md`, *Worktree creation from a GitHub pull request*);
111
+ everything else about the request is resolved on the server.
108
112
  - A rule about when to act belongs where the model reads it before choosing a
109
113
  tool: the head of the tool description and, when it must hold in every
110
114
  session, the session context (`../session-knowledge/`). An action's
@@ -1,3 +1,4 @@
1
+ import { asNonEmptyString } from '../shared/guards.js';
1
2
  import {
2
3
  OPENCHAMBER_AGENT_TOOL_ACTION_DEFINITIONS,
3
4
  OPENCHAMBER_AGENT_TOOL_ACTIONS,
@@ -72,6 +73,7 @@ const ALL_PARAMETER_PROPERTIES = {
72
73
  additionalProperties: false,
73
74
  },
74
75
  taskId: { type: 'string' },
76
+ targetSessionId: { type: 'string', description: 'Scheduled task target; omit for a new session, empty on update clears it' },
75
77
  title: { type: 'string' },
76
78
  prompt: { type: 'string' },
77
79
  model: { type: 'string', description: 'Model in provider/model format. When the user names no model: for session.create pick a suitable one from models.list favorites or recents (omit if there are none); for send and fork omit it — the session reuses its previous model' },
@@ -81,6 +83,7 @@ const ALL_PARAMETER_PROPERTIES = {
81
83
  branch: { type: 'string', description: 'Branch name for the new worktree' },
82
84
  startRef: { type: 'string', description: 'Git ref used to create the new worktree' },
83
85
  setUpstream: { type: 'boolean', description: 'Make the new worktree branch track its upstream' },
86
+ pullRequest: { type: 'integer', minimum: 1, description: "Pull or merge request number in this project for session.create: the session starts in a new worktree on that request's branch, made the way the New worktree dialog makes it. worktree and branch only rename the folder and the local branch. Use only when the user asks to work on that pull request" },
84
87
  goal: { type: 'boolean', description: 'Run the dispatched prompt in Goal Mode; use only when the user explicitly requests it' },
85
88
  goalTokenBudget: { type: 'integer', minimum: 1000, maximum: 100_000_000, description: 'Goal token budget; requires goal' },
86
89
  returnResult: { type: 'boolean', description: 'For session.create, send and fork with a prompt: deliver the session\'s final answer back to you as a message when it finishes, waking you to continue. The call still returns at once. Set only when the user wants the outcome back or your next step needs it' },
@@ -170,12 +173,6 @@ const agentOnlyUsageError = (action, input) => {
170
173
  return null;
171
174
  };
172
175
 
173
- const asNonEmptyString = (value) => {
174
- if (typeof value !== 'string') return null;
175
- const trimmed = value.trim();
176
- return trimmed.length > 0 ? trimmed : null;
177
- };
178
-
179
176
  const createResult = ({ ok, action, data, error, exitCode }) => ({
180
177
  schemaVersion: TOOL_SCHEMA_VERSION,
181
178
  ok,
@@ -505,8 +505,6 @@ describe('managed agent tool runtime', () => {
505
505
  expect(response.body).toEqual(expect.objectContaining({ ok: true, action: 'projects.list' }));
506
506
  });
507
507
 
508
-
509
-
510
508
  it.each([
511
509
  ['0.0.0.0', 'http://127.0.0.1:3901/api/openchamber/agent-tool'],
512
510
  ['::', 'http://127.0.0.1:3901/api/openchamber/agent-tool'],
@@ -64,6 +64,12 @@ itself; it can only ask and wait.
64
64
  pane. `browser.capture` never opens the panel or switches its tab: a hidden
65
65
  pane is drawn at zero opacity inside the window for the screenshot, because
66
66
  Chromium composites a transparent webview but not a hidden or clipped one.
67
+ Agent work never takes keyboard focus from the user
68
+ (`useWebviewFocusGuard` beside `BrowserPane`): a page may take focus only
69
+ while the user can see it and no agent action is driving it, otherwise focus
70
+ goes straight back to where it was. `browser.click` and `browser.type` focus
71
+ the page on purpose, so it can use the clipboard, and return focus when they
72
+ finish.
67
73
  `tabId` is validated and passed through by
68
74
  `../openchamber-control/service.js` for every action, so an extension
69
75
  provider receives it untouched (`BrowserTabTarget` in `@openchamber/sdk`).
@@ -10,7 +10,7 @@
10
10
  // Any failure (network, 404, unexpected shape) yields null: the update is
11
11
  // still offered, only without notes.
12
12
 
13
- export const CHANGELOG_INDEX_URL = 'https://raw.githubusercontent.com/openchamber/openchamber/main/changelog/index.json';
13
+ const CHANGELOG_INDEX_URL = 'https://raw.githubusercontent.com/openchamber/openchamber/main/changelog/index.json';
14
14
 
15
15
  const GROUPS = [
16
16
  ['new', 'New'],
@@ -1,10 +1,9 @@
1
+ import { isRecord } from '../shared/guards.js';
1
2
  import { assertPromptResponse } from '../opencode/prompt-response.js';
2
3
  import { unwrapOpenCodeResponse } from '../opencode/response-envelope.js';
3
4
  const FETCH_TIMEOUT_MS = 15_000;
4
5
  const MESSAGE_FETCH_LIMIT = 20;
5
6
 
6
- const isRecord = (value) => Boolean(value && typeof value === 'object' && !Array.isArray(value));
7
-
8
7
  const readContextState = (session) => {
9
8
  const metadata = isRecord(session?.metadata) ? session.metadata : {};
10
9
  const openchamber = isRecord(metadata.openchamber) ? metadata.openchamber : {};
@@ -74,3 +74,11 @@ and what made it fragile per framework.
74
74
  machine answers and show local content under a remote address.
75
75
  - Closing either end closes the other. A half-open pipe would leave the page
76
76
  waiting on bytes that will never arrive.
77
+ - A dev server inside an isolated space is reached the same way, with a space
78
+ id: the client dials `/api/spaces/<id>/dev-tunnel`, which the host forwards
79
+ to the server inside the space, and that server dials the port on its own
80
+ loopback against its own discovery. A space's tunnel is keyed apart from the
81
+ host's on the same port. What the desktop does with the page it gets, a
82
+ session of the space's own behind a proxy that reaches only its tunnel ports,
83
+ is in `packages/electron/space-preview.mjs` and the "Preview" section of
84
+ `packages/web/server/lib/spaces/DOCUMENTATION.md`.