@openchambery/web 1.19.22-beta.1 → 2.0.0-beta.10

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 (328) hide show
  1. package/README.md +13 -7
  2. package/bin/cli-opencode.test.js +208 -0
  3. package/bin/cli.js +62 -9
  4. package/bin/lib/cli-startup.js +105 -2
  5. package/bin/lib/cli-startup.test.js +179 -0
  6. package/dist/assets/{AgentAvatar-CRaBJXKs.js → AgentAvatar-CzTtVMnI.js} +1 -1
  7. package/dist/assets/AssistantView-Cg1qQvVe.js +3 -0
  8. package/dist/assets/{DiagramView-D1LGK_s2.js → DiagramView-hOi72Wdx.js} +1 -1
  9. package/dist/assets/{FadeInOnReveal-B0kJo9Ii.js → FadeInOnReveal-DCqrQkkz.js} +1 -1
  10. package/dist/assets/Icon-B8fSTLdP.js +1 -0
  11. package/dist/assets/MarkdownRenderer-Cw74oVxV.js +2 -0
  12. package/dist/assets/{MarkdownRendererImpl-DfoCJ1Mq.js → MarkdownRendererImpl-YM7iRmzK.js} +3 -3
  13. package/dist/assets/MarkstreamRendererImpl-BDy_oGJQ.js +3 -0
  14. package/dist/assets/MobileDetailNavigation-iX_hb_Xt.js +1 -0
  15. package/dist/assets/{MobileShareBridge-2Yjn6wXg.js → MobileShareBridge-CAMUupwR.js} +2 -2
  16. package/dist/assets/MobileSurface-CHbdPcLH.js +2 -0
  17. package/dist/assets/{MultiRunWindow-tTbMFowS.js → MultiRunWindow-Ci1ODFFX.js} +1 -1
  18. package/dist/assets/{OnboardingScreen-CD2KtlF3.js → OnboardingScreen-O4cGdz5p.js} +1 -1
  19. package/dist/assets/OverlayScrollbar-CRfGtcmG.js +2 -0
  20. package/dist/assets/SettingsView-Dg8BtTV1.js +25 -0
  21. package/dist/assets/{SettingsWindow-zIa76s4t.js → SettingsWindow-B8d8qIQ7.js} +1 -1
  22. package/dist/assets/TerminalView-CMiw3s_c.js +8 -0
  23. package/dist/assets/{ToolOutputDialog-DNqA4uBl.js → ToolOutputDialog-ByaQYRTp.js} +2 -2
  24. package/dist/assets/appThemeRegistry-BGGHio8T.js +1 -0
  25. package/dist/assets/{assistant-attachment-cache-C0aRnFkj.js → assistant-attachment-cache-DphJleHr.js} +1 -1
  26. package/dist/assets/{button-CI7Q-Zw_.js → button-DIIrsMjW.js} +1 -1
  27. package/dist/assets/{collapsible-D5Phaykh.js → collapsible-CnvUeYst.js} +1 -1
  28. package/dist/assets/{context-menu-CubSDW2g.js → context-menu-BGBUpZEQ.js} +1 -1
  29. package/dist/assets/{desktopHosts-B1ixEylr.js → desktopHosts-JGFqhlaM.js} +1 -1
  30. package/dist/assets/{desktopRelayRestore-4JmFUw8r.js → desktopRelayRestore-CHEwrI93.js} +1 -1
  31. package/dist/assets/{diagram-DdLO8HZ9.js → diagram-rvn7_qBM.js} +1 -1
  32. package/dist/assets/{dialog-B6pnIYmp.js → dialog-CQ63sc9E.js} +1 -1
  33. package/dist/assets/es-Dsmc0A_3.js +15 -0
  34. package/dist/assets/fileMentionTouchSelection-BzzcWJCi.js +3 -0
  35. package/dist/assets/{fileQueries-DQc8EJUf.js → fileQueries-DN6gbLhM.js} +1 -1
  36. package/dist/assets/fr-C_ZlZDI2.js +13 -0
  37. package/dist/assets/gitApi-BF8vuoZc.js +10 -0
  38. package/dist/assets/{imageSource-BlAJJUEI.js → imageSource-BMztRu0c.js} +1 -1
  39. package/dist/assets/{input-D-__fwRi.js → input-BVu-iykl.js} +1 -1
  40. package/dist/assets/insertionBoundaries-EcAfGT2D.js +1 -0
  41. package/dist/assets/ja-BqqTaWTi.js +15 -0
  42. package/dist/assets/ko-DP2XPM37.js +15 -0
  43. package/dist/assets/main-B7t9lavz.js +2 -0
  44. package/dist/assets/main-D2BzpnUt.css +1 -0
  45. package/dist/assets/main-DWP-prNB.js +169 -0
  46. package/dist/assets/markdown-worker-bS5OgGO3.js +2 -0
  47. package/dist/assets/{markdownHeightCache-BhxqJOvf.js → markdownHeightCache-D9-B1wdY.js} +1 -1
  48. package/dist/assets/markdownTheme-DM5h1i18.js +1 -0
  49. package/dist/assets/mcpQueries-CfXrAkuU.js +1 -0
  50. package/dist/assets/miniChat-DgOrEQbN.js +2 -0
  51. package/dist/assets/mobile-Co_ZOHkZ.js +2 -0
  52. package/dist/assets/multirun-DelyUO6k.js +4 -0
  53. package/dist/assets/persistence-D0y7226-.js +3 -0
  54. package/dist/assets/pl-BCf5uLlK.js +15 -0
  55. package/dist/assets/platform-CurqO28D.js +6 -0
  56. package/dist/assets/{projectMeta-S1hJ7oBp.js → projectMeta-CPElzJ0n.js} +2 -2
  57. package/dist/assets/pt-BR-W09Q2pvn.js +15 -0
  58. package/dist/assets/{relay-image-stream-DM7atqJs.js → relay-image-stream-DrdVj99c.js} +1 -1
  59. package/dist/assets/renderElectronMiniChatApp-pOE93w86.js +2 -0
  60. package/dist/assets/renderMobileApp-F7ZSLcw8.js +28 -0
  61. package/dist/assets/runtime-fetch-Fs9ZV2V8.js +1 -0
  62. package/dist/assets/{runtimeConfig-CMkwoQ_X.js → runtimeConfig-DSS0KxG3.js} +1 -1
  63. package/dist/assets/runtimeEndpointReset-x2Wgx57R.js +149 -0
  64. package/dist/assets/sessionChangeSummary-BUGSYcHp.js +2 -0
  65. package/dist/assets/{sessionLookup-BrU3rFHJ.js → sessionLookup-Bss8M20i.js} +1 -1
  66. package/dist/assets/{sortable-tabs-strip-Fnfhf3K9.js → sortable-tabs-strip-CE7W7lJ9.js} +1 -1
  67. package/dist/assets/src-lS1keDVV.css +2 -0
  68. package/dist/assets/store-jaP79mqI.js +15 -0
  69. package/dist/assets/{terminalApi-xjqssKke.js → terminalApi-mDR2jXTo.js} +1 -1
  70. package/dist/assets/textarea-XD2oX_Ee.js +1 -0
  71. package/dist/assets/{tooltip-0T5jv0cu.js → tooltip-DYeQ_Hvy.js} +1 -1
  72. package/dist/assets/uk-BgFzz8m2.js +15 -0
  73. package/dist/assets/{url-_z7evzdK.js → url-CGbJbiJq.js} +1 -1
  74. package/dist/assets/{useAppFontEffects-C02YFyAv.js → useAppFontEffects-BAWHZ-t0.js} +64 -45
  75. package/dist/assets/{useAssistantUIStore-CMutVh9B.js → useAssistantUIStore-Bz4tRflF.js} +1 -1
  76. package/dist/assets/useDesktopWindowControlsLayout-hN_nLb7T.js +1 -0
  77. package/dist/assets/useEffectiveDirectory-Do9DQ453.js +1 -0
  78. package/dist/assets/{useFontPreferences-B1JYyzpK.js → useFontPreferences-Bjx8zkGM.js} +1 -1
  79. package/dist/assets/useMobileNavigationStore-BsY_gi_K.js +414 -0
  80. package/dist/assets/useSessionAutoCleanup-C4g5KmDf.js +2 -0
  81. package/dist/assets/useUIStore-syVmbuDA.js +1 -0
  82. package/dist/assets/{useWorkerHighlightedLines-C9z0ML1z.js → useWorkerHighlightedLines-B5QXxBok.js} +2 -2
  83. package/dist/assets/vendor-opencode-client-C12gfjag.js +12 -0
  84. package/dist/assets/{vendor-reactuses-core-BnW6GxJt.js → vendor-reactuses-core-Dq5ocTF8.js} +1 -1
  85. package/dist/assets/{vendor-yaml-DIcAK3EC.js → vendor-yaml-C9KlJAlj.js} +37 -37
  86. package/dist/assets/zh-CN-BhqSLgUY.js +15 -0
  87. package/dist/assets/zh-TW-BsaBgY-p.js +15 -0
  88. package/dist/index.html +12 -12
  89. package/dist/mini-chat.html +12 -12
  90. package/dist/mobile.html +12 -12
  91. package/package.json +3 -2
  92. package/server/index.js +423 -20
  93. package/server/lib/assistants/DOCUMENTATION.md +26 -21
  94. package/server/lib/assistants/assign.js +2 -1
  95. package/server/lib/assistants/contact-store.js +37 -19
  96. package/server/lib/assistants/contracts.js +11 -1
  97. package/server/lib/assistants/projection-history.test.js +454 -0
  98. package/server/lib/assistants/routes.js +11 -5
  99. package/server/lib/assistants/service.js +850 -294
  100. package/server/lib/assistants/service.test.js +588 -274
  101. package/server/lib/browser-provider/DOCUMENTATION.md +141 -0
  102. package/server/lib/browser-provider/contract.js +312 -0
  103. package/server/lib/browser-provider/host.js +421 -0
  104. package/server/lib/browser-provider/host.test.js +304 -0
  105. package/server/lib/browser-provider/routes.js +122 -0
  106. package/server/lib/browser-provider/routes.test.js +120 -0
  107. package/server/lib/browser-provider/selection-store.js +43 -0
  108. package/server/lib/browser-provider/selection-store.test.js +35 -0
  109. package/server/lib/conversations/DOCUMENTATION.md +5 -5
  110. package/server/lib/conversations/service.js +87 -57
  111. package/server/lib/conversations/service.test.js +132 -100
  112. package/server/lib/conversations/validation.js +11 -1
  113. package/server/lib/event-stream/DOCUMENTATION.md +3 -1
  114. package/server/lib/event-stream/directory-ws-bridge.js +13 -2
  115. package/server/lib/event-stream/global-hub.js +51 -5
  116. package/server/lib/event-stream/reasoning-projection.js +16 -1
  117. package/server/lib/event-stream/reasoning-projection.test.js +15 -0
  118. package/server/lib/event-stream/runtime.js +57 -20
  119. package/server/lib/event-stream/runtime.test.js +112 -0
  120. package/server/lib/llm/DOCUMENTATION.md +95 -84
  121. package/server/lib/llm/catalog.js +111 -45
  122. package/server/lib/llm/catalog.test.js +121 -59
  123. package/server/lib/llm/completions.js +41 -12
  124. package/server/lib/llm/completions.test.js +45 -4
  125. package/server/lib/llm/generate.js +516 -453
  126. package/server/lib/llm/generate.test.js +705 -484
  127. package/server/lib/llm/routes.js +8 -4
  128. package/server/lib/message-queue/DOCUMENTATION.md +5 -5
  129. package/server/lib/message-queue/opencode-adapter.js +191 -104
  130. package/server/lib/message-queue/opencode-adapter.test.js +328 -58
  131. package/server/lib/message-queue/runtime.js +15 -2
  132. package/server/lib/message-queue/runtime.test.js +6 -6
  133. package/server/lib/message-queue/worker.js +7 -1
  134. package/server/lib/notifications/DOCUMENTATION.md +3 -1
  135. package/server/lib/notifications/runtime.js +133 -31
  136. package/server/lib/notifications/runtime.test.js +103 -0
  137. package/server/lib/notifications/template-runtime.js +130 -38
  138. package/server/lib/notifications/template-runtime.test.js +96 -0
  139. package/server/lib/opencode/DOCUMENTATION.md +111 -16
  140. package/server/lib/opencode/agent-document.d.ts +28 -0
  141. package/server/lib/opencode/agent-document.js +280 -0
  142. package/server/lib/opencode/agent-document.test.js +137 -0
  143. package/server/lib/opencode/agents.js +96 -0
  144. package/server/lib/opencode/auth-state-runtime.js +5 -0
  145. package/server/lib/opencode/bootstrap-runtime.js +2 -0
  146. package/server/lib/opencode/config-entity-routes.js +117 -103
  147. package/server/lib/opencode/config-entity-routes.test.js +148 -10
  148. package/server/lib/opencode/config-hot-reload.integration.test.js +105 -0
  149. package/server/lib/opencode/ensure-cli.d.ts +8 -0
  150. package/server/lib/opencode/ensure-cli.js +238 -0
  151. package/server/lib/opencode/ensure-cli.test.js +119 -0
  152. package/server/lib/opencode/env-runtime.js +208 -111
  153. package/server/lib/opencode/env-runtime.test.js +211 -14
  154. package/server/lib/opencode/feature-routes-runtime.js +90 -5
  155. package/server/lib/opencode/feature-routes-runtime.test.js +25 -0
  156. package/server/lib/opencode/http-server-connections.js +98 -0
  157. package/server/lib/opencode/http-server-connections.test.js +321 -0
  158. package/server/lib/opencode/lifecycle.js +539 -95
  159. package/server/lib/opencode/lifecycle.test.js +698 -6
  160. package/server/lib/opencode/managed-capabilities-runtime.js +15 -2
  161. package/server/lib/opencode/managed-capabilities-runtime.test.js +1 -0
  162. package/server/lib/opencode/network-runtime.js +28 -16
  163. package/server/lib/opencode/network-runtime.test.js +68 -4
  164. package/server/lib/opencode/openchamber-routes.js +7 -1
  165. package/server/lib/opencode/opencode2-pin.js +139 -0
  166. package/server/lib/opencode/opencode2-pin.test.js +88 -0
  167. package/server/lib/opencode/opencode2-sidecar.e2e.test.js +326 -0
  168. package/server/lib/opencode/owned-runtime-upgrade.js +431 -0
  169. package/server/lib/opencode/owned-runtime-upgrade.test.js +160 -0
  170. package/server/lib/opencode/plugin-compatibility.js +15 -0
  171. package/server/lib/opencode/plugin-compatibility.test.js +21 -0
  172. package/server/lib/opencode/plugin-routes.js +3 -18
  173. package/server/lib/opencode/plugin-routes.test.js +9 -9
  174. package/server/lib/opencode/plugins.js +4 -3
  175. package/server/lib/opencode/plugins.test.js +12 -0
  176. package/server/lib/opencode/provider-catalog.js +58 -12
  177. package/server/lib/opencode/provider-catalog.test.js +48 -0
  178. package/server/lib/opencode/proxy.js +373 -28
  179. package/server/lib/opencode/proxy.test.js +353 -0
  180. package/server/lib/opencode/routes.js +333 -76
  181. package/server/lib/opencode/routes.test.js +315 -50
  182. package/server/lib/opencode/runtime-contract.js +401 -0
  183. package/server/lib/opencode/runtime-contract.test.js +214 -0
  184. package/server/lib/opencode/server-opencode-fetch.js +242 -0
  185. package/server/lib/opencode/server-opencode-fetch.test.js +130 -0
  186. package/server/lib/opencode/server-utils-runtime.js +35 -0
  187. package/server/lib/opencode/shared-service.integration.test.js +66 -0
  188. package/server/lib/opencode/shared-service.js +147 -0
  189. package/server/lib/opencode/shared-service.test.js +93 -0
  190. package/server/lib/opencode/shared.js +3 -3
  191. package/server/lib/opencode/shutdown-runtime.js +15 -6
  192. package/server/lib/opencode/shutdown-runtime.test.js +49 -1
  193. package/server/lib/opencode/skill-routes.js +26 -40
  194. package/server/lib/opencode/skill-routes.test.js +71 -7
  195. package/server/lib/opencode/skills.test.js +15 -0
  196. package/server/lib/opencode/startup-pipeline-runtime.js +4 -0
  197. package/server/lib/opencode/static-routes-runtime.js +3 -1
  198. package/server/lib/opencode/static-routes-runtime.test.js +33 -0
  199. package/server/lib/opencode/upgrade-screen.d.ts +30 -0
  200. package/server/lib/opencode/upgrade-screen.js +299 -0
  201. package/server/lib/opencode/upgrade-screen.test.js +196 -0
  202. package/server/lib/opencode/v1-migration-gate.js +157 -0
  203. package/server/lib/opencode/v1-migration-gate.test.js +111 -0
  204. package/server/lib/opencode/v2-client.js +60 -0
  205. package/server/lib/opencode/v2-plugin-host-shim/index.mjs +155 -0
  206. package/server/lib/opencode/v2-plugin-host-shim/package.json +4 -0
  207. package/server/lib/opencode/watcher.js +2 -1
  208. package/server/lib/opencode/watcher.test.js +1 -1
  209. package/server/lib/permission-auto-accept/DOCUMENTATION.md +5 -5
  210. package/server/lib/permission-auto-accept/runtime.js +14 -7
  211. package/server/lib/permission-auto-accept/runtime.test.js +27 -12
  212. package/server/lib/relay/reasoning-projection.e2e.test.ts +22 -7
  213. package/server/lib/scheduled-tasks/DOCUMENTATION.md +79 -39
  214. package/server/lib/scheduled-tasks/managed-tool-route.js +31 -1
  215. package/server/lib/scheduled-tasks/managed-tool-route.test.js +23 -0
  216. package/server/lib/scheduled-tasks/routes.js +27 -0
  217. package/server/lib/scheduled-tasks/routes.test.js +94 -0
  218. package/server/lib/scheduled-tasks/runtime.js +381 -310
  219. package/server/lib/scheduled-tasks/runtime.test.js +600 -309
  220. package/server/lib/session-goal/DOCUMENTATION.md +173 -22
  221. package/server/lib/session-goal/capability.js +57 -0
  222. package/server/lib/session-goal/capability.test.js +33 -0
  223. package/server/lib/session-goal/routes.js +240 -2
  224. package/server/lib/session-goal/routes.test.js +211 -0
  225. package/server/lib/session-goal/runtime.js +1617 -113
  226. package/server/lib/session-goal/runtime.test.js +1500 -70
  227. package/server/lib/session-index/DOCUMENTATION.md +18 -15
  228. package/server/lib/session-index/event-ingest.js +89 -16
  229. package/server/lib/session-index/event-ingest.test.js +73 -0
  230. package/server/lib/session-index/host-authority-snapshot.js +92 -0
  231. package/server/lib/session-index/routes.host-archive.test.js +201 -0
  232. package/server/lib/session-index/routes.js +63 -10
  233. package/server/lib/session-index/routes.test.js +8 -8
  234. package/server/lib/session-index/service.js +7 -1
  235. package/server/lib/session-index/sync-runtime.js +171 -41
  236. package/server/lib/session-index/sync-runtime.test.js +164 -9
  237. package/server/lib/session-metadata/DOCUMENTATION.md +96 -0
  238. package/server/lib/session-metadata/opencode-session-record.d.ts +57 -0
  239. package/server/lib/session-metadata/opencode-session-record.js +316 -0
  240. package/server/lib/session-metadata/opencode-session-record.test.js +242 -0
  241. package/server/lib/session-metadata/routes.js +197 -0
  242. package/server/lib/session-metadata/routes.test.js +156 -0
  243. package/server/lib/session-metadata/session-archive.d.ts +73 -0
  244. package/server/lib/session-metadata/session-archive.js +654 -0
  245. package/server/lib/session-metadata/session-archive.test.js +359 -0
  246. package/server/lib/session-metadata/session-metadata-store.d.ts +38 -0
  247. package/server/lib/session-metadata/session-metadata-store.js +422 -0
  248. package/server/lib/session-metadata/session-metadata-store.test.js +379 -0
  249. package/server/lib/session-metadata/session-projection.d.ts +41 -0
  250. package/server/lib/session-metadata/session-projection.js +279 -0
  251. package/server/lib/session-metadata/session-projection.test.js +64 -0
  252. package/server/lib/session-metadata/system-session.js +55 -0
  253. package/server/lib/session-metadata/system-session.test.js +55 -0
  254. package/server/lib/session-title/DOCUMENTATION.md +40 -7
  255. package/server/lib/session-title/native-runtime.test.js +167 -0
  256. package/server/lib/session-title/runtime.js +69 -44
  257. package/server/lib/session-title/session-access.js +46 -0
  258. package/server/lib/session-title/session-access.test.js +91 -0
  259. package/server/lib/session-turn-pages/DOCUMENTATION.md +12 -11
  260. package/server/lib/session-turn-pages/reconcile.service.js +1 -1
  261. package/server/lib/session-turn-pages/reconcile.service.test.js +16 -0
  262. package/server/lib/session-turn-pages/routes.js +123 -75
  263. package/server/lib/session-turn-pages/routes.test.js +566 -0
  264. package/server/lib/session-turn-pages/service.js +6 -2
  265. package/server/lib/session-turn-pages/service.test.js +34 -0
  266. package/server/lib/session-turn-pages/session-message-projection.d.ts +13 -0
  267. package/server/lib/session-turn-pages/session-message-projection.js +281 -0
  268. package/server/lib/small-model/DOCUMENTATION.md +101 -146
  269. package/server/lib/small-model/catalog.js +84 -54
  270. package/server/lib/small-model/catalog.test.js +111 -9
  271. package/server/lib/small-model/custom-api.js +68 -0
  272. package/server/lib/small-model/custom-api.test.js +64 -0
  273. package/server/lib/small-model/index.js +125 -241
  274. package/server/lib/small-model/resolve.js +35 -120
  275. package/server/lib/small-model/resolve.test.js +20 -110
  276. package/server/lib/small-model/routes.js +1 -3
  277. package/server/lib/small-model/summary-settings.test.js +157 -253
  278. package/server/opencode-proxy.test.js +63 -12
  279. package/dist/assets/AssistantView-BUveAgc4.js +0 -3
  280. package/dist/assets/Icon-BgdfPhNs.js +0 -1
  281. package/dist/assets/MarkdownRenderer-BbrbDH6-.js +0 -2
  282. package/dist/assets/MarkstreamRendererImpl-D2dsW5Lg.js +0 -3
  283. package/dist/assets/MobileDetailNavigation-B0aqKXd7.js +0 -1
  284. package/dist/assets/MobileSurface-DW7WfPsy.js +0 -2
  285. package/dist/assets/OverlayScrollbar-DrA0Vsg5.js +0 -2
  286. package/dist/assets/SettingsView-PkXIavr7.js +0 -25
  287. package/dist/assets/TerminalView-CDdzF4yi.js +0 -8
  288. package/dist/assets/appThemeRegistry-D5Yxg4YF.js +0 -1
  289. package/dist/assets/es-DA3MqOo0.js +0 -15
  290. package/dist/assets/fileMentionTouchSelection-DNeiqns-.js +0 -4
  291. package/dist/assets/fr-Dbz0CdIA.js +0 -13
  292. package/dist/assets/gitApi-DXyC4MiV.js +0 -7
  293. package/dist/assets/insertionBoundaries-KlOVrHHt.js +0 -1
  294. package/dist/assets/ja-DumanVQA.js +0 -15
  295. package/dist/assets/ko-C0IkiUjQ.js +0 -15
  296. package/dist/assets/main-BPS5ylib.js +0 -2
  297. package/dist/assets/main-Cpd9VWYs.js +0 -169
  298. package/dist/assets/main-qSeeJRW1.css +0 -1
  299. package/dist/assets/markdown-worker-CptoICmq.js +0 -2
  300. package/dist/assets/markdownTheme-DOfGg-A7.js +0 -1
  301. package/dist/assets/miniChat-B8_KLWiY.js +0 -2
  302. package/dist/assets/mobile-CtktKrXn.js +0 -2
  303. package/dist/assets/multirun-CYfP9Cfm.js +0 -4
  304. package/dist/assets/persistence-Ce3AnpEr.js +0 -3
  305. package/dist/assets/pl-B9No6MQp.js +0 -15
  306. package/dist/assets/platform-0w_Q9_ji.js +0 -2
  307. package/dist/assets/pt-BR-DyQ0WTDh.js +0 -15
  308. package/dist/assets/renderElectronMiniChatApp-iK14LWm8.js +0 -2
  309. package/dist/assets/renderMobileApp-DORLPWnb.js +0 -28
  310. package/dist/assets/runtime-fetch-zIalUnbb.js +0 -1
  311. package/dist/assets/runtimeEndpointReset-ChOxt-J7.js +0 -147
  312. package/dist/assets/sessionChangeSummary-NnxcqCTI.js +0 -2
  313. package/dist/assets/src-rS3zCcsC.css +0 -2
  314. package/dist/assets/store-5B_LDnLM.js +0 -15
  315. package/dist/assets/textarea-bHYxZtfH.js +0 -1
  316. package/dist/assets/uk-C_1KkqyP.js +0 -15
  317. package/dist/assets/useDesktopWindowControlsLayout-Dnr-jX0C.js +0 -1
  318. package/dist/assets/useEffectiveDirectory-CZLLyarc.js +0 -1
  319. package/dist/assets/useMobileNavigationStore-CoCiqNgm.js +0 -413
  320. package/dist/assets/useSessionAutoCleanup-xQyETQkG.js +0 -2
  321. package/dist/assets/useUIStore-Bxv3f23A.js +0 -1
  322. package/dist/assets/vendor-opencode-sdk-C07HQypa.js +0 -7
  323. package/dist/assets/zh-CN-uWILgBdt.js +0 -15
  324. package/dist/assets/zh-TW-MYfdvhbD.js +0 -15
  325. package/server/lib/small-model/call.js +0 -427
  326. package/server/lib/small-model/call.test.js +0 -382
  327. package/server/lib/small-model/opencode-session.js +0 -339
  328. package/server/lib/small-model/opencode-session.test.js +0 -177
@@ -0,0 +1,379 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { afterEach, describe, expect, it, vi } from 'vitest';
5
+
6
+ import { createSessionMetadataStore, mergeMetadataPatch } from './session-metadata-store.js';
7
+
8
+ const tempDirs = [];
9
+
10
+ const makeDataDir = () => {
11
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'openchamber-metadata-'));
12
+ tempDirs.push(dir);
13
+ return dir;
14
+ };
15
+
16
+ const readFile = (dataDir) => fs.readFileSync(path.join(dataDir, 'sessions-metadata.json'), 'utf8');
17
+
18
+ afterEach(() => {
19
+ while (tempDirs.length > 0) {
20
+ fs.rmSync(tempDirs.pop(), { recursive: true, force: true });
21
+ }
22
+ vi.restoreAllMocks();
23
+ });
24
+
25
+ describe('mergeMetadataPatch', () => {
26
+ it('merges nested objects key by key instead of replacing them', () => {
27
+ const current = { openchamber: { goal: { id: 'g1', status: 'active' }, assist: { recap: 'r' } } };
28
+ const merged = mergeMetadataPatch(current, { openchamber: { goal: { status: 'complete' } } });
29
+
30
+ expect(merged).toEqual({
31
+ openchamber: { goal: { id: 'g1', status: 'complete' }, assist: { recap: 'r' } },
32
+ });
33
+ // The input is untouched: callers keep whatever they already held.
34
+ expect(current.openchamber.goal.status).toBe('active');
35
+ });
36
+
37
+ it('deletes a key when its patch value is null', () => {
38
+ expect(mergeMetadataPatch({ a: 1, b: 2 }, { b: null })).toEqual({ a: 1 });
39
+ expect(mergeMetadataPatch({ openchamber: { goal: {}, assist: {} } }, { openchamber: { assist: null } }))
40
+ .toEqual({ openchamber: { goal: {} } });
41
+ });
42
+
43
+ it('replaces arrays and scalars rather than merging into them', () => {
44
+ expect(mergeMetadataPatch({ pins: ['a', 'b'] }, { pins: ['c'] })).toEqual({ pins: ['c'] });
45
+ expect(mergeMetadataPatch({ a: { nested: true } }, { a: 'flat' })).toEqual({ a: 'flat' });
46
+ });
47
+
48
+ it('treats a missing or non-object base as empty', () => {
49
+ expect(mergeMetadataPatch(undefined, { a: 1 })).toEqual({ a: 1 });
50
+ expect(mergeMetadataPatch('nope', { a: 1 })).toEqual({ a: 1 });
51
+ expect(mergeMetadataPatch({ a: 1 }, 'nope')).toEqual({ a: 1 });
52
+ });
53
+ });
54
+
55
+ describe('createSessionMetadataStore', () => {
56
+ it('starts empty when the file does not exist', async () => {
57
+ const store = createSessionMetadataStore({ dataDir: makeDataDir() });
58
+ await expect(store.getAll()).resolves.toEqual({});
59
+ await expect(store.get('ses_1')).resolves.toEqual({});
60
+ });
61
+
62
+ it('stores a patch, persists it, and reads it back in a fresh store', async () => {
63
+ const dataDir = makeDataDir();
64
+ const store = createSessionMetadataStore({ dataDir });
65
+
66
+ const merged = await store.setSessionMetadata('ses_1', { openchamber: { goal: { id: 'g1' } } });
67
+ expect(merged).toEqual({ openchamber: { goal: { id: 'g1' } } });
68
+ expect(JSON.parse(readFile(dataDir))).toEqual({ ses_1: { openchamber: { goal: { id: 'g1' } } } });
69
+
70
+ const reopened = createSessionMetadataStore({ dataDir });
71
+ await expect(reopened.get('ses_1')).resolves.toEqual({ openchamber: { goal: { id: 'g1' } } });
72
+ });
73
+
74
+ it('keeps a neighbouring namespace when another feature writes', async () => {
75
+ const store = createSessionMetadataStore({ dataDir: makeDataDir() });
76
+ await store.setSessionMetadata('ses_1', { openchamber: { assist: { recap: 'done' } } });
77
+ const merged = await store.setSessionMetadata('ses_1', { openchamber: { goal: { status: 'active' } } });
78
+
79
+ expect(merged).toEqual({ openchamber: { assist: { recap: 'done' }, goal: { status: 'active' } } });
80
+ });
81
+
82
+ it('deletes a key with a null patch value and drops a session that empties out', async () => {
83
+ const dataDir = makeDataDir();
84
+ const store = createSessionMetadataStore({ dataDir });
85
+ await store.setSessionMetadata('ses_1', { openchamber: { goal: { id: 'g1' } } });
86
+
87
+ await expect(store.setSessionMetadata('ses_1', { openchamber: null })).resolves.toEqual({});
88
+ await expect(store.getAll()).resolves.toEqual({});
89
+ expect(JSON.parse(readFile(dataDir))).toEqual({});
90
+ });
91
+
92
+ it('scopes metadata per session', async () => {
93
+ const store = createSessionMetadataStore({ dataDir: makeDataDir() });
94
+ await store.setSessionMetadata('ses_1', { a: 1 });
95
+ await store.setSessionMetadata('ses_2', { b: 2 });
96
+
97
+ await expect(store.getAll()).resolves.toEqual({ ses_1: { a: 1 }, ses_2: { b: 2 } });
98
+ });
99
+
100
+ it('rejects a blank session id and a non-object patch', async () => {
101
+ const store = createSessionMetadataStore({ dataDir: makeDataDir() });
102
+ await expect(store.setSessionMetadata(' ', { a: 1 })).rejects.toThrow(/session id is required/);
103
+ await expect(store.setSessionMetadata('ses_1', 'nope')).rejects.toThrow(/must be an object/);
104
+ await expect(store.setSessionMetadata('ses_1', ['a'])).rejects.toThrow(/must be an object/);
105
+ });
106
+
107
+ it('writes atomically: the visible file is never a partial payload', async () => {
108
+ const dataDir = makeDataDir();
109
+ const seen = [];
110
+ const fsPromises = {
111
+ ...fs.promises,
112
+ writeFile: async (target, payload, encoding) => {
113
+ // The visible file must still be the previous one at this point.
114
+ seen.push(fs.existsSync(path.join(dataDir, 'sessions-metadata.json')) ? readFile(dataDir) : null);
115
+ return fs.promises.writeFile(target, payload, encoding);
116
+ },
117
+ };
118
+ const store = createSessionMetadataStore({ dataDir, fsPromises });
119
+
120
+ await store.setSessionMetadata('ses_1', { a: 1 });
121
+ await store.setSessionMetadata('ses_2', { b: 2 });
122
+
123
+ expect(seen).toEqual([null, JSON.stringify({ ses_1: { a: 1 } })]);
124
+ expect(JSON.parse(readFile(dataDir))).toEqual({ ses_1: { a: 1 }, ses_2: { b: 2 } });
125
+ });
126
+
127
+ it('refuses corrupt JSON as empty success and does not overwrite the file', async () => {
128
+ const dataDir = makeDataDir();
129
+ const corruptPath = path.join(dataDir, 'sessions-metadata.json');
130
+ fs.writeFileSync(corruptPath, '{ not json', 'utf8');
131
+ vi.spyOn(console, 'warn').mockImplementation(() => {});
132
+
133
+ const store = createSessionMetadataStore({ dataDir });
134
+ await expect(store.getAll()).rejects.toThrow(/unavailable|corrupt/i);
135
+ await expect(store.setSessionMetadata('ses_1', { a: 1 })).rejects.toThrow(/unavailable|corrupt/i);
136
+ expect(fs.readFileSync(corruptPath, 'utf8')).toBe('{ not json');
137
+ expect(store.isLoaded()).toBe(false);
138
+ expect(store.getSnapshotSync()).toBeNull();
139
+ });
140
+
141
+ it('drops entries that are not metadata objects', async () => {
142
+ const dataDir = makeDataDir();
143
+ fs.writeFileSync(
144
+ path.join(dataDir, 'sessions-metadata.json'),
145
+ JSON.stringify({ ses_ok: { a: 1 }, ses_list: ['a'], ses_text: 'nope', ses_null: null }),
146
+ 'utf8',
147
+ );
148
+ const store = createSessionMetadataStore({ dataDir });
149
+ await expect(store.getAll()).resolves.toEqual({ ses_ok: { a: 1 } });
150
+ });
151
+
152
+ it('refuses to write when the file could not be read, so unknown state is never overwritten', async () => {
153
+ const dataDir = makeDataDir();
154
+ fs.writeFileSync(path.join(dataDir, 'sessions-metadata.json'), '{}', 'utf8');
155
+ const unreadable = Object.assign(new Error('EACCES'), { code: 'EACCES' });
156
+ const fsPromises = {
157
+ ...fs.promises,
158
+ readFile: async () => { throw unreadable; },
159
+ writeFile: async () => { throw new Error('must not write'); },
160
+ };
161
+ vi.spyOn(console, 'warn').mockImplementation(() => {});
162
+
163
+ const store = createSessionMetadataStore({ dataDir, fsPromises });
164
+ await expect(store.setSessionMetadata('ses_1', { a: 1 })).rejects.toThrow(/unavailable/);
165
+ expect(readFile(dataDir)).toBe('{}');
166
+ });
167
+
168
+ it('does not publish uncommitted drafts while persist is blocked (set)', async () => {
169
+ const dataDir = makeDataDir();
170
+ let releaseWrite;
171
+ const writeGate = new Promise((resolve) => { releaseWrite = resolve; });
172
+ const fsPromises = {
173
+ ...fs.promises,
174
+ writeFile: async (target, payload, encoding) => {
175
+ await writeGate;
176
+ return fs.promises.writeFile(target, payload, encoding);
177
+ },
178
+ };
179
+ const store = createSessionMetadataStore({ dataDir, fsPromises });
180
+ const pending = store.setSessionMetadata('ses_1', { a: 1 });
181
+ // Concurrent readers must still see committed empty — not the in-flight draft.
182
+ await expect(store.get('ses_1')).resolves.toEqual({});
183
+ expect(store.getSnapshotSync()).toEqual({});
184
+ releaseWrite();
185
+ await expect(pending).resolves.toEqual({ a: 1 });
186
+ await expect(store.get('ses_1')).resolves.toEqual({ a: 1 });
187
+ });
188
+
189
+ it('does not publish uncommitted deletes while persist is blocked (remove)', async () => {
190
+ const dataDir = makeDataDir();
191
+ const storeWarm = createSessionMetadataStore({ dataDir });
192
+ await storeWarm.setSessionMetadata('ses_1', { a: 1 });
193
+
194
+ let releaseWrite = null;
195
+ const fsPromises = {
196
+ ...fs.promises,
197
+ writeFile: async (target, payload, encoding) => {
198
+ if (releaseWrite) await new Promise((resolve) => { releaseWrite = resolve; });
199
+ return fs.promises.writeFile(target, payload, encoding);
200
+ },
201
+ };
202
+ const store = createSessionMetadataStore({ dataDir, fsPromises });
203
+ await store.load();
204
+ // Arm the gate only for the remove persist.
205
+ releaseWrite = () => {};
206
+ let unlock;
207
+ const gate = new Promise((resolve) => { unlock = resolve; });
208
+ fsPromises.writeFile = async (target, payload, encoding) => {
209
+ await gate;
210
+ return fs.promises.writeFile(target, payload, encoding);
211
+ };
212
+ const pending = store.removeSession('ses_1');
213
+ await expect(store.get('ses_1')).resolves.toEqual({ a: 1 });
214
+ unlock();
215
+ await expect(pending).resolves.toBe(true);
216
+ await expect(store.get('ses_1')).resolves.toEqual({});
217
+ });
218
+
219
+ it('keeps committed entries when persist fails (set never published)', async () => {
220
+ const dataDir = makeDataDir();
221
+ const storeOk = createSessionMetadataStore({ dataDir });
222
+ await storeOk.setSessionMetadata('ses_1', { a: 1 });
223
+
224
+ const fsPromises = { ...fs.promises, writeFile: async () => { throw new Error('disk full'); } };
225
+ const store = createSessionMetadataStore({ dataDir, fsPromises });
226
+ await expect(store.setSessionMetadata('ses_1', { b: 2 })).rejects.toThrow('disk full');
227
+ await expect(store.get('ses_1')).resolves.toEqual({ a: 1 });
228
+ });
229
+
230
+ it('forgets a session on request', async () => {
231
+ const dataDir = makeDataDir();
232
+ const store = createSessionMetadataStore({ dataDir });
233
+ await store.setSessionMetadata('ses_1', { a: 1 });
234
+
235
+ await expect(store.removeSession('ses_1')).resolves.toBe(true);
236
+ await expect(store.removeSession('ses_1')).resolves.toBe(false);
237
+ expect(JSON.parse(readFile(dataDir))).toEqual({});
238
+ });
239
+
240
+ it('serializes concurrent writes so neighboring keys are not lost', async () => {
241
+ const store = createSessionMetadataStore({ dataDir: makeDataDir() });
242
+ await Promise.all([
243
+ store.setSessionMetadata('ses_1', { openchamber: { goal: { id: 'g1' } } }),
244
+ store.setSessionMetadata('ses_1', { openchamber: { assist: { recap: 'a' } } }),
245
+ ]);
246
+ await expect(store.get('ses_1')).resolves.toEqual({
247
+ openchamber: { goal: { id: 'g1' }, assist: { recap: 'a' } },
248
+ });
249
+ });
250
+
251
+ it('protects Host archive from generic metadata null ancestor deletes', async () => {
252
+ const store = createSessionMetadataStore({ dataDir: makeDataDir() });
253
+ await store.setSessionMetadata('ses_1', { openchamber: { archive: { archivedAt: 9 } } }, { allowArchive: true });
254
+ await store.setSessionMetadata('ses_1', { openchamber: { goal: { id: 'g1' } } });
255
+ await expect(store.get('ses_1')).resolves.toEqual({
256
+ openchamber: { archive: { archivedAt: 9 }, goal: { id: 'g1' } },
257
+ });
258
+ await store.setSessionMetadata('ses_1', { openchamber: null });
259
+ await expect(store.get('ses_1')).resolves.toEqual({
260
+ openchamber: { archive: { archivedAt: 9 } },
261
+ });
262
+ await store.setSessionMetadata('ses_1', { openchamber: { archive: { archivedAt: 1 } } });
263
+ await expect(store.get('ses_1')).resolves.toEqual({
264
+ openchamber: { archive: { archivedAt: 9 } },
265
+ });
266
+ });
267
+
268
+ it('does not treat a failed load as empty success on get/getAll', async () => {
269
+ const dataDir = makeDataDir();
270
+ fs.writeFileSync(path.join(dataDir, 'sessions-metadata.json'), '{}', 'utf8');
271
+ const unreadable = Object.assign(new Error('EACCES'), { code: 'EACCES' });
272
+ const fsPromises = {
273
+ ...fs.promises,
274
+ readFile: async () => { throw unreadable; },
275
+ };
276
+ vi.spyOn(console, 'warn').mockImplementation(() => {});
277
+ const store = createSessionMetadataStore({ dataDir, fsPromises });
278
+ await expect(store.get('ses_1')).rejects.toThrow(/unavailable|could not be read|EACCES/i);
279
+ await expect(store.getAll()).rejects.toThrow(/unavailable|could not be read|EACCES/i);
280
+ expect(store.getSnapshotSync()).toBeNull();
281
+ });
282
+
283
+ it('mutateSessionMetadata commits only when decide returns ok with a patch', async () => {
284
+ const store = createSessionMetadataStore({ dataDir: makeDataDir() });
285
+ await store.setSessionMetadata('ses_1', {
286
+ openchamber: { goal: { id: 'g1', status: 'active', executionGeneration: 2 }, assist: { recap: 'keep' } },
287
+ });
288
+
289
+ const rejected = await store.mutateSessionMetadata('ses_1', (current) => {
290
+ const gen = current?.openchamber?.goal?.executionGeneration;
291
+ if (gen !== 2) return { ok: false, reason: 'generation_mismatch' };
292
+ return {
293
+ ok: false,
294
+ reason: 'status_not_active',
295
+ };
296
+ });
297
+ expect(rejected).toEqual({
298
+ committed: false,
299
+ reason: 'status_not_active',
300
+ metadata: {
301
+ openchamber: { goal: { id: 'g1', status: 'active', executionGeneration: 2 }, assist: { recap: 'keep' } },
302
+ },
303
+ });
304
+ await expect(store.get('ses_1')).resolves.toEqual({
305
+ openchamber: { goal: { id: 'g1', status: 'active', executionGeneration: 2 }, assist: { recap: 'keep' } },
306
+ });
307
+
308
+ const accepted = await store.mutateSessionMetadata('ses_1', (current) => {
309
+ if (current?.openchamber?.goal?.executionGeneration !== 2) {
310
+ return { ok: false, reason: 'generation_mismatch' };
311
+ }
312
+ return {
313
+ ok: true,
314
+ patch: { openchamber: { goal: { status: 'paused', executionGeneration: 3 } } },
315
+ };
316
+ });
317
+ expect(accepted.committed).toBe(true);
318
+ expect(accepted.metadata.openchamber.goal).toEqual({
319
+ id: 'g1',
320
+ status: 'paused',
321
+ executionGeneration: 3,
322
+ });
323
+ expect(accepted.metadata.openchamber.assist).toEqual({ recap: 'keep' });
324
+ });
325
+
326
+ it('mutateSessionMetadata does not publish drafts while persist is blocked', async () => {
327
+ const dataDir = makeDataDir();
328
+ await createSessionMetadataStore({ dataDir }).setSessionMetadata('ses_1', {
329
+ openchamber: { goal: { id: 'g1', status: 'active', executionGeneration: 1 } },
330
+ });
331
+
332
+ let unlock;
333
+ const gate = new Promise((resolve) => { unlock = resolve; });
334
+ const fsPromises = {
335
+ ...fs.promises,
336
+ writeFile: async (target, payload, encoding) => {
337
+ await gate;
338
+ return fs.promises.writeFile(target, payload, encoding);
339
+ },
340
+ };
341
+ const store = createSessionMetadataStore({ dataDir, fsPromises });
342
+ await store.load();
343
+
344
+ const pending = store.mutateSessionMetadata('ses_1', () => ({
345
+ ok: true,
346
+ patch: { openchamber: { goal: { status: 'paused', executionGeneration: 2 } } },
347
+ }));
348
+ await expect(store.get('ses_1')).resolves.toEqual({
349
+ openchamber: { goal: { id: 'g1', status: 'active', executionGeneration: 1 } },
350
+ });
351
+ expect(store.getSnapshotSync()?.ses_1?.openchamber?.goal?.status).toBe('active');
352
+ unlock();
353
+ await expect(pending).resolves.toMatchObject({
354
+ committed: true,
355
+ metadata: { openchamber: { goal: { status: 'paused', executionGeneration: 2 } } },
356
+ });
357
+ });
358
+
359
+ it('mutateSessionMetadata preserves Host archive and serializes with setSessionMetadata', async () => {
360
+ const store = createSessionMetadataStore({ dataDir: makeDataDir() });
361
+ await store.setSessionMetadata('ses_1', { openchamber: { archive: { archivedAt: 42 } } }, { allowArchive: true });
362
+
363
+ const [mutated] = await Promise.all([
364
+ store.mutateSessionMetadata('ses_1', () => ({
365
+ ok: true,
366
+ patch: { openchamber: { goal: { id: 'g1', status: 'active', executionGeneration: 0 } } },
367
+ })),
368
+ store.setSessionMetadata('ses_1', { openchamber: { assist: { recap: 'a' } } }),
369
+ ]);
370
+ expect(mutated.committed).toBe(true);
371
+ await expect(store.get('ses_1')).resolves.toEqual({
372
+ openchamber: {
373
+ archive: { archivedAt: 42 },
374
+ goal: { id: 'g1', status: 'active', executionGeneration: 0 },
375
+ assist: { recap: 'a' },
376
+ },
377
+ });
378
+ });
379
+ });
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Type surface for session-projection.js (consumed by VS Code Extension Host facades).
3
+ * Runtime implementation stays in the .js module.
4
+ */
5
+
6
+ export const HOST_ARCHIVE_METADATA_KEY: string;
7
+
8
+ export function normalizeSessionEventType(type: unknown): string;
9
+
10
+ export function isSessionLifecycleEventType(type: unknown): boolean;
11
+
12
+ export function extractSessionInfoFromPayload(
13
+ payload: unknown,
14
+ ): { id: string; [key: string]: unknown } | null;
15
+
16
+ export function resolveSessionDirectory(session: unknown): string | null;
17
+
18
+ export function readHostArchivedAt(metadata: unknown): number | null;
19
+
20
+ export function resolveProjectedArchivedAt(
21
+ upstreamArchived: unknown,
22
+ hostArchivedAt: unknown,
23
+ ): number | null | undefined;
24
+
25
+ export function isSessionArchived(session: unknown): boolean;
26
+
27
+ export function projectSessionWithHostMetadata(
28
+ session: unknown,
29
+ hostMetadata: unknown,
30
+ ): unknown;
31
+
32
+ export function projectSessionWithStoredMap(
33
+ session: unknown,
34
+ storedBySessionId: unknown,
35
+ ): unknown;
36
+
37
+ export function projectSessionLifecyclePayload(
38
+ payload: unknown,
39
+ readHostMetadata: (sessionId: string) => unknown,
40
+ options?: { hostReady?: boolean },
41
+ ): unknown;