@aiworker/web 1.22.0 → 1.22.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. package/README.md +4 -4
  2. package/bin/cli.js +7 -4
  3. package/bin/cli.test.js +165 -73
  4. package/bin/lib/cli-api-target.js +2 -2
  5. package/bin/lib/cli-args.js +119 -119
  6. package/bin/lib/cli-lifecycle.js +9 -9
  7. package/bin/lib/cli-network.js +3 -3
  8. package/bin/lib/cli-paths.js +3 -3
  9. package/bin/lib/cli-ports.js +2 -2
  10. package/bin/lib/cli-process.js +4 -4
  11. package/bin/lib/cli-startup.js +64 -15
  12. package/bin/lib/cli-tunnel-profiles.js +1 -1
  13. package/bin/lib/cli-tunnel-utils.js +2 -2
  14. package/bin/lib/commands-connect-url.js +19 -19
  15. package/bin/lib/commands-lifecycle.js +27 -27
  16. package/bin/lib/commands-logs.js +5 -5
  17. package/bin/lib/commands-models.js +1 -1
  18. package/bin/lib/commands-projects.js +1 -1
  19. package/bin/lib/commands-schedule.js +1 -1
  20. package/bin/lib/commands-serve.js +29 -29
  21. package/bin/lib/commands-session.js +1 -1
  22. package/bin/lib/commands-startup.js +45 -10
  23. package/bin/lib/commands-status.js +1 -1
  24. package/bin/lib/commands-tunnel.js +40 -40
  25. package/bin/lib/commands-update.js +1 -1
  26. package/bin/lib/commands-update.test.js +6 -6
  27. package/dist/assets/{CodeMirrorCommentWidgets-B3u7UIcE.js → CodeMirrorCommentWidgets-CSICpWQD.js} +1 -1
  28. package/dist/assets/{DiffView-DluiRSla.js → DiffView-hDBKesA_.js} +3 -3
  29. package/dist/assets/DirtyBranchSwitchDialog-C22HdWj4.js +1 -0
  30. package/dist/assets/FilesView-CdWzeOp9.js +17 -0
  31. package/dist/assets/GitView-VQQkYuUw.js +6 -0
  32. package/dist/assets/{JsonTreeView-B0BdZEHG.js → JsonTreeView-6lrhwD3q.js} +1 -1
  33. package/dist/assets/LinearIssuesView-Ba6Q9569.js +1 -0
  34. package/dist/assets/{MarkdownImageGallery-ClOvuZxC.js → MarkdownImageGallery-Czv_mhvS.js} +1 -1
  35. package/dist/assets/MarkdownRendererImpl-BrMcswiy.js +12 -0
  36. package/dist/assets/{OnboardingScreen-D2DG7K6b.js → OnboardingScreen-ChxQoAkx.js} +1 -1
  37. package/dist/assets/{PatchDiff-DvfqDql7.js → PatchDiff-BzcZPlOq.js} +1 -1
  38. package/dist/assets/{PierreDiffViewer-B7m3f0d7.js → PierreDiffViewer-BchBtZlp.js} +2 -2
  39. package/dist/assets/PlanView-DyDt_nZ_.js +5 -0
  40. package/dist/assets/SettingsView-BKf5xBsP.js +28 -0
  41. package/dist/assets/{SettingsWindow-i45U1Cy1.js → SettingsWindow-DDQYaKWQ.js} +1 -1
  42. package/dist/assets/{ToolOutputDialog-BTwyh5OF.js → ToolOutputDialog-iYF8Y2bz.js} +6 -6
  43. package/dist/assets/ToolPartDiffPreview-CdjbOVMM.js +8 -0
  44. package/dist/assets/{VirtualizedFileDiff-DD8lDVej.js → VirtualizedFileDiff-fFFm2QgH.js} +1 -1
  45. package/dist/assets/{WalkthroughView-egQgxel3.js → WalkthroughView-DOeCsMju.js} +2 -2
  46. package/dist/assets/{computeVirtualFileMetrics-BMIRgMHv.js → computeVirtualFileMetrics-CzgLum_K.js} +2 -2
  47. package/dist/assets/{contextPanelEmbeddedChat-C3fjDbdg.js → contextPanelEmbeddedChat-C0ZLAepL.js} +1 -1
  48. package/dist/assets/{de-C1P6X5Rs.js → de-B5JaA3SA.js} +6 -5
  49. package/dist/assets/{es-CDgaF1_t.js → es-EPIH88ii.js} +6 -5
  50. package/dist/assets/{fr-Bgxqvvz_.js → fr-CAMfxUdZ.js} +6 -5
  51. package/dist/assets/{index-CODwDsU_.js → index-Bl3LSbjn.js} +1 -1
  52. package/dist/assets/index-DF5kMP-i.js +39 -0
  53. package/dist/assets/index-Dl3xbAB_.css +1 -0
  54. package/dist/assets/{isDiffPlainText-BqayB8d3.js → isDiffPlainText-Dx-dB_8l.js} +1 -1
  55. package/dist/assets/{isFilePlainText-QfoiKJNY.js → isFilePlainText-CWFPwmnU.js} +1 -1
  56. package/dist/assets/{ja-BDRrEcNP.js → ja-CifOE1VN.js} +7 -6
  57. package/dist/assets/{ko-Ba8sQV79.js → ko-BBDyAyYQ.js} +7 -6
  58. package/dist/assets/{main-C5DVOxc6.js → main-DnBAoktx.js} +2 -2
  59. package/dist/assets/main-MhSaOZoB.js +930 -0
  60. package/dist/assets/{markdownCore-CZwzz5gw.js → markdownCore-BrBwOOMn.js} +2 -2
  61. package/dist/assets/{miniChat-DUJ4irZc.js → miniChat-BKyvLseN.js} +2 -2
  62. package/dist/assets/{mobile-CcaxB0n4.js → mobile-DKjeFgMN.js} +2 -2
  63. package/dist/assets/{patchFileDiff-yNfWXN4E.js → patchFileDiff-o8ms1me8.js} +1 -1
  64. package/dist/assets/pl-DgEHYfFM.js +16 -0
  65. package/dist/assets/{pt-BR-DIs6ElwV.js → pt-BR-DuWHojUw.js} +6 -5
  66. package/dist/assets/{renderElectronMiniChatApp-BcKLHXKe.js → renderElectronMiniChatApp-CDgBwwCS.js} +2 -2
  67. package/dist/assets/renderMobileApp-DJIKIK1r.js +25 -0
  68. package/dist/assets/runtimeEndpointReset-CYJ9O_xX.js +17 -0
  69. package/dist/assets/{scheduledTasksApi-DLW0mkQK.js → scheduledTasksApi-D8yamh1b.js} +1 -1
  70. package/dist/assets/{shikiHighlight-DYOWuY65.js → shikiHighlight-TEQCmzW8.js} +1 -1
  71. package/dist/assets/tr-D5m2yIWL.js +7 -0
  72. package/dist/assets/{uk-ZrCNjM7Y.js → uk-D_q60oog.js} +6 -5
  73. package/dist/assets/{useAppFontEffects-CjrntdL0.js → useAppFontEffects-D7sNpuL2.js} +161 -190
  74. package/dist/assets/useInlineCommentController-Brz_cLcQ.js +2 -0
  75. package/dist/assets/{useRootScrollLock-BHYPkrLv.js → useRootScrollLock-lXEnWlaU.js} +1 -1
  76. package/dist/assets/{vendor-codemirror-language-data-DFZik9R2.js → vendor-codemirror-language-data-Dp3KMRQG.js} +2 -2
  77. package/dist/assets/vendor-zod-CK21ihK-.js +39 -0
  78. package/dist/assets/{web-components-Bhg83tjf.js → web-components-_mNEMjFY.js} +1 -1
  79. package/dist/assets/{zh-CN-iv_AV4EC.js → zh-CN-D8QvsVeg.js} +6 -5
  80. package/dist/assets/{zh-TW-CzEUk38j.js → zh-TW-B9t7rQQO.js} +6 -5
  81. package/dist/index.html +22 -22
  82. package/dist/mini-chat.html +7 -7
  83. package/dist/mobile.html +5 -5
  84. package/package.json +3 -3
  85. package/server/index.js +118 -85
  86. package/server/lib/agent-memory/actions.js +2 -2
  87. package/server/lib/agent-memory/feature-flag.js +1 -1
  88. package/server/lib/agent-memory/feature-flag.test.js +8 -8
  89. package/server/lib/agent-memory/routes.js +2 -2
  90. package/server/lib/agent-tool/runtime.js +37 -54
  91. package/server/lib/agent-tool/runtime.test.js +59 -59
  92. package/server/lib/browser-control/broker.js +3 -3
  93. package/server/lib/browser-control/broker.test.js +1 -1
  94. package/server/lib/changelog/update-notes.js +82 -0
  95. package/server/lib/changelog/update-notes.test.js +59 -0
  96. package/server/lib/client-auth/remote-clients.test.js +5 -5
  97. package/server/lib/context-obligatory/runtime.js +7 -7
  98. package/server/lib/context-obligatory/runtime.test.js +5 -5
  99. package/server/lib/dev-servers/parse.js +2 -2
  100. package/server/lib/dev-servers/parse.test.js +2 -2
  101. package/server/lib/dev-servers/routes.js +1 -1
  102. package/server/lib/dev-tunnel/DOCUMENTATION.md +13 -4
  103. package/server/lib/dev-tunnel/client.js +1 -1
  104. package/server/lib/dev-tunnel/runtime.js +5 -5
  105. package/server/lib/dev-tunnel/tunnel.test.js +21 -1
  106. package/server/lib/dictation/local/model-catalog.js +1 -1
  107. package/server/lib/dictation/local/worker-process.js +2 -2
  108. package/server/lib/event-stream/directory-ws-bridge.js +1 -1
  109. package/server/lib/event-stream/global-ws-bridge.js +1 -1
  110. package/server/lib/event-stream/protocol.test.js +4 -4
  111. package/server/lib/event-stream/runtime.test.js +6 -6
  112. package/server/lib/fs/DOCUMENTATION.md +2 -0
  113. package/server/lib/fs/routes.js +37 -26
  114. package/server/lib/fs/routes.test.js +98 -21
  115. package/server/lib/git/DOCUMENTATION.md +3 -1
  116. package/server/lib/git/identity-storage.js +1 -1
  117. package/server/lib/git/issue-2746-longpaths.test.js +4 -4
  118. package/server/lib/git/routes.js +17 -1
  119. package/server/lib/git/service.js +116 -26
  120. package/server/lib/git/service.test.js +174 -3
  121. package/server/lib/github/auth.js +8 -8
  122. package/server/lib/github/pr-status.js +1 -1
  123. package/server/lib/github/routes.js +2 -2
  124. package/server/lib/inherited-env.js +1 -1
  125. package/server/lib/inherited-env.test.js +2 -2
  126. package/server/lib/linear/auth.js +8 -8
  127. package/server/lib/linear/auth.test.js +24 -24
  128. package/server/lib/linear/issues.test.js +6 -6
  129. package/server/lib/linear/mapping.test.js +4 -4
  130. package/server/lib/linear/oauth.js +2 -2
  131. package/server/lib/linear/oauth.test.js +14 -14
  132. package/server/lib/linear/routes.js +5 -5
  133. package/server/lib/linear/routes.test.js +16 -16
  134. package/server/lib/linear/status-runtime.test.js +9 -9
  135. package/server/lib/linear/status.js +1 -1
  136. package/server/lib/linear/status.test.js +15 -15
  137. package/server/lib/linear/teams.test.js +4 -4
  138. package/server/lib/magic-prompts/routes.js +2 -2
  139. package/server/lib/mcp-reconnect/DOCUMENTATION.md +55 -0
  140. package/server/lib/mcp-reconnect/runtime.js +122 -0
  141. package/server/lib/mcp-reconnect/runtime.test.js +140 -0
  142. package/server/lib/message-queue/DOCUMENTATION.md +158 -0
  143. package/server/lib/message-queue/runtime.js +870 -0
  144. package/server/lib/message-queue/runtime.test.js +482 -0
  145. package/server/lib/notifications/apns-runtime.js +17 -17
  146. package/server/lib/notifications/apns-runtime.test.js +11 -11
  147. package/server/lib/notifications/emitter-runtime.js +1 -1
  148. package/server/lib/notifications/emitter-runtime.test.js +1 -1
  149. package/server/lib/notifications/push-runtime.js +7 -7
  150. package/server/lib/notifications/routes.js +1 -1
  151. package/server/lib/notifications/runtime.js +1 -1
  152. package/server/lib/openchamber-control/action-resolution.test.js +10 -10
  153. package/server/lib/openchamber-control/actions.js +24 -24
  154. package/server/lib/openchamber-control/error.js +4 -4
  155. package/server/lib/openchamber-control/routes.js +2 -2
  156. package/server/lib/openchamber-control/routes.test.js +5 -5
  157. package/server/lib/openchamber-control/screenshots.js +1 -1
  158. package/server/lib/openchamber-control/screenshots.test.js +1 -1
  159. package/server/lib/openchamber-control/service.js +50 -50
  160. package/server/lib/openchamber-control/service.test.js +5 -5
  161. package/server/lib/openchamber-sessions/routes.js +124 -22
  162. package/server/lib/openchamber-sessions/routes.test.js +99 -11
  163. package/server/lib/opencode/DOCUMENTATION.md +13 -5
  164. package/server/lib/opencode/auth.js +1 -1
  165. package/server/lib/opencode/bootstrap-runtime.js +6 -6
  166. package/server/lib/opencode/cli-options.js +8 -8
  167. package/server/lib/opencode/config-paths.test.js +116 -0
  168. package/server/lib/opencode/core-routes.js +8 -7
  169. package/server/lib/opencode/core-routes.test.js +11 -11
  170. package/server/lib/opencode/env-config.js +5 -5
  171. package/server/lib/opencode/env-config.test.js +7 -7
  172. package/server/lib/opencode/env-runtime.js +10 -10
  173. package/server/lib/opencode/env-runtime.test.js +18 -18
  174. package/server/lib/opencode/feature-routes-runtime.js +17 -12
  175. package/server/lib/opencode/hmr-state-runtime.js +2 -2
  176. package/server/lib/opencode/hmr-state-runtime.test.js +1 -1
  177. package/server/lib/opencode/input-history-scope.js +14 -0
  178. package/server/lib/opencode/lifecycle.js +8 -8
  179. package/server/lib/opencode/lifecycle.test.js +4 -4
  180. package/server/lib/opencode/managed-plugin-config.js +35 -0
  181. package/server/lib/opencode/managed-process-registry.js +3 -3
  182. package/server/lib/opencode/mcp-oauth-callback.test.js +2 -2
  183. package/server/lib/opencode/openchamber-routes.js +15 -15
  184. package/server/lib/opencode/openchamber-routes.test.js +11 -11
  185. package/server/lib/opencode/plugins.js +2 -2
  186. package/server/lib/opencode/plugins.test.js +1 -1
  187. package/server/lib/opencode/project-icon-routes.js +2 -2
  188. package/server/lib/opencode/project-icon-routes.test.js +1 -1
  189. package/server/lib/opencode/providers.js +44 -2
  190. package/server/lib/opencode/providers.test.js +131 -4
  191. package/server/lib/opencode/proxy.js +2 -2
  192. package/server/lib/opencode/pwa-manifest-routes.js +1 -1
  193. package/server/lib/opencode/restart-session-recovery.test.js +1 -1
  194. package/server/lib/opencode/routes-upgrade.test.js +4 -4
  195. package/server/lib/opencode/routes.js +14 -14
  196. package/server/lib/opencode/server-startup-runtime.js +6 -6
  197. package/server/lib/opencode/session-runtime.js +3 -3
  198. package/server/lib/opencode/session-runtime.test.js +6 -6
  199. package/server/lib/opencode/settings-helpers.js +31 -3
  200. package/server/lib/opencode/settings-helpers.test.js +189 -12
  201. package/server/lib/opencode/settings-runtime.js +2 -2
  202. package/server/lib/opencode/settings-runtime.test.js +29 -0
  203. package/server/lib/opencode/shared.js +5 -2
  204. package/server/lib/opencode/shared.test.js +7 -7
  205. package/server/lib/opencode/shutdown-runtime.js +2 -0
  206. package/server/lib/opencode/skill-routes.js +2 -1
  207. package/server/lib/opencode/snippets.js +1 -2
  208. package/server/lib/opencode/startup-performance.js +1 -1
  209. package/server/lib/opencode/startup-performance.test.js +6 -6
  210. package/server/lib/opencode/static-routes-runtime.js +8 -8
  211. package/server/lib/opencode/static-routes-runtime.test.js +7 -7
  212. package/server/lib/opencode/upgrade-capability.js +2 -2
  213. package/server/lib/opencode/upgrade-capability.test.js +3 -3
  214. package/server/lib/package-manager.js +17 -42
  215. package/server/lib/package-manager.test.js +19 -19
  216. package/server/lib/permission-auto-accept/runtime.js +1 -1
  217. package/server/lib/project-context/routes.js +1 -1
  218. package/server/lib/projects/project-config.js +2 -2
  219. package/server/lib/quota/DOCUMENTATION.md +9 -1
  220. package/server/lib/quota/credentials/providers.js +4 -0
  221. package/server/lib/quota/credentials/store.js +4 -4
  222. package/server/lib/quota/credentials/store.test.js +8 -8
  223. package/server/lib/quota/index.js +1 -0
  224. package/server/lib/quota/providers/exe-dev.js +75 -0
  225. package/server/lib/quota/providers/exe-dev.test.js +47 -0
  226. package/server/lib/quota/providers/hyper.js +118 -0
  227. package/server/lib/quota/providers/hyper.test.js +126 -0
  228. package/server/lib/quota/providers/index.js +15 -0
  229. package/server/lib/quota/providers/ollama-cloud.js +1 -1
  230. package/server/lib/quota/providers/opencode-go.js +2 -1
  231. package/server/lib/quota/providers/opencode-go.test.js +9 -5
  232. package/server/lib/quota/providers/xai.js +1 -1
  233. package/server/lib/quota/routes.js +2 -0
  234. package/server/lib/quota/utils/auth.js +1 -1
  235. package/server/lib/relay/DOCUMENTATION.md +1 -1
  236. package/server/lib/relay/host-client.js +1 -1
  237. package/server/lib/relay/host-client.test.js +9 -1
  238. package/server/lib/relay/host-lock.js +1 -1
  239. package/server/lib/relay/service.js +5 -5
  240. package/server/lib/relay/tunnel-host.js +3 -1
  241. package/server/lib/relay/tunnel-host.test.js +9 -1
  242. package/server/lib/scheduled-tasks/issue-2710-double-execution.test.js +2 -2
  243. package/server/lib/scheduled-tasks/routes.js +5 -5
  244. package/server/lib/scheduled-tasks/service.js +25 -25
  245. package/server/lib/scheduled-tasks/service.test.js +1 -1
  246. package/server/lib/security/bind-host.js +4 -4
  247. package/server/lib/security/bind-host.test.js +1 -1
  248. package/server/lib/security/request-security.js +11 -5
  249. package/server/lib/security/request-security.test.js +14 -14
  250. package/server/lib/session-assist/runtime.js +10 -9
  251. package/server/lib/session-folders/routes.js +2 -2
  252. package/server/lib/session-folders/routes.test.js +8 -8
  253. package/server/lib/session-goal/DOCUMENTATION.md +20 -7
  254. package/server/lib/session-goal/create.js +4 -2
  255. package/server/lib/session-goal/create.test.js +1 -1
  256. package/server/lib/session-goal/objectives.js +4 -4
  257. package/server/lib/session-goal/routes.js +1 -1
  258. package/server/lib/session-goal/runtime.js +88 -22
  259. package/server/lib/session-goal/runtime.test.js +428 -2
  260. package/server/lib/session-knowledge/runtime.js +11 -11
  261. package/server/lib/session-knowledge/runtime.test.js +5 -5
  262. package/server/lib/skills-catalog/DOCUMENTATION.md +1 -1
  263. package/server/lib/skills-catalog/cache.test.js +2 -2
  264. package/server/lib/skills-catalog/disk-cache.js +5 -5
  265. package/server/lib/skills-catalog/github-meta.test.js +2 -2
  266. package/server/lib/skills-catalog/install.js +3 -2
  267. package/server/lib/small-model/DOCUMENTATION.md +4 -0
  268. package/server/lib/small-model/call.js +9 -3
  269. package/server/lib/small-model/call.test.js +29 -6
  270. package/server/lib/small-model/index.js +8 -7
  271. package/server/lib/small-model/index.test.js +1 -1
  272. package/server/lib/small-model/resolve.js +1 -1
  273. package/server/lib/small-model/resolve.test.js +1 -1
  274. package/server/lib/small-model/routes.js +2 -1
  275. package/server/lib/system-prompt/runtime.js +3 -22
  276. package/server/lib/system-prompt/runtime.test.js +3 -3
  277. package/server/lib/terminal/DOCUMENTATION.md +11 -7
  278. package/server/lib/terminal/runtime.js +180 -26
  279. package/server/lib/terminal/runtime.test.js +554 -27
  280. package/server/lib/terminal/shells.js +20 -3
  281. package/server/lib/terminal/shells.test.js +33 -2
  282. package/server/lib/tts/base-url.js +3 -3
  283. package/server/lib/tts/routes.test.js +20 -20
  284. package/server/lib/ui-auth/ui-auth.js +12 -9
  285. package/server/lib/ui-auth/ui-auth.test.js +19 -3
  286. package/server/lib/ui-auth/ui-passkeys.js +7 -7
  287. package/server/lib/walkthrough/index.js +1 -0
  288. package/server/lib/walkthrough/jobs.test.js +1 -1
  289. package/server/lib/walkthrough/language.test.js +1 -1
  290. package/server/lib/walkthrough/model-settings.js +3 -3
  291. package/server/lib/walkthrough/model-settings.test.js +1 -1
  292. package/server/lib/walkthrough/pull-request.test.js +5 -5
  293. package/server/lib/walkthrough/reproduce-2607.test.js +2 -2
  294. package/server/lib/walkthrough/routes.test.js +26 -5
  295. package/server/lib/walkthrough/store.js +3 -3
  296. package/server/lib/walkthrough/store.test.js +1 -1
  297. package/server/opencode-proxy.test.js +2 -2
  298. package/server/proxy-headers.js +1 -1
  299. package/server/sse-routes.test.js +4 -4
  300. package/README.md.bak +0 -250
  301. package/bin/lib/DOCUMENTATION.md.bak +0 -163
  302. package/dist/assets/CommitSection-SGBCAW0w.js +0 -1
  303. package/dist/assets/FilesView-Bdq8ppva.js +0 -17
  304. package/dist/assets/GitView-Znn7VJcP.js +0 -6
  305. package/dist/assets/LinearIssuesView-jP-hXyac.js +0 -1
  306. package/dist/assets/MarkdownRendererImpl-Dt9mjTRN.js +0 -12
  307. package/dist/assets/PlanView-B0F3BtPZ.js +0 -5
  308. package/dist/assets/SettingsView-BBW-S-gh.js +0 -28
  309. package/dist/assets/ToolPartDiffPreview-CUNe28U1.js +0 -8
  310. package/dist/assets/index-C57jT0Sa.css +0 -1
  311. package/dist/assets/index-DW_E3rnL.js +0 -7
  312. package/dist/assets/main-Bv5Pkngh.js +0 -928
  313. package/dist/assets/pl-Dioz29BI.js +0 -15
  314. package/dist/assets/renderMobileApp-D9yQJy0L.js +0 -25
  315. package/dist/assets/runtimeEndpointReset-CjhvxLH0.js +0 -16
  316. package/dist/assets/tr-DFnMlPxY.js +0 -6
  317. package/dist/assets/useInlineCommentController-CDEuSlPH.js +0 -2
  318. package/dist/assets/vendor-zod-BLfBSgBh.js +0 -39
  319. package/server/index.d.ts.bak +0 -39
  320. package/server/lib/agent-tool/DOCUMENTATION.md.bak +0 -119
  321. package/server/lib/browser-control/DOCUMENTATION.md.bak +0 -50
  322. package/server/lib/context-obligatory/DOCUMENTATION.md.bak +0 -19
  323. package/server/lib/dev-tunnel/DOCUMENTATION.md.bak +0 -57
  324. package/server/lib/dictation/DOCUMENTATION.md.bak +0 -100
  325. package/server/lib/event-stream/DOCUMENTATION.md.bak +0 -62
  326. package/server/lib/fs/DOCUMENTATION.md.bak +0 -47
  327. package/server/lib/git/DOCUMENTATION.md.bak +0 -193
  328. package/server/lib/github/DOCUMENTATION.md.bak +0 -183
  329. package/server/lib/linear/DOCUMENTATION.md.bak +0 -97
  330. package/server/lib/linear/OAUTH-BROKER-HANDOFF.md.bak +0 -91
  331. package/server/lib/markdown-image-grants/DOCUMENTATION.md.bak +0 -40
  332. package/server/lib/notifications/APNS.md.bak +0 -135
  333. package/server/lib/notifications/DOCUMENTATION.md.bak +0 -138
  334. package/server/lib/openchamber-control/DOCUMENTATION.md.bak +0 -64
  335. package/server/lib/opencode/DOCUMENTATION.md.bak +0 -431
  336. package/server/lib/opencode/managed-process-registry.d.ts.bak +0 -13
  337. package/server/lib/opencode/provider-env-aliases.d.ts.bak +0 -3
  338. package/server/lib/permission-auto-accept/DOCUMENTATION.md.bak +0 -34
  339. package/server/lib/project-context/DOCUMENTATION.md.bak +0 -160
  340. package/server/lib/quota/DOCUMENTATION.md.bak +0 -123
  341. package/server/lib/relay/DOCUMENTATION.md.bak +0 -100
  342. package/server/lib/scheduled-tasks/DOCUMENTATION.md.bak +0 -182
  343. package/server/lib/session-assist/DOCUMENTATION.md.bak +0 -66
  344. package/server/lib/session-goal/DOCUMENTATION.md.bak +0 -213
  345. package/server/lib/session-knowledge/DOCUMENTATION.md.bak +0 -89
  346. package/server/lib/skills-catalog/DOCUMENTATION.md.bak +0 -151
  347. package/server/lib/small-model/DOCUMENTATION.md.bak +0 -212
  348. package/server/lib/system-prompt/DOCUMENTATION.md.bak +0 -36
  349. package/server/lib/terminal/DOCUMENTATION.md.bak +0 -50
  350. package/server/lib/text/DOCUMENTATION.md.bak +0 -35
  351. package/server/lib/tts/DOCUMENTATION.md.bak +0 -147
  352. package/server/lib/tunnels/DOCUMENTATION.md.bak +0 -21
  353. package/server/lib/ui-auth/DOCUMENTATION.md.bak +0 -44
  354. package/server/lib/walkthrough/DOCUMENTATION.md.bak +0 -411
@@ -0,0 +1,59 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { fetchUpdateNotes, renderUpdateNotes } from './update-notes.js';
3
+
4
+ const compare = (a, b) => {
5
+ const pa = a.split('.').map(Number);
6
+ const pb = b.split('.').map(Number);
7
+ for (let i = 0; i < 3; i += 1) if (pa[i] !== pb[i]) return pa[i] - pb[i];
8
+ return 0;
9
+ };
10
+
11
+ const index = [
12
+ { version: '1.2.3', date: '2026-03-03', title: 'Comments everywhere', intro: 'A short intro.', app: { new: ['**Comments:** on code.'], improvements: [], fixes: ['Chat: no freeze.'], misc: [] }, vscode: null },
13
+ { version: '1.2.2', date: '2026-03-02', title: null, intro: null, app: { new: [], improvements: ['Faster.'], fixes: [], misc: [] }, vscode: null },
14
+ { version: '1.2.1', date: '2026-03-01', title: 'Old', intro: null, app: { new: ['Older.'], improvements: [], fixes: [], misc: [] }, vscode: null },
15
+ ];
16
+
17
+ describe('renderUpdateNotes', () => {
18
+ it('renders the releases after the installed version up to the offered one, newest first', () => {
19
+ expect(renderUpdateNotes(index, '1.2.1', '1.2.3', compare)).toBe(`## [1.2.3] - 2026-03-03
20
+
21
+ **Comments everywhere**
22
+
23
+ A short intro.
24
+
25
+ ### New
26
+
27
+ - **Comments:** on code.
28
+
29
+ ### Fixes
30
+
31
+ - Chat: no freeze.
32
+
33
+ ## [1.2.2] - 2026-03-02
34
+
35
+ ### Improvements
36
+
37
+ - Faster.`);
38
+ });
39
+
40
+ it('returns null when nothing lies in the range or the payload is not an index', () => {
41
+ expect(renderUpdateNotes(index, '1.2.3', '1.2.3', compare)).toBe(null);
42
+ expect(renderUpdateNotes({ entries: [] }, '1.0.0', '9.9.9', compare)).toBe(null);
43
+ expect(renderUpdateNotes([{ version: 'nope' }, { version: '1.2.2', date: '2026' }], '1.0.0', '9.9.9', compare)).toBe(null);
44
+ });
45
+ });
46
+
47
+ describe('fetchUpdateNotes', () => {
48
+ it('turns a failed request or a thrown fetch into null', async () => {
49
+ const notFound = async () => ({ ok: false });
50
+ expect(await fetchUpdateNotes('1.0.0', '2.0.0', compare, { fetch: notFound })).toBe(null);
51
+ const throwing = async () => { throw new Error('offline'); };
52
+ expect(await fetchUpdateNotes('1.0.0', '2.0.0', compare, { fetch: throwing })).toBe(null);
53
+ });
54
+
55
+ it('renders a successful response', async () => {
56
+ const ok = async () => ({ ok: true, json: async () => index });
57
+ expect(await fetchUpdateNotes('1.2.2', '1.2.3', compare, { fetch: ok })).toMatch(/^## \[1\.2\.3\] - 2026-03-03\n\n\*\*Comments everywhere\*\*/);
58
+ });
59
+ });
@@ -86,15 +86,15 @@ describe('remote client auth runtime', () => {
86
86
  it('keeps the replaced record label on a dedupe re-mint without an explicit label', async () => {
87
87
  const { dir, runtime } = await createRuntime();
88
88
  try {
89
- await runtime.createClient({ label: 'Iryna iPhone', dedupeKey: 'mobile:device-1', fallbackLabel: 'OpenChamber Mobile' });
90
- const remint = await runtime.createClient({ dedupeKey: 'mobile:device-1', fallbackLabel: 'OpenChamber Mobile' });
89
+ await runtime.createClient({ label: 'Iryna iPhone', dedupeKey: 'mobile:device-1', fallbackLabel: 'AiWorker Mobile' });
90
+ const remint = await runtime.createClient({ dedupeKey: 'mobile:device-1', fallbackLabel: 'AiWorker Mobile' });
91
91
  expect(remint.client.label).toBe('Iryna iPhone');
92
92
 
93
- const renamed = await runtime.createClient({ label: 'Work phone', dedupeKey: 'mobile:device-1', fallbackLabel: 'OpenChamber Mobile' });
93
+ const renamed = await runtime.createClient({ label: 'Work phone', dedupeKey: 'mobile:device-1', fallbackLabel: 'AiWorker Mobile' });
94
94
  expect(renamed.client.label).toBe('Work phone');
95
95
 
96
- const fresh = await runtime.createClient({ dedupeKey: 'mobile:device-2', fallbackLabel: 'OpenChamber Mobile' });
97
- expect(fresh.client.label).toBe('OpenChamber Mobile');
96
+ const fresh = await runtime.createClient({ dedupeKey: 'mobile:device-2', fallbackLabel: 'AiWorker Mobile' });
97
+ expect(fresh.client.label).toBe('AiWorker Mobile');
98
98
  } finally {
99
99
  await fs.rm(dir, { recursive: true, force: true });
100
100
  }
@@ -5,15 +5,15 @@ const isRecord = (value) => Boolean(value && typeof value === 'object' && !Array
5
5
 
6
6
  const readContextState = (session) => {
7
7
  const metadata = isRecord(session?.metadata) ? session.metadata : {};
8
- const openchamber = isRecord(metadata.openchamber) ? metadata.openchamber : {};
9
- const messages = Array.isArray(openchamber.context_obligatory_messages)
10
- ? openchamber.context_obligatory_messages.filter((item) =>
8
+ const aiworker = isRecord(metadata.aiworker) ? metadata.aiworker : {};
9
+ const messages = Array.isArray(aiworker.context_obligatory_messages)
10
+ ? aiworker.context_obligatory_messages.filter((item) =>
11
11
  isRecord(item)
12
12
  && typeof item.id === 'string'
13
13
  && typeof item.createdAt === 'number'
14
14
  && (item.role === 'user' || item.role === 'assistant'))
15
15
  : [];
16
- return { metadata, openchamber, messages };
16
+ return { metadata, aiworker, messages };
17
17
  };
18
18
 
19
19
  const buildContextPrompt = (entries) => {
@@ -89,7 +89,7 @@ export const createContextObligatoryRuntime = ({
89
89
  const summary = recent.toReversed().find((message) =>
90
90
  message?.info?.role === 'assistant' && message.info.summary === true)?.info;
91
91
  if (!summary?.id || !summary?.time?.completed) return;
92
- if (state.openchamber.context_obligatory_last_compaction_message_id === summary.id) return;
92
+ if (state.aiworker.context_obligatory_last_compaction_message_id === summary.id) return;
93
93
 
94
94
  const fetched = await Promise.allSettled(state.messages.map(async (pinned) => {
95
95
  const message = await openCodeFetch(
@@ -138,8 +138,8 @@ export const createContextObligatoryRuntime = ({
138
138
  body: {
139
139
  metadata: {
140
140
  ...freshState.metadata,
141
- openchamber: {
142
- ...freshState.openchamber,
141
+ aiworker: {
142
+ ...freshState.aiworker,
143
143
  context_obligatory_last_compaction_message_id: summary.id,
144
144
  // Recorded together with the cursor: the session now carries this
145
145
  // knowledge again, so the next send must not repeat it.
@@ -23,7 +23,7 @@ describe('context obligatory runtime', () => {
23
23
  sessionReads += 1;
24
24
  return json({
25
25
  id: 'ses_1',
26
- metadata: { openchamber: { context_obligatory_messages: [
26
+ metadata: { aiworker: { context_obligatory_messages: [
27
27
  { id: 'msg_2', createdAt: 20, role: 'assistant' },
28
28
  { id: 'msg_1', createdAt: 10, role: 'user' },
29
29
  ] } },
@@ -58,7 +58,7 @@ describe('context obligatory runtime', () => {
58
58
  expect(payload.parts[0].text).toContain('Only if no tasks or next steps remain');
59
59
  expect(payload.parts[0].text).toContain('no more than one short paragraph');
60
60
  const patch = requests.find((request) => request.method === 'PATCH');
61
- expect(JSON.parse(patch.body).metadata.openchamber.context_obligatory_last_compaction_message_id).toBe('msg_summary');
61
+ expect(JSON.parse(patch.body).metadata.aiworker.context_obligatory_last_compaction_message_id).toBe('msg_summary');
62
62
  expect(sessionReads).toBe(2);
63
63
  runtime.stop();
64
64
  });
@@ -75,7 +75,7 @@ describe('context obligatory runtime', () => {
75
75
  if (url.pathname === '/session/ses_1' && init.method === 'PATCH') return json({});
76
76
  if (url.pathname === '/session/ses_1') return json({
77
77
  id: 'ses_1',
78
- metadata: { openchamber: { knowledge_context_delivered: 'sig-before-compaction' } },
78
+ metadata: { aiworker: { knowledge_context_delivered: 'sig-before-compaction' } },
79
79
  });
80
80
  if (url.pathname === '/session/ses_1/message') return json([
81
81
  { info: { id: 'msg_agent', role: 'assistant', providerID: 'provider', modelID: 'model', agent: 'build' } },
@@ -112,7 +112,7 @@ describe('context obligatory runtime', () => {
112
112
  expect(JSON.parse(prompt.body).parts[0].text).toContain('Remember this.');
113
113
  const patch = requests.find((request) => request.method === 'PATCH');
114
114
  // Recorded with the cursor, so the next ordinary send does not repeat it.
115
- expect(JSON.parse(patch.body).metadata.openchamber.knowledge_context_delivered).toBe('sig-1');
115
+ expect(JSON.parse(patch.body).metadata.aiworker.knowledge_context_delivered).toBe('sig-1');
116
116
  });
117
117
 
118
118
  it('sends pinned messages and project knowledge as one message', async () => {
@@ -123,7 +123,7 @@ describe('context obligatory runtime', () => {
123
123
  if (url.pathname === '/session/ses_1' && init.method === 'PATCH') return json({});
124
124
  if (url.pathname === '/session/ses_1') return json({
125
125
  id: 'ses_1',
126
- metadata: { openchamber: { context_obligatory_messages: [{ id: 'msg_1', createdAt: 10, role: 'user' }] } },
126
+ metadata: { aiworker: { context_obligatory_messages: [{ id: 'msg_1', createdAt: 10, role: 'user' }] } },
127
127
  });
128
128
  if (url.pathname === '/session/ses_1/message') return json([
129
129
  { info: { id: 'msg_agent', role: 'assistant', providerID: 'provider', modelID: 'model', agent: 'build' } },
@@ -143,7 +143,7 @@ export const parseNetstatListeners = (output) => {
143
143
  /**
144
144
  * Narrows raw listeners to the ones worth offering as a preview target.
145
145
  *
146
- * `ownPorts` removes OpenChamber's own listeners — offering the user a preview
146
+ * `ownPorts` removes AiWorker's own listeners — offering the user a preview
147
147
  * of the app they are already looking at is pure noise.
148
148
  */
149
149
  export const selectDevServerCandidates = (listeners, { ownPorts = [], ownPids = [] } = {}) => {
@@ -169,7 +169,7 @@ const PROC_LOOPBACK_ADDRESSES = new Set(['0100007F', '00000000000000000000000001
169
169
  * Parses `/proc/net/tcp` and `/proc/net/tcp6`.
170
170
  *
171
171
  * The fallback for hosts without `lsof`, which is most containers — and a
172
- * deployed OpenChamber is exactly where a dev server needs discovering. Reads a
172
+ * deployed AiWorker is exactly where a dev server needs discovering. Reads a
173
173
  * kernel file rather than shelling out, so it cannot be defeated by a missing
174
174
  * binary or a stripped PATH.
175
175
  *
@@ -100,11 +100,11 @@ describe('candidate selection', () => {
100
100
  const listeners = [
101
101
  { port: 5173, pid: 10, command: 'node' },
102
102
  { port: 5432, pid: 11, command: 'postgres' },
103
- { port: 4096, pid: 12, command: 'openchamber' },
103
+ { port: 4096, pid: 12, command: 'aiworker' },
104
104
  { port: 3000, pid: 13, command: 'node' },
105
105
  ];
106
106
 
107
- test('drops OpenChamber own ports so the app never offers itself', () => {
107
+ test('drops AiWorker own ports so the app never offers itself', () => {
108
108
  const ports = selectDevServerCandidates(listeners, { ownPorts: [4096] }).map((entry) => entry.port);
109
109
  expect(ports).toEqual([5173, 3000]);
110
110
  });
@@ -50,7 +50,7 @@ const runCommand = (spawn, command, args, timeoutMs) => new Promise((resolve) =>
50
50
 
51
51
  /**
52
52
  * Reads the kernel's socket tables. Containers routinely ship without `lsof`,
53
- * and a deployed OpenChamber is precisely where discovery has to work, so this
53
+ * and a deployed AiWorker is precisely where discovery has to work, so this
54
54
  * is tried whenever the command is unavailable.
55
55
  */
56
56
  const readProcListeners = async (readFile) => {
@@ -20,7 +20,13 @@ and what made it fragile per framework.
20
20
  - `client.js` is the local end: it binds a loopback listener on the user's
21
21
  machine and pipes each accepted connection through one WebSocket. It lives in
22
22
  this package because it needs a WebSocket client the package already depends
23
- on; the desktop shell drives it over IPC.
23
+ on; the desktop shell drives it over IPC for directly reachable HTTP(S)
24
+ runtimes.
25
+ - Relay-only runtimes use `packages/electron/relay-dev-tunnel.mjs` for the local
26
+ listener. Each accepted connection gets an Electron `MessagePort`; the trusted
27
+ renderer carries its bytes through the active E2EE relay. This keeps relay
28
+ credentials and encryption in their existing renderer owner instead of
29
+ duplicating them in Electron main.
24
30
  - Port discovery is not owned here. `runtime.js` is given the reachable set by
25
31
  the same dev-server discovery the user's own list is built from.
26
32
  - The browser panel decides when to tunnel; this module never chooses a target.
@@ -40,9 +46,12 @@ and what made it fragile per framework.
40
46
  usual origin allowlist applies unchanged. That check is a CSRF defence: a
41
47
  hostile page can make a browser open a WebSocket carrying ambient cookies,
42
48
  and the origin is what exposes it.
43
- - With no `Origin` the request must carry client-token auth. A browser cannot
44
- reach this path the WebSocket API always sends an origin and never lets a
45
- page set an `Authorization` header so this case is the desktop shell.
49
+ - With no `Origin` the request must carry client-token auth or a short-lived
50
+ URL token. The bearer case is the desktop main process. The URL-token case
51
+ is the trusted renderer carrying the socket through the E2EE relay.
52
+ - Through the E2EE relay, the trusted renderer mints a short-lived URL token
53
+ and includes it in the virtual WebSocket URL. The relay host and URL-token
54
+ allowlists accept exactly `/api/dev-tunnel`, not subpaths.
46
55
  - Concurrency is capped per host, not per page, because one page load opens
47
56
  many sockets.
48
57
  - A connection that cannot be established fails the socket rather than holding
@@ -2,7 +2,7 @@
2
2
  * Local end of the dev-server tunnel.
3
3
  *
4
4
  * Binds a loopback listener on this machine and pipes every connection to a
5
- * dev server on the OpenChamber host. The point of binding a real local port —
5
+ * dev server on the AiWorker host. The point of binding a real local port —
6
6
  * rather than serving the remote page under a path on some other origin — is
7
7
  * that the page then has its own origin at the root of its own host. Absolute
8
8
  * URLs resolve, cookies scope correctly, HMR sockets connect, and nothing has
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Raw byte tunnel to a dev server running on the OpenChamber host.
2
+ * Raw byte tunnel to a dev server running on the AiWorker host.
3
3
  *
4
4
  * This is what lets a desktop client preview a dev server that lives on another
5
5
  * machine without rewriting anything. The client binds its own local port and
@@ -20,9 +20,9 @@
20
20
  *
21
21
  * - With an `Origin` header, the request came from a browser context and the
22
22
  * usual origin check applies unchanged.
23
- * - With no `Origin`, the request must carry client-token auth. A browser
24
- * cannot reach this path: the WebSocket API always sends an origin and never
25
- * lets a page set an `Authorization` header.
23
+ * - With no `Origin`, the request must carry client-token auth or a short-lived
24
+ * URL token. The URL-token case is used only by the trusted renderer through
25
+ * the E2EE relay; the UI-auth allowlist limits it to this exact path.
26
26
  */
27
27
  import net from 'node:net';
28
28
  import { WebSocketServer } from 'ws';
@@ -133,7 +133,7 @@ export function createDevTunnelRuntime({
133
133
  void (async () => {
134
134
  try {
135
135
  if (uiAuthController?.enabled) {
136
- const auth = await uiAuthController.resolveAuthContext(req, null, { allowUrlToken: false });
136
+ const auth = await uiAuthController.resolveAuthContext(req, null, { allowUrlToken: true });
137
137
  if (!auth) {
138
138
  rejectWebSocketUpgrade(socket, 401, 'UI authentication required');
139
139
  return;
@@ -1,12 +1,13 @@
1
1
  import { afterEach, describe, expect, test } from 'bun:test';
2
2
  import http from 'node:http';
3
3
  import net from 'node:net';
4
+ import WebSocket from 'ws';
4
5
 
5
6
  import { createDevTunnelClient } from './client.js';
6
7
  import { createDevTunnelRuntime, isDevTunnelPath } from './runtime.js';
7
8
 
8
9
  /**
9
- * These exercise the real socket path end to end: a dev server, an OpenChamber
10
+ * These exercise the real socket path end to end: a dev server, an AiWorker
10
11
  * host tunnelling to it, and a client binding a local port. Anything less would
11
12
  * not prove the thing that matters — that a page loads over the tunnel exactly
12
13
  * as it does locally.
@@ -228,6 +229,12 @@ describe('dev tunnel authentication', () => {
228
229
  enabled: true,
229
230
  resolveAuthContext: async () => ({ type: 'session' }),
230
231
  };
232
+ const urlTokenAuth = {
233
+ enabled: true,
234
+ resolveAuthContext: async (req, _res, options) => (
235
+ options?.allowUrlToken === true && req.url.includes('oc_url_token=good') ? { type: 'client', token: 'url:authenticated' } : null
236
+ ),
237
+ };
231
238
 
232
239
  test('accepts a bearer-authenticated client that sends no origin', async () => {
233
240
  const devPort = await startDevServer((_req, res) => res.end('ok'));
@@ -243,6 +250,19 @@ describe('dev tunnel authentication', () => {
243
250
  expect((await httpGet(localPort, '/')).body).toBe('ok');
244
251
  });
245
252
 
253
+ test('accepts a URL-token client carried by the E2EE relay', async () => {
254
+ const devPort = await startDevServer((_req, res) => res.end('relay-ok'));
255
+ const host = await startHost({ allowedPorts: [devPort], auth: urlTokenAuth });
256
+
257
+ const body = await new Promise((resolve, reject) => {
258
+ const socket = new WebSocket(`ws://127.0.0.1:${host.port}/api/dev-tunnel?port=${devPort}&oc_url_token=good`);
259
+ socket.on('open', () => socket.send('GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n'));
260
+ socket.on('message', (data) => resolve(Buffer.from(data).toString()));
261
+ socket.on('error', reject);
262
+ });
263
+ expect(body).toContain('relay-ok');
264
+ });
265
+
246
266
  test('rejects a client with no credentials', async () => {
247
267
  const devPort = await startDevServer((_req, res) => res.end('ok'));
248
268
  const host = await startHost({ allowedPorts: [devPort], auth: clientAuth });
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Catalog of local sherpa-onnx STT models available for dictation.
3
3
  * Models are downloaded on demand from the k2-fsa GitHub releases and
4
- * extracted under the OpenChamber speech-models directory.
4
+ * extracted under the AiWorker speech-models directory.
5
5
  *
6
6
  * `type` selects the recognizer construction path in the worker:
7
7
  * - 'nemo_transducer': encoder/decoder/joiner transducer (Parakeet)
@@ -2,7 +2,7 @@
2
2
  * Dictation local-speech worker process.
3
3
  *
4
4
  * Hosts the sherpa-onnx native inference (Parakeet STT) in a separate process
5
- * so ONNX decoding never blocks the main OpenChamber server. Communicates
5
+ * so ONNX decoding never blocks the main AiWorker server. Communicates
6
6
  * with the parent over child_process IPC (advanced serialization, so Buffers
7
7
  * survive the trip as Uint8Array).
8
8
  *
@@ -24,7 +24,7 @@ import { getLocalSttModelDir, getLocalSttModelSpec } from './model-catalog.js';
24
24
  import { pcm16ToWav } from '../audio.js';
25
25
  import path from 'path';
26
26
 
27
- process.title = 'OpenChamber Dictation';
27
+ process.title = 'AiWorker Dictation';
28
28
 
29
29
  const engines = new Map();
30
30
  const ttsEngines = new Map();
@@ -56,7 +56,7 @@ export function acceptDirectoryMessageStreamWsConnection({
56
56
  return;
57
57
  }
58
58
 
59
- sendMessageStreamWsEvent(socket, { type: 'openchamber:heartbeat', timestamp: Date.now() }, { directory: 'global' });
59
+ sendMessageStreamWsEvent(socket, { type: 'aiworker:heartbeat', timestamp: Date.now() }, { directory: 'global' });
60
60
  }, heartbeatIntervalMs);
61
61
 
62
62
  socket.on('close', () => {
@@ -177,7 +177,7 @@ export function createGlobalMessageStreamWsBridge({
177
177
  return;
178
178
  }
179
179
 
180
- sendMessageStreamWsEvent(socket, { type: 'openchamber:heartbeat', timestamp: Date.now() }, { directory: 'global' });
180
+ sendMessageStreamWsEvent(socket, { type: 'aiworker:heartbeat', timestamp: Date.now() }, { directory: 'global' });
181
181
  }, heartbeatIntervalMs);
182
182
 
183
183
  socket.on('close', () => {
@@ -32,14 +32,14 @@ describe('event stream protocol helpers', () => {
32
32
 
33
33
  it('derives directory from payload properties when not wrapped', () => {
34
34
  const envelope = parseSseEventEnvelope(
35
- 'data: {"type":"openchamber:notification","properties":{"directory":"/tmp/project"}}\n'
35
+ 'data: {"type":"aiworker:notification","properties":{"directory":"/tmp/project"}}\n'
36
36
  );
37
37
 
38
38
  expect(envelope).toEqual({
39
39
  eventId: null,
40
40
  directory: '/tmp/project',
41
41
  payload: {
42
- type: 'openchamber:notification',
42
+ type: 'aiworker:notification',
43
43
  properties: { directory: '/tmp/project' },
44
44
  },
45
45
  });
@@ -167,14 +167,14 @@ describe('event stream protocol helpers', () => {
167
167
 
168
168
  const sent = sendMessageStreamWsEvent(
169
169
  socket,
170
- { type: 'openchamber:heartbeat', timestamp: 1 },
170
+ { type: 'aiworker:heartbeat', timestamp: 1 },
171
171
  { eventId: 'evt-2', directory: '/tmp/project' }
172
172
  );
173
173
 
174
174
  expect(sent).toBe(true);
175
175
  expect(JSON.parse(rawPayload)).toEqual({
176
176
  type: 'event',
177
- payload: { type: 'openchamber:heartbeat', timestamp: 1 },
177
+ payload: { type: 'aiworker:heartbeat', timestamp: 1 },
178
178
  eventId: 'evt-2',
179
179
  directory: '/tmp/project',
180
180
  });
@@ -84,18 +84,18 @@ describe('event stream broadcaster', () => {
84
84
  },
85
85
  });
86
86
 
87
- broadcast({ type: 'openchamber:session-status' }, { eventId: 'evt-1', directory: '/tmp/project' });
87
+ broadcast({ type: 'aiworker:session-status' }, { eventId: 'evt-1', directory: '/tmp/project' });
88
88
 
89
89
  expect(sseEvents).toEqual([
90
90
  {
91
91
  res: sseClient,
92
- payload: { type: 'openchamber:session-status' },
92
+ payload: { type: 'aiworker:session-status' },
93
93
  },
94
94
  ]);
95
95
  expect(wsPayloads).toEqual([
96
96
  {
97
97
  type: 'event',
98
- payload: { type: 'openchamber:session-status' },
98
+ payload: { type: 'aiworker:session-status' },
99
99
  eventId: 'evt-1',
100
100
  directory: '/tmp/project',
101
101
  },
@@ -120,7 +120,7 @@ describe('event stream broadcaster', () => {
120
120
  },
121
121
  });
122
122
 
123
- broadcast({ type: 'openchamber:notification' });
123
+ broadcast({ type: 'aiworker:notification' });
124
124
 
125
125
  expect(wsClients.size).toBe(0);
126
126
  });
@@ -475,7 +475,7 @@ describe('message stream websocket runtime', () => {
475
475
  getOpenCodeAuthHeaders: () => ({}),
476
476
  processForwardedEventPayload(payload, emitSynthetic) {
477
477
  if (payload.type === 'session.updated') {
478
- emitSynthetic({ type: 'openchamber:session-status', sessionID: 'ses_1' });
478
+ emitSynthetic({ type: 'aiworker:session-status', sessionID: 'ses_1' });
479
479
  }
480
480
  },
481
481
  wsClients,
@@ -502,7 +502,7 @@ describe('message stream websocket runtime', () => {
502
502
  });
503
503
  expect(socket.sent).toContainEqual({
504
504
  type: 'event',
505
- payload: { type: 'openchamber:session-status', sessionID: 'ses_1' },
505
+ payload: { type: 'aiworker:session-status', sessionID: 'ses_1' },
506
506
  directory: 'global',
507
507
  });
508
508
 
@@ -40,6 +40,8 @@ Own filesystem API behavior for the web server runtime, including workspace-boun
40
40
 
41
41
  ## Notes for contributors
42
42
  - Keep filesystem policy (workspace root checks, error mapping, exec timeout behavior) inside this module, not in the composition root.
43
+ - Workspace checks accept, besides the active workspace and its worktrees, the **managed roots**: the AiWorker config root and the managed chats root (`managedChatsRoot` dependency; `AIWORKER_CHATS_DIR` upstream, default `<config root>/chats`). Chat worktrees may legitimately live outside every project workspace.
44
+ - `GET /api/fs/home` answers `{ home, chatsRoot }`. `chatsRoot` is the server-resolved managed chats root; clients must use it instead of joining `home` + the well-known segment (a relocated root does not contain that segment).
43
45
  - Filesystem `EPERM`/`EACCES` failures use the stable `reason: "os-permission"` response marker. Policy denials such as workspace-boundary or missing-grant failures must not use that marker because a native folder picker cannot remediate them.
44
46
  - Read-only routes authorize the requested path against the workspace before resolving symlinks. A symlink reached through the workspace may therefore target a file outside it, while a directly requested outside path still requires an exact-path grant. Write routes keep canonical-target boundary checks.
45
47
  - If adding new `/api/fs/*` endpoints, add them in `routes.js` and extend this document.