@vantran-se/openchamber-web 1.23.1 → 1.24.4

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 (313) hide show
  1. package/bin/cli.test.js +29 -6
  2. package/bin/lib/cli-http.js +5 -1
  3. package/bin/lib/commands-status.js +5 -0
  4. package/dist/assets/{CodeMirrorCommentWidgets-BOpqXpFU.js → CodeMirrorCommentWidgets-B4a0JkUz.js} +1 -1
  5. package/dist/assets/DiffView-B2CD9wC8.js +4 -0
  6. package/dist/assets/FilesView-C4vMFclc.js +13 -0
  7. package/dist/assets/GitView-Byu2DY7s.js +6 -0
  8. package/dist/assets/GuestAttachDialog-B808E0-d.js +1 -0
  9. package/dist/assets/{JsonTreeView-nd_E8eVM.js → JsonTreeView-VW_7czo3.js} +1 -1
  10. package/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  11. package/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  12. package/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  13. package/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  14. package/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  15. package/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  16. package/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  17. package/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  18. package/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  19. package/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  20. package/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  21. package/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  22. package/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  23. package/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  24. package/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  25. package/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  26. package/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  27. package/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  28. package/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  29. package/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  30. package/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  31. package/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  32. package/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  33. package/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  34. package/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  35. package/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  36. package/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  37. package/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  38. package/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  39. package/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  40. package/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  41. package/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  42. package/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  43. package/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  44. package/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  45. package/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  46. package/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  47. package/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  48. package/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  49. package/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  50. package/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  51. package/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  52. package/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  53. package/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  54. package/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  55. package/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  56. package/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  57. package/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  58. package/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  59. package/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  60. package/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  61. package/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  62. package/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  63. package/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  64. package/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  65. package/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  66. package/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  67. package/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  68. package/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  69. package/dist/assets/LinearIssuesView-EzGNCGrd.js +1 -0
  70. package/dist/assets/{MarkdownImageGallery-CVYds3sQ.js → MarkdownImageGallery-B2YUDFaB.js} +1 -1
  71. package/dist/assets/MarkdownRendererImpl-B4ikIzR3.js +12 -0
  72. package/dist/assets/{OnboardingScreen-Dd2IbPTn.js → OnboardingScreen-CQHBSTEi.js} +1 -1
  73. package/dist/assets/{PatchDiff-nUu5i4bG.js → PatchDiff-DCjGhlYV.js} +1 -1
  74. package/dist/assets/PierreDiffViewer-CEDZNkU2.js +210 -0
  75. package/dist/assets/PlanView-D3x-pTkZ.js +5 -0
  76. package/dist/assets/PluginPane-DEcgDQ9h.js +3 -0
  77. package/dist/assets/SettingsView-CSinuH-1.js +29 -0
  78. package/dist/assets/{SettingsWindow-BccxY81J.js → SettingsWindow-B5CHoJFZ.js} +1 -1
  79. package/dist/assets/SubmoduleDiffSummary-oxeACCWs.js +1 -0
  80. package/dist/assets/ToolOutputDialog-tLNWmfcW.js +15 -0
  81. package/dist/assets/{ToolPartDiffPreview-BFVgk0UK.js → ToolPartDiffPreview-CflzmK-x.js} +2 -2
  82. package/dist/assets/{VirtualizedFileDiff-z3_H74UR.js → VirtualizedFileDiff-NU0FHFhT.js} +3 -3
  83. package/dist/assets/{WalkthroughView-BqM9GFbJ.js → WalkthroughView-BZyjhqHv.js} +2 -2
  84. package/dist/assets/appThemeRegistry-DLicw4dH.js +1 -0
  85. package/dist/assets/commitAndPush-BDftrjr6.js +1 -0
  86. package/dist/assets/{computeVirtualFileMetrics-Bdazp9Qo.js → computeVirtualFileMetrics-DlWlEM3x.js} +1 -1
  87. package/dist/assets/de-Bro6_zyl.js +10 -0
  88. package/dist/assets/es-Bb9XQZvd.js +16 -0
  89. package/dist/assets/fr-Dgfzn-IL.js +14 -0
  90. package/dist/assets/{index-eo1-D_7z.js → index-CtQNmqUL.js} +1 -1
  91. package/dist/assets/index-DqaMWNrC.css +1 -0
  92. package/dist/assets/index-Dqc6USl3.js +40 -0
  93. package/dist/assets/{isDiffPlainText-BvKH712-.js → isDiffPlainText-CO4e5J_S.js} +1 -1
  94. package/dist/assets/{isFilePlainText-BdVVPukf.js → isFilePlainText-ue6kCou7.js} +1 -1
  95. package/dist/assets/ja-BYsakGFh.js +16 -0
  96. package/dist/assets/ko-BSaQz9aN.js +16 -0
  97. package/dist/assets/main-B62_pjL5.js +2 -0
  98. package/dist/assets/main-BEdcOI2P.js +896 -0
  99. package/dist/assets/{markdown-shiki.worker-D5fBU-lw.js → markdown-shiki.worker-CahLvHIq.js} +5 -5
  100. package/dist/assets/markdownCore-CK48LG0z.js +5 -0
  101. package/dist/assets/miniChat-LT8Rqofr.js +2 -0
  102. package/dist/assets/mobile-CqarEynh.js +2 -0
  103. package/dist/assets/{patchFileDiff-B7LjppSS.js → patchFileDiff-D7QVlovD.js} +3 -3
  104. package/dist/assets/pl-OIviPdoj.js +16 -0
  105. package/dist/assets/pt-BR-Cltg-E6s.js +16 -0
  106. package/dist/assets/renderElectronMiniChatApp-COyLTtZx.js +2 -0
  107. package/dist/assets/renderMobileApp-BC1MHg6g.js +25 -0
  108. package/dist/assets/runtimeEndpointReset-DdrazOVH.js +25 -0
  109. package/dist/assets/{scheduledTasksApi-hceovDei.js → scheduledTasksApi-B2SWMGEU.js} +1 -1
  110. package/dist/assets/shikiHighlight-BPu3JiQs.js +1 -0
  111. package/dist/assets/textMateThemeFromAppTheme-DWqRPo9A.js +1 -0
  112. package/dist/assets/tr-CQI-KPre.js +7 -0
  113. package/dist/assets/uk-CqW7R4DA.js +16 -0
  114. package/dist/assets/useAppFontEffects-ne84JBVL.js +7333 -0
  115. package/dist/assets/useInlineCommentController-CgS0fnw_.js +2 -0
  116. package/dist/assets/useRootScrollLock-Cpf1qoGp.js +2 -0
  117. package/dist/assets/{vendor-base-ui-BY_5qla_.js → vendor-base-ui-CsXYnR5c.js} +1 -1
  118. package/dist/assets/{vendor-codemirror-language-data-DWA1bm1F.js → vendor-codemirror-language-data-Bx2EHc1O.js} +2 -2
  119. package/dist/assets/vendor-framer-motion-Bq3iTZ6r.js +1 -0
  120. package/dist/assets/vendor-katex-Cp579UoJ.css +1 -0
  121. package/dist/assets/{vendor-motion-dom-D_o3BTI3.js → vendor-motion-dom-DcCgeG69.js} +1 -1
  122. package/dist/assets/{vendor-remixicon-react-Dil0zKKT.js → vendor-remixicon-react-BDmGmFCA.js} +1 -1
  123. package/dist/assets/vendor-strip-json-comments-5dJlOkP1.js +4 -0
  124. package/dist/assets/{vendor-tanstack-react-virtual-g05Cx3z9.js → vendor-tanstack-react-virtual-ClYN8CzB.js} +1 -1
  125. package/dist/assets/{vendor-tanstack-virtual-core-Dubg10g5.js → vendor-tanstack-virtual-core-BewVQryB.js} +1 -1
  126. package/dist/assets/{vendor-zod-B6551dwG.js → vendor-zod-CgAdXWZO.js} +4 -4
  127. package/dist/assets/{web-components-B_Z64So5.js → web-components-DxX8bZ1o.js} +2 -2
  128. package/dist/assets/zh-CN-CVZG_o_J.js +16 -0
  129. package/dist/assets/zh-TW-D5ZxzCZp.js +16 -0
  130. package/dist/index.html +6 -4
  131. package/dist/mini-chat.html +6 -4
  132. package/dist/mobile.html +6 -4
  133. package/package.json +12 -9
  134. package/server/built-in-extensions/registry.json +4 -0
  135. package/server/index.d.ts +2 -0
  136. package/server/index.js +44 -10
  137. package/server/lib/agent-tool/DOCUMENTATION.md +17 -4
  138. package/server/lib/agent-tool/runtime.js +62 -15
  139. package/server/lib/agent-tool/runtime.test.js +88 -2
  140. package/server/lib/changelog/update-notes.js +2 -1
  141. package/server/lib/changelog/update-notes.test.js +19 -0
  142. package/server/lib/event-stream/DOCUMENTATION.md +23 -0
  143. package/server/lib/event-stream/delta-coalescer.js +0 -0
  144. package/server/lib/event-stream/delta-coalescer.test.js +292 -0
  145. package/server/lib/event-stream/global-hub.js +53 -23
  146. package/server/lib/event-stream/global-hub.test.js +160 -0
  147. package/server/lib/event-stream/global-ws-bridge.js +1 -0
  148. package/server/lib/event-stream/index.js +4 -0
  149. package/server/lib/fs/DOCUMENTATION.md +10 -1
  150. package/server/lib/fs/git-process.test.js +77 -0
  151. package/server/lib/fs/routes.js +58 -5
  152. package/server/lib/fs/routes.test.js +116 -0
  153. package/server/lib/fs/search.js +2 -1
  154. package/server/lib/git/DOCUMENTATION.md +20 -5
  155. package/server/lib/git/routes.js +16 -3
  156. package/server/lib/git/serial-refresh.js +93 -0
  157. package/server/lib/git/serial-refresh.test.js +112 -0
  158. package/server/lib/git/service.js +429 -70
  159. package/server/lib/git/service.test.js +418 -0
  160. package/server/lib/github/pr-status.js +5 -5
  161. package/server/lib/github/pr-status.test.js +1 -1
  162. package/server/lib/github/routes.js +4 -4
  163. package/server/lib/guests/DOCUMENTATION.md +68 -0
  164. package/server/lib/guests/auth-store.js +184 -0
  165. package/server/lib/guests/auth-store.test.js +112 -0
  166. package/server/lib/guests/background.test.js +83 -0
  167. package/server/lib/guests/builtins.js +34 -0
  168. package/server/lib/guests/builtins.test.js +174 -0
  169. package/server/lib/guests/catalog.js +477 -0
  170. package/server/lib/guests/catalog.test.js +390 -0
  171. package/server/lib/guests/clone.js +297 -0
  172. package/server/lib/guests/extract-zip.js +136 -0
  173. package/server/lib/guests/extract-zip.test.js +109 -0
  174. package/server/lib/guests/files.js +308 -0
  175. package/server/lib/guests/files.test.js +262 -0
  176. package/server/lib/guests/grant-scope.js +81 -0
  177. package/server/lib/guests/grant-scope.test.js +75 -0
  178. package/server/lib/guests/host-session.js +73 -0
  179. package/server/lib/guests/host-session.test.js +30 -0
  180. package/server/lib/guests/html-styles.js +6 -0
  181. package/server/lib/guests/html-styles.test.js +45 -0
  182. package/server/lib/guests/html-tokens.js +73 -0
  183. package/server/lib/guests/html-tokens.test.js +53 -0
  184. package/server/lib/guests/install.js +406 -0
  185. package/server/lib/guests/install.test.js +338 -0
  186. package/server/lib/guests/oauth.js +501 -0
  187. package/server/lib/guests/oauth.test.js +481 -0
  188. package/server/lib/guests/persist.js +336 -0
  189. package/server/lib/guests/persist.test.js +288 -0
  190. package/server/lib/guests/request.js +112 -0
  191. package/server/lib/guests/request.test.js +206 -0
  192. package/server/lib/guests/routes.js +838 -0
  193. package/server/lib/guests/service.js +538 -0
  194. package/server/lib/guests/service.test.js +277 -0
  195. package/server/lib/guests/sockets.js +129 -0
  196. package/server/lib/guests/sockets.test.js +110 -0
  197. package/server/lib/guests/ssh-install.test.js +188 -0
  198. package/server/lib/guests/storage.js +68 -0
  199. package/server/lib/guests/storage.test.js +59 -0
  200. package/server/lib/guests/updates.js +294 -0
  201. package/server/lib/guests/updates.test.js +334 -0
  202. package/server/lib/guests/upload.js +50 -0
  203. package/server/lib/guests/upload.test.js +131 -0
  204. package/server/lib/linear/DOCUMENTATION.md +1 -1
  205. package/server/lib/message-queue/DOCUMENTATION.md +10 -1
  206. package/server/lib/message-queue/runtime.js +21 -1
  207. package/server/lib/message-queue/runtime.test.js +52 -5
  208. package/server/lib/notifications/routes.js +5 -0
  209. package/server/lib/openchamber-control/DOCUMENTATION.md +6 -0
  210. package/server/lib/openchamber-sessions/routes.js +62 -29
  211. package/server/lib/openchamber-sessions/routes.test.js +96 -0
  212. package/server/lib/opencode/DOCUMENTATION.md +55 -1
  213. package/server/lib/opencode/bootstrap-runtime.js +1 -0
  214. package/server/lib/opencode/core-routes.js +39 -1
  215. package/server/lib/opencode/feature-routes-runtime.js +15 -0
  216. package/server/lib/opencode/lifecycle-process.test.js +84 -0
  217. package/server/lib/opencode/lifecycle.js +54 -67
  218. package/server/lib/opencode/openchamber-routes.js +72 -14
  219. package/server/lib/opencode/openchamber-routes.test.js +71 -3
  220. package/server/lib/opencode/session-runtime.js +68 -0
  221. package/server/lib/opencode/session-runtime.test.js +43 -0
  222. package/server/lib/opencode/settings-helpers.js +8 -0
  223. package/server/lib/opencode/settings-helpers.test.js +13 -1
  224. package/server/lib/opencode/settings-normalization-runtime.js +2 -0
  225. package/server/lib/opencode/settings-normalization-runtime.test.js +13 -0
  226. package/server/lib/opencode/settings-registry.json +15 -0
  227. package/server/lib/opencode/shutdown-runtime.js +3 -0
  228. package/server/lib/opencode/shutdown-runtime.test.js +24 -0
  229. package/server/lib/opencode/theme-archive.js +53 -0
  230. package/server/lib/opencode/theme-catalog.js +171 -0
  231. package/server/lib/opencode/theme-catalog.test.js +125 -0
  232. package/server/lib/opencode/theme-import.test.js +144 -0
  233. package/server/lib/opencode/theme-runtime.js +100 -28
  234. package/server/lib/opencode/theme-runtime.test.js +15 -0
  235. package/server/lib/permission-auto-accept/DOCUMENTATION.md +8 -0
  236. package/server/lib/permission-auto-accept/runtime.js +13 -0
  237. package/server/lib/permission-auto-accept/runtime.test.js +37 -1
  238. package/server/lib/projects/project-config.js +2 -2
  239. package/server/lib/quota/DOCUMENTATION.md +0 -1
  240. package/server/lib/quota/providers/index.js +0 -7
  241. package/server/lib/realtime-proxy-terminal.test.js +150 -0
  242. package/server/lib/realtime-proxy.js +2 -0
  243. package/server/lib/routing/DOCUMENTATION.md +83 -0
  244. package/server/lib/routing/defaults.js +98 -0
  245. package/server/lib/routing/feature-flag.js +11 -0
  246. package/server/lib/routing/history.js +34 -0
  247. package/server/lib/routing/jev.js +98 -0
  248. package/server/lib/routing/routes.http.test.js +100 -0
  249. package/server/lib/routing/routes.js +81 -0
  250. package/server/lib/routing/runtime.js +217 -0
  251. package/server/lib/routing/runtime.test.js +188 -0
  252. package/server/lib/routing/store.js +249 -0
  253. package/server/lib/routing/store.test.js +96 -0
  254. package/server/lib/scheduled-tasks/runtime.js +2 -2
  255. package/server/lib/scheduled-tasks/runtime.test.js +14 -0
  256. package/server/lib/security/request-security.js +9 -5
  257. package/server/lib/security/request-security.test.js +37 -0
  258. package/server/lib/small-model/DOCUMENTATION.md +14 -2
  259. package/server/lib/small-model/call.js +37 -6
  260. package/server/lib/small-model/call.test.js +182 -0
  261. package/server/lib/terminal/DOCUMENTATION.md +23 -2
  262. package/server/lib/terminal/runtime.js +27 -5
  263. package/server/lib/terminal/runtime.test.js +67 -0
  264. package/server/lib/terminal/shutdown.js +106 -0
  265. package/server/lib/terminal/shutdown.test.js +84 -0
  266. package/server/lib/tts/service.test.js +78 -0
  267. package/server/lib/ui-auth/DOCUMENTATION.md +8 -0
  268. package/server/lib/ui-auth/session-cookie.js +51 -0
  269. package/server/lib/ui-auth/session-cookie.test.js +46 -0
  270. package/server/lib/ui-auth/ui-auth.js +56 -17
  271. package/server/lib/ui-auth/ui-auth.test.js +96 -0
  272. package/dist/assets/DiffView-CyLmb-wF.js +0 -4
  273. package/dist/assets/DirtyBranchSwitchDialog-pu5kcoir.js +0 -1
  274. package/dist/assets/FilesView-WtJB0y_l.js +0 -13
  275. package/dist/assets/GitView-DkNrV0BK.js +0 -6
  276. package/dist/assets/LinearIssuesView-B0H0Otii.js +0 -1
  277. package/dist/assets/MarkdownRendererImpl-DSqVN2d8.js +0 -12
  278. package/dist/assets/PierreDiffViewer-Bsq9z-sw.js +0 -161
  279. package/dist/assets/PlanView-CAFziKH5.js +0 -5
  280. package/dist/assets/SettingsView-BRittavZ.js +0 -28
  281. package/dist/assets/ToolOutputDialog-B0uYaJio.js +0 -15
  282. package/dist/assets/appThemeRegistry-BK0dHKa6.js +0 -1
  283. package/dist/assets/de-c7CYLCAW.js +0 -10
  284. package/dist/assets/es-BKAVPQmQ.js +0 -16
  285. package/dist/assets/fr-Bj1glqfV.js +0 -14
  286. package/dist/assets/index-BYFyOu_D.css +0 -1
  287. package/dist/assets/index-BfwRClDe.js +0 -40
  288. package/dist/assets/ja-5jwSIbK0.js +0 -16
  289. package/dist/assets/ko-BaDbg-Eb.js +0 -16
  290. package/dist/assets/main-CGG2_uHq.js +0 -2
  291. package/dist/assets/main-CcrSaL4J.js +0 -930
  292. package/dist/assets/markdownCore-DsmQr3bt.js +0 -5
  293. package/dist/assets/miniChat-DEaAhP4b.js +0 -2
  294. package/dist/assets/mobile-BC3rsvv0.js +0 -2
  295. package/dist/assets/pl-BFKVBDFu.js +0 -16
  296. package/dist/assets/pt-BR-qKfHvkDL.js +0 -16
  297. package/dist/assets/registerCustomTheme-BBXUCRnG.js +0 -1
  298. package/dist/assets/renderElectronMiniChatApp-CR9d1Mr0.js +0 -2
  299. package/dist/assets/renderMobileApp-Da5dwobZ.js +0 -25
  300. package/dist/assets/runtimeEndpointReset-CLYVRw2H.js +0 -41
  301. package/dist/assets/shikiHighlight-D1Z9G58W.js +0 -1
  302. package/dist/assets/tr-DYXPoEDG.js +0 -7
  303. package/dist/assets/uk-CwAoloR8.js +0 -16
  304. package/dist/assets/useAppFontEffects-DeStGcUT.js +0 -7282
  305. package/dist/assets/useGitComparison-CpxioduU.js +0 -1
  306. package/dist/assets/useInlineCommentController-gmUnJtrb.js +0 -2
  307. package/dist/assets/useRootScrollLock--a3cPz8s.js +0 -1
  308. package/dist/assets/vendor-framer-motion-livSKyyV.js +0 -1
  309. package/dist/assets/zh-CN-D9MG0lqF.js +0 -16
  310. package/dist/assets/zh-TW-1HNK7shh.js +0 -16
  311. package/server/lib/quota/providers/crof.js +0 -96
  312. package/server/lib/quota/providers/crof.test.js +0 -98
  313. /package/dist/assets/{vendor-katex-k3Ppq1Ha.js → vendor-katex-CHD9BdDO.js} +0 -0
@@ -0,0 +1,538 @@
1
+ import { spawn } from 'node:child_process';
2
+ import crypto from 'node:crypto';
3
+ import fs from 'node:fs/promises';
4
+ import net from 'node:net';
5
+ import path from 'node:path';
6
+
7
+ import {
8
+ GUEST_REQUEST_RESPONSE_MAX,
9
+ GUEST_REQUEST_TIMEOUT_MS,
10
+ isGuestRequestPath,
11
+ } from '@openchamber/sdk';
12
+
13
+ import { readExtensionStore, updateExtensionStore } from './persist.js';
14
+ import { resolveServiceSocketEnv } from './sockets.js';
15
+
16
+ const METHODS = new Set(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
17
+ const SERVICE_READY_TIMEOUT_MS = 15_000;
18
+ const SERVICE_KILL_TIMEOUT_MS = 5_000;
19
+ const SERVICE_HEALTH_PATH = '/health';
20
+ /** Inbound auth header the service must require. */
21
+ const OPENCHAMBER_SERVICE_AUTH_HEADER = 'authorization';
22
+
23
+ /**
24
+ * @typedef {{
25
+ * child: import('node:child_process').ChildProcess,
26
+ * port: number,
27
+ * token: string,
28
+ * status: 'starting' | 'ready' | 'failed' | 'stopped',
29
+ * packageRoot: string,
30
+ * entry: string,
31
+ * }} ServiceRuntime
32
+ */
33
+
34
+ /** @type {Map<string, ServiceRuntime>} */
35
+ const runtimes = new Map();
36
+
37
+ /** @type {Map<string, Promise<ServiceRuntime>>} */
38
+ const startingByGuest = new Map();
39
+
40
+ export class GuestServiceError extends Error {
41
+ /**
42
+ * @param {string} message
43
+ * @param {'NO_SERVICE' | 'SERVICE_FAILED' | 'BAD_PATH' | 'BAD_METHOD'} code
44
+ */
45
+ constructor(message, code) {
46
+ super(message);
47
+ this.name = 'GuestServiceError';
48
+ this.code = code;
49
+ }
50
+ }
51
+
52
+ const reserveLoopbackPort = () => new Promise((resolve, reject) => {
53
+ const server = net.createServer();
54
+ server.listen(0, '127.0.0.1', () => {
55
+ const address = server.address();
56
+ if (!address || !('port' in address)) {
57
+ server.close();
58
+ reject(new Error('Could not reserve a loopback port'));
59
+ return;
60
+ }
61
+ const { port } = address;
62
+ server.close((error) => {
63
+ if (error) {
64
+ reject(error);
65
+ return;
66
+ }
67
+ resolve(port);
68
+ });
69
+ });
70
+ server.on('error', reject);
71
+ });
72
+
73
+ const sleep = (ms) => new Promise((resolve) => {
74
+ setTimeout(resolve, ms);
75
+ });
76
+
77
+ /**
78
+ * @param {number} port
79
+ * @param {string} token
80
+ */
81
+ const waitForServiceReady = async (port, token, shouldStop = () => false) => {
82
+ const deadline = Date.now() + SERVICE_READY_TIMEOUT_MS;
83
+ while (Date.now() < deadline && !shouldStop()) {
84
+ try {
85
+ const response = await fetch(`http://127.0.0.1:${port}${SERVICE_HEALTH_PATH}`, {
86
+ method: 'GET',
87
+ headers: {
88
+ Accept: 'application/json',
89
+ [OPENCHAMBER_SERVICE_AUTH_HEADER]: `Bearer ${token}`,
90
+ },
91
+ signal: AbortSignal.timeout(1_500),
92
+ });
93
+ if (response.status === 200) {
94
+ return true;
95
+ }
96
+ } catch {
97
+ // keep polling
98
+ }
99
+ await sleep(200);
100
+ }
101
+ return false;
102
+ };
103
+
104
+ /**
105
+ * @param {string} guestId
106
+ * @param {string} persistPath
107
+ */
108
+ /**
109
+ * @param {string} guestId
110
+ * @param {string} persistPath
111
+ * @param {boolean} enabled
112
+ */
113
+ export const setGuestEnabled = async (guestId, persistPath, enabled) => {
114
+ await updateExtensionStore(persistPath, (store) => {
115
+ const disabledGuests = { ...(store.disabledGuests ?? {}) };
116
+ if (enabled) {
117
+ delete disabledGuests[guestId];
118
+ } else {
119
+ disabledGuests[guestId] = true;
120
+ }
121
+ return { ...store, disabledGuests };
122
+ });
123
+ if (!enabled) {
124
+ await stopGuestService(guestId);
125
+ }
126
+ };
127
+
128
+ /**
129
+ * @param {string} guestId
130
+ * @param {string} socketId
131
+ * @param {string} persistPath
132
+ * @param {string | null} socketPath empty/null clears the override
133
+ */
134
+ export const setServiceSocketOverride = async (guestId, socketId, persistPath, socketPath) => {
135
+ await updateExtensionStore(persistPath, (store) => {
136
+ const serviceSocketOverrides = { ...(store.serviceSocketOverrides ?? {}) };
137
+ const forGuest = { ...(serviceSocketOverrides[guestId] ?? {}) };
138
+ const trimmed = typeof socketPath === 'string' ? socketPath.trim() : '';
139
+ if (trimmed) {
140
+ forGuest[socketId] = trimmed;
141
+ } else {
142
+ delete forGuest[socketId];
143
+ }
144
+ if (Object.keys(forGuest).length > 0) {
145
+ serviceSocketOverrides[guestId] = forGuest;
146
+ } else {
147
+ delete serviceSocketOverrides[guestId];
148
+ }
149
+ return { ...store, serviceSocketOverrides };
150
+ });
151
+ await stopGuestService(guestId);
152
+ };
153
+
154
+ /**
155
+ * @param {string} guestId
156
+ */
157
+ export const getServiceStatus = (guestId) => {
158
+ const runtime = runtimes.get(guestId);
159
+ if (!runtime) {
160
+ return 'stopped';
161
+ }
162
+ return runtime.status;
163
+ };
164
+
165
+ /**
166
+ * @param {string} guestId
167
+ */
168
+ /**
169
+ * Bumped by every stop. A start that began before the bump is cancelled: it
170
+ * checks the epoch after each await and kills whatever it spawned, so Pause
171
+ * during the seconds before the process is registered still stops it.
172
+ * @type {Map<string, number>}
173
+ */
174
+ const stopEpochs = new Map();
175
+
176
+ const stopEpochOf = (guestId) => stopEpochs.get(guestId) ?? 0;
177
+
178
+ /**
179
+ * A user-facing stop (Pause, Remove, withdrawn approval, socket change,
180
+ * host quit): ends the process and cancels any request or start in flight.
181
+ * @param {string} guestId
182
+ */
183
+ export const stopGuestService = async (guestId) => {
184
+ stopEpochs.set(guestId, stopEpochOf(guestId) + 1);
185
+ await discardRuntime(guestId);
186
+ };
187
+
188
+ /**
189
+ * Internal cleanup of a runtime that is dead or failed, before a restart.
190
+ * Does not bump the epoch: replacing a crashed process is not a Pause and
191
+ * must not cancel the request that triggered the restart.
192
+ * @param {string} guestId
193
+ */
194
+ const discardRuntime = async (guestId) => {
195
+ const runtime = runtimes.get(guestId);
196
+ if (!runtime) {
197
+ return;
198
+ }
199
+ runtimes.delete(guestId);
200
+ runtime.status = 'stopped';
201
+ const { child } = runtime;
202
+ if (child.exitCode !== null || child.signalCode) {
203
+ return;
204
+ }
205
+ await new Promise((resolve) => {
206
+ const timer = setTimeout(() => {
207
+ child.kill('SIGKILL');
208
+ resolve(undefined);
209
+ }, SERVICE_KILL_TIMEOUT_MS);
210
+ child.once('exit', () => {
211
+ clearTimeout(timer);
212
+ resolve(undefined);
213
+ });
214
+ child.kill('SIGTERM');
215
+ });
216
+ };
217
+
218
+ /** Test seam: the pid of a guest's running service, or `null`. */
219
+ export const readServicePid = (guestId) => runtimes.get(guestId)?.child.pid ?? null;
220
+
221
+ export const stopAllGuestServices = async () => {
222
+ const ids = [...runtimes.keys()];
223
+ await Promise.all(ids.map((id) => stopGuestService(id)));
224
+ };
225
+
226
+ /**
227
+ * @param {import('node:child_process').ChildProcess} child
228
+ * @param {number} maxChars
229
+ */
230
+ const collectProcessOutput = (child, maxChars = 2_000) => {
231
+ let stdout = '';
232
+ let stderr = '';
233
+ const append = (/** @type {'stdout' | 'stderr'} */ stream, chunk) => {
234
+ const text = typeof chunk === 'string' ? chunk : chunk.toString('utf8');
235
+ if (stream === 'stdout') {
236
+ stdout = `${stdout}${text}`.slice(-maxChars);
237
+ return;
238
+ }
239
+ stderr = `${stderr}${text}`.slice(-maxChars);
240
+ };
241
+ child.stdout?.on('data', (chunk) => append('stdout', chunk));
242
+ child.stderr?.on('data', (chunk) => append('stderr', chunk));
243
+ return {
244
+ snapshot: () => {
245
+ const out = stdout.trim();
246
+ const err = stderr.trim();
247
+ if (err && out) return `${err}\n${out}`;
248
+ return err || out;
249
+ },
250
+ };
251
+ };
252
+
253
+ /**
254
+ * @param {{
255
+ * guestId: string,
256
+ * packageRoot: string,
257
+ * entry: string,
258
+ * socketBindings?: Array<{ id: string, candidatesByPlatform?: Partial<Record<'linux' | 'darwin' | 'win32', string[]>> }>,
259
+ * socketOverrides?: Record<string, string>,
260
+ * }} params
261
+ */
262
+ const startGuestService = async ({
263
+ guestId,
264
+ packageRoot,
265
+ entry,
266
+ socketBindings = [],
267
+ socketOverrides = {},
268
+ epoch,
269
+ }) => {
270
+ const existing = runtimes.get(guestId);
271
+ if (existing?.status === 'ready' && existing.child.exitCode === null && !existing.child.signalCode) {
272
+ return existing;
273
+ }
274
+ if (existing) {
275
+ await discardRuntime(guestId);
276
+ }
277
+ // The request's epoch, read before its first store access: a Pause that
278
+ // finished anywhere since then is a cancellation, spawn included.
279
+ const cancelled = () => stopEpochOf(guestId) !== epoch;
280
+ const stoppedError = () => new GuestServiceError('The service was stopped before it became ready.', 'NO_SERVICE');
281
+
282
+ const absoluteEntry = path.resolve(packageRoot, entry);
283
+ const rootResolved = path.resolve(packageRoot);
284
+ if (!absoluteEntry.startsWith(`${rootResolved}${path.sep}`)) {
285
+ throw new GuestServiceError('Service entry must stay inside the package.', 'NO_SERVICE');
286
+ }
287
+ try {
288
+ await fs.access(absoluteEntry);
289
+ } catch {
290
+ throw new GuestServiceError('Service entry is missing.', 'NO_SERVICE');
291
+ }
292
+
293
+ if (cancelled()) {
294
+ throw stoppedError();
295
+ }
296
+ const port = await reserveLoopbackPort();
297
+ const token = crypto.randomBytes(24).toString('hex');
298
+ const socketEnv = socketBindings.length > 0
299
+ ? await resolveServiceSocketEnv(socketBindings, socketOverrides)
300
+ : {};
301
+ if (cancelled()) {
302
+ throw stoppedError();
303
+ }
304
+ const env = {
305
+ ...inheritedServiceEnv(process.env),
306
+ OPENCHAMBER_SERVICE_PORT: String(port),
307
+ OPENCHAMBER_SERVICE_TOKEN: token,
308
+ ELECTRON_RUN_AS_NODE: '1',
309
+ };
310
+ if (Object.keys(socketEnv).length > 0) {
311
+ env.OPENCHAMBER_SERVICE_SOCKETS = JSON.stringify(socketEnv);
312
+ }
313
+ if (cancelled()) {
314
+ throw stoppedError();
315
+ }
316
+ const child = spawn(process.execPath, [absoluteEntry], {
317
+ cwd: packageRoot,
318
+ env,
319
+ stdio: ['ignore', 'pipe', 'pipe'],
320
+ windowsHide: true,
321
+ });
322
+ const output = collectProcessOutput(child);
323
+
324
+ /** @type {ServiceRuntime} */
325
+ const runtime = {
326
+ child,
327
+ port,
328
+ token,
329
+ status: 'starting',
330
+ packageRoot,
331
+ entry,
332
+ };
333
+ runtimes.set(guestId, runtime);
334
+
335
+ child.once('exit', () => {
336
+ const current = runtimes.get(guestId);
337
+ if (current === runtime) {
338
+ runtime.status = runtime.status === 'starting' ? 'failed' : 'stopped';
339
+ }
340
+ });
341
+
342
+ const ready = await waitForServiceReady(port, token, () => cancelled() || child.exitCode !== null || Boolean(child.signalCode));
343
+ if (cancelled()) {
344
+ // Pause landed while the process was coming up; stopGuestService found
345
+ // this runtime (registered above) and is killing it, or already did.
346
+ if (runtimes.get(guestId) === runtime) {
347
+ await discardRuntime(guestId);
348
+ }
349
+ throw stoppedError();
350
+ }
351
+ if (!ready || child.exitCode !== null || child.signalCode) {
352
+ runtime.status = 'failed';
353
+ const detail = output.snapshot();
354
+ await discardRuntime(guestId);
355
+ throw new GuestServiceError(
356
+ detail
357
+ ? `Guest service failed to become ready. ${detail}`
358
+ : 'Guest service failed to become ready.',
359
+ 'SERVICE_FAILED',
360
+ );
361
+ }
362
+ runtime.status = 'ready';
363
+ return runtime;
364
+ };
365
+
366
+ /**
367
+ * One spawn in flight per guest. Parallel panel requests must not kill each other.
368
+ * @param {{
369
+ * guestId: string,
370
+ * packageRoot: string,
371
+ * entry: string,
372
+ * socketBindings?: Array<{ id: string, candidatesByPlatform?: Partial<Record<'linux' | 'darwin' | 'win32', string[]>> }>,
373
+ * socketOverrides?: Record<string, string>,
374
+ * }} params
375
+ */
376
+ /**
377
+ * Environment variables a guest service may inherit from the host process.
378
+ * The host env also carries the UI password, tool tokens, and whatever API
379
+ * keys the user exported; a third-party process gets none of that, only what
380
+ * a locale-aware Node process needs to find its tools and temp dir.
381
+ */
382
+ const INHERITED_SERVICE_ENV_NAMES = new Set([
383
+ 'PATH', 'HOME', 'USER', 'LOGNAME', 'SHELL', 'TMPDIR', 'TEMP', 'TMP', 'TZ',
384
+ 'LANG', 'LANGUAGE', 'LC_ALL', 'LC_CTYPE', 'LC_MESSAGES',
385
+ 'XDG_CONFIG_HOME', 'XDG_DATA_HOME', 'XDG_CACHE_HOME', 'XDG_RUNTIME_DIR',
386
+ 'USERPROFILE', 'HOMEDRIVE', 'HOMEPATH', 'APPDATA', 'LOCALAPPDATA', 'PROGRAMDATA',
387
+ 'SYSTEMROOT', 'SYSTEMDRIVE', 'COMSPEC', 'PATHEXT', 'WINDIR',
388
+ ]);
389
+
390
+ /** @param {NodeJS.ProcessEnv} source */
391
+ export const inheritedServiceEnv = (source) => {
392
+ /** @type {Record<string, string>} */
393
+ const env = {};
394
+ for (const [name, value] of Object.entries(source)) {
395
+ if (typeof value === 'string' && INHERITED_SERVICE_ENV_NAMES.has(name.toUpperCase())) {
396
+ env[name] = value;
397
+ }
398
+ }
399
+ return env;
400
+ };
401
+
402
+ const ensureGuestService = async (params) => {
403
+ const existing = runtimes.get(params.guestId);
404
+ if (existing?.status === 'ready' && existing.child.exitCode === null && !existing.child.signalCode) {
405
+ return existing;
406
+ }
407
+ const inflight = startingByGuest.get(params.guestId);
408
+ if (inflight) {
409
+ return inflight;
410
+ }
411
+ const pending = startGuestService(params).finally(() => {
412
+ if (startingByGuest.get(params.guestId) === pending) {
413
+ startingByGuest.delete(params.guestId);
414
+ }
415
+ });
416
+ startingByGuest.set(params.guestId, pending);
417
+ return pending;
418
+ };
419
+
420
+ /**
421
+ * @param {{
422
+ * guestId: string,
423
+ * packageRoot: string,
424
+ * service: { entry: string, permissions?: { sockets?: Array<{ id: string, candidatesByPlatform?: Partial<Record<'linux' | 'darwin' | 'win32', string[]>> }>, exec?: string[] } },
425
+ * granted: string[],
426
+ * persistPath: string,
427
+ * method: string,
428
+ * path: string,
429
+ * query?: Record<string, string>,
430
+ * body?: string,
431
+ * }} params
432
+ */
433
+ export const proxyGuestServiceRequest = async ({
434
+ guestId,
435
+ guestName,
436
+ packageRoot,
437
+ service,
438
+ granted,
439
+ persistPath,
440
+ method,
441
+ path: requestPath,
442
+ query,
443
+ body,
444
+ }) => {
445
+ if (!METHODS.has(method)) {
446
+ throw new GuestServiceError('Unsupported request method.', 'BAD_METHOD');
447
+ }
448
+ if (!isGuestRequestPath(requestPath)) {
449
+ throw new GuestServiceError('Request path must stay on the service.', 'BAD_PATH');
450
+ }
451
+ // A Pause that lands anywhere between here and the proxied call bumps
452
+ // this; the request then ends with NO_SERVICE instead of using the
453
+ // enabled flag it read before the pause.
454
+ const epoch = stopEpochOf(guestId);
455
+ const store = await readExtensionStore(persistPath);
456
+ if (store.disabledGuests?.[guestId]) {
457
+ const label = typeof guestName === 'string' && guestName.trim() ? guestName.trim() : 'This extension';
458
+ throw new GuestServiceError(
459
+ `${label} is disabled in Settings → Extensions.`,
460
+ 'DISABLED',
461
+ );
462
+ }
463
+ // Every service is a third-party process running as the user. Declared
464
+ // permissions describe what it intends to touch; they do not confine it, so
465
+ // the grant is required whether or not the manifest declared any.
466
+ // `granted` is the catalog's effective list: it already drops `service`
467
+ // when the package's permissions changed after the user approved them.
468
+ if (!Array.isArray(granted) || !granted.includes('service')) {
469
+ throw new GuestServiceError('Allow this extension\'s local service in Settings → Extensions.', 'NO_SERVICE');
470
+ }
471
+
472
+ const socketOverrides = store.serviceSocketOverrides?.[guestId] ?? {};
473
+ const socketBindings = service.permissions?.sockets ?? [];
474
+
475
+ let runtime = runtimes.get(guestId);
476
+ if (!runtime || runtime.status !== 'ready' || runtime.child.exitCode !== null || runtime.child.signalCode) {
477
+ runtime = await ensureGuestService({
478
+ guestId,
479
+ packageRoot,
480
+ entry: service.entry,
481
+ socketBindings,
482
+ socketOverrides,
483
+ epoch,
484
+ });
485
+ }
486
+ if (stopEpochOf(guestId) !== epoch) {
487
+ if (runtimes.get(guestId) === runtime) {
488
+ await discardRuntime(guestId);
489
+ }
490
+ throw new GuestServiceError('The service was stopped before the request could run.', 'NO_SERVICE');
491
+ }
492
+
493
+ let url;
494
+ try {
495
+ url = new URL(requestPath, `http://127.0.0.1:${runtime.port}/`);
496
+ } catch {
497
+ throw new GuestServiceError('Request path must stay on the service.', 'BAD_PATH');
498
+ }
499
+ if (url.hostname !== '127.0.0.1' || url.port !== String(runtime.port)) {
500
+ throw new GuestServiceError('Request path must stay on the service.', 'BAD_PATH');
501
+ }
502
+ if (query) {
503
+ for (const [key, value] of Object.entries(query)) {
504
+ url.searchParams.set(key, value);
505
+ }
506
+ }
507
+
508
+ /** @type {Record<string, string>} */
509
+ const headers = {
510
+ Accept: 'application/json',
511
+ [OPENCHAMBER_SERVICE_AUTH_HEADER]: `Bearer ${runtime.token}`,
512
+ };
513
+ if (body !== undefined && method !== 'GET') {
514
+ headers['Content-Type'] = 'application/json';
515
+ }
516
+
517
+ let response;
518
+ try {
519
+ response = await fetch(url, {
520
+ method,
521
+ headers,
522
+ body: method === 'GET' || body === undefined ? undefined : body,
523
+ redirect: 'manual',
524
+ signal: AbortSignal.timeout(GUEST_REQUEST_TIMEOUT_MS),
525
+ });
526
+ } catch {
527
+ runtime.status = 'failed';
528
+ throw new GuestServiceError('Guest service request failed.', 'SERVICE_FAILED');
529
+ }
530
+
531
+ const text = await response.text();
532
+ return {
533
+ status: response.status,
534
+ body: text.length <= GUEST_REQUEST_RESPONSE_MAX
535
+ ? text
536
+ : text.slice(0, GUEST_REQUEST_RESPONSE_MAX),
537
+ };
538
+ };