@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
@@ -22,8 +22,8 @@ export const createServerStartupRuntime = (dependencies) => {
22
22
 
23
23
  const resolveBindHost = (host) =>
24
24
  host
25
- || (typeof process.env.OPENCHAMBER_HOST === 'string' && process.env.OPENCHAMBER_HOST.trim().length > 0
26
- ? process.env.OPENCHAMBER_HOST.trim()
25
+ || (typeof process.env.AIWORKER_HOST === 'string' && process.env.AIWORKER_HOST.trim().length > 0
26
+ ? process.env.AIWORKER_HOST.trim()
27
27
  : '127.0.0.1');
28
28
 
29
29
  const startListeningAndMaybeTunnel = async ({
@@ -48,12 +48,12 @@ export const createServerStartupRuntime = (dependencies) => {
48
48
 
49
49
  if (typeof process.send === 'function') {
50
50
  if (!process.connected) {
51
- throw new Error('OpenChamber startup IPC channel disconnected before ready notification');
51
+ throw new Error('AiWorker startup IPC channel disconnected before ready notification');
52
52
  }
53
53
 
54
54
  await new Promise((resolveReadyNotification, rejectReadyNotification) => {
55
55
  try {
56
- process.send({ type: 'openchamber:ready', port: activePort }, (error) => {
56
+ process.send({ type: 'aiworker:ready', port: activePort }, (error) => {
57
57
  if (error) {
58
58
  rejectReadyNotification(error);
59
59
  return;
@@ -69,7 +69,7 @@ export const createServerStartupRuntime = (dependencies) => {
69
69
  const displayHost = (bindHost === '0.0.0.0' || bindHost === '::' || bindHost === '[::]')
70
70
  ? 'localhost'
71
71
  : (bindHost.includes(':') ? `[${bindHost}]` : bindHost);
72
- console.log(`OpenChamber server listening on ${bindHost}:${activePort}`);
72
+ console.log(`AiWorker server listening on ${bindHost}:${activePort}`);
73
73
  console.log(`Health check: http://${displayHost}:${activePort}/health`);
74
74
  console.log(`Web interface: http://${displayHost}:${activePort}`);
75
75
 
@@ -138,7 +138,7 @@ export const createServerStartupRuntime = (dependencies) => {
138
138
  // Cover every signal a shell or dev harness may use to stop/restart us, so
139
139
  // the managed OpenCode child is always torn down gracefully instead of
140
140
  // orphaned: SIGINT/SIGQUIT (Ctrl+C/Ctrl+\), SIGTERM (kill/default), SIGHUP
141
- // (terminal close), SIGUSR2 (nodemon restart for `dev:server:watch`).
141
+ // (terminal close), SIGUSR2 (nodemon restart outside Windows).
142
142
  process.on('SIGTERM', handleSignal);
143
143
  process.on('SIGINT', handleSignal);
144
144
  process.on('SIGQUIT', handleSignal);
@@ -98,7 +98,7 @@ export const createSessionRuntime = ({ writeSseEvent, getNotificationClients, br
98
98
 
99
99
  if (typeof broadcastEvent === 'function') {
100
100
  broadcastEvent({
101
- type: 'openchamber:session-activity',
101
+ type: 'aiworker:session-activity',
102
102
  properties: {
103
103
  sessionId,
104
104
  phase,
@@ -149,7 +149,7 @@ export const createSessionRuntime = ({ writeSseEvent, getNotificationClients, br
149
149
  if (!existing || existing.status !== status || attentionChanged || isRestartInterruption) {
150
150
  const state = sessionStates.get(sessionId);
151
151
  const syntheticPayload = {
152
- type: 'openchamber:session-status',
152
+ type: 'aiworker:session-status',
153
153
  properties: {
154
154
  sessionID: sessionId,
155
155
  status: state.status,
@@ -207,7 +207,7 @@ export const createSessionRuntime = ({ writeSseEvent, getNotificationClients, br
207
207
  state.needsAttention = false;
208
208
 
209
209
  const syntheticPayload = {
210
- type: 'openchamber:session-status',
210
+ type: 'aiworker:session-status',
211
211
  properties: {
212
212
  sessionID: sessionId,
213
213
  status: state.status,
@@ -47,7 +47,7 @@ describe('session runtime', () => {
47
47
  runtime.markSessionViewed('session-1', 'client-1');
48
48
 
49
49
  expect(events).toContainEqual({
50
- type: 'openchamber:session-status',
50
+ type: 'aiworker:session-status',
51
51
  properties: expect.objectContaining({
52
52
  sessionID: 'session-1',
53
53
  status: 'idle',
@@ -55,7 +55,7 @@ describe('session runtime', () => {
55
55
  }),
56
56
  });
57
57
  expect(events.at(-1)).toEqual({
58
- type: 'openchamber:session-status',
58
+ type: 'aiworker:session-status',
59
59
  properties: {
60
60
  sessionID: 'session-1',
61
61
  status: 'idle',
@@ -90,7 +90,7 @@ describe('session runtime', () => {
90
90
  });
91
91
 
92
92
  expect(events).toContainEqual({
93
- type: 'openchamber:session-status',
93
+ type: 'aiworker:session-status',
94
94
  properties: expect.objectContaining({
95
95
  sessionID: 'legacy-session-1',
96
96
  status: 'busy',
@@ -132,7 +132,7 @@ describe('session runtime', () => {
132
132
  });
133
133
 
134
134
  const activityPhases = () => events
135
- .filter((event) => event.type === 'openchamber:session-activity')
135
+ .filter((event) => event.type === 'aiworker:session-activity')
136
136
  .map((event) => event.properties.phase);
137
137
 
138
138
  expect(activityPhases()).toEqual(['busy', 'cooldown']);
@@ -224,12 +224,12 @@ describe('session runtime', () => {
224
224
  });
225
225
 
226
226
  const terminalEvents = events.filter((event) => (
227
- event.type === 'openchamber:session-status' || event.type === 'session.error'
227
+ event.type === 'aiworker:session-status' || event.type === 'session.error'
228
228
  ));
229
229
  expect(terminalEvents).toHaveLength(6);
230
230
  for (const sessionId of ['session-busy-1', 'session-busy-2', 'session-busy-3']) {
231
231
  expect(terminalEvents).toContainEqual({
232
- type: 'openchamber:session-status',
232
+ type: 'aiworker:session-status',
233
233
  properties: expect.objectContaining({
234
234
  sessionID: sessionId,
235
235
  status: 'idle',
@@ -1,4 +1,10 @@
1
1
  import { isAgentMemoryFeatureAvailable } from '../agent-memory/feature-flag.js';
2
+ import {
3
+ DEFAULT_INPUT_HISTORY_LIMIT,
4
+ DEFAULT_INPUT_HISTORY_SCOPE,
5
+ isInputHistoryLimit,
6
+ isInputHistoryScope,
7
+ } from './input-history-scope.js';
2
8
 
3
9
  export const createSettingsHelpers = (dependencies) => {
4
10
  const {
@@ -140,6 +146,12 @@ export const createSettingsHelpers = (dependencies) => {
140
146
  if (typeof candidate.themeVariant === 'string' && (candidate.themeVariant === 'light' || candidate.themeVariant === 'dark')) {
141
147
  result.themeVariant = candidate.themeVariant;
142
148
  }
149
+ if (typeof candidate.inputHistoryScope === 'string' && isInputHistoryScope(candidate.inputHistoryScope)) {
150
+ result.inputHistoryScope = candidate.inputHistoryScope;
151
+ }
152
+ if (isInputHistoryLimit(candidate.inputHistoryLimit)) {
153
+ result.inputHistoryLimit = candidate.inputHistoryLimit;
154
+ }
143
155
  if (typeof candidate.useSystemTheme === 'boolean') {
144
156
  result.useSystemTheme = candidate.useSystemTheme;
145
157
  }
@@ -519,6 +531,12 @@ export const createSettingsHelpers = (dependencies) => {
519
531
  if (typeof candidate.inputSpellcheckEnabled === 'boolean') {
520
532
  result.inputSpellcheckEnabled = candidate.inputSpellcheckEnabled;
521
533
  }
534
+ if (candidate.enterToSend === true || candidate.enterToSend === false) {
535
+ result.enterToSend = candidate.enterToSend;
536
+ }
537
+ if (candidate.enterToSendConfigured === true || candidate.enterToSendConfigured === false) {
538
+ result.enterToSendConfigured = candidate.enterToSendConfigured;
539
+ }
522
540
  if (typeof candidate.showOpenCodeUpdateNotifications === 'boolean') {
523
541
  result.showOpenCodeUpdateNotifications = candidate.showOpenCodeUpdateNotifications;
524
542
  }
@@ -687,6 +705,12 @@ export const createSettingsHelpers = (dependencies) => {
687
705
  result.gitChangesViewMode = mode;
688
706
  }
689
707
  }
708
+ if (typeof candidate.toolJsonViewMode === 'string') {
709
+ const mode = candidate.toolJsonViewMode.trim();
710
+ if (mode === 'summary' || mode === 'formatted' || mode === 'raw') {
711
+ result.toolJsonViewMode = mode;
712
+ }
713
+ }
690
714
  if (typeof candidate.directoryShowHidden === 'boolean') {
691
715
  result.directoryShowHidden = candidate.directoryShowHidden;
692
716
  }
@@ -927,6 +951,8 @@ export const createSettingsHelpers = (dependencies) => {
927
951
  const pwaAppName = normalizePwaAppName(settings?.pwaAppName, '');
928
952
  const pwaOrientation = normalizePwaOrientation(settings?.pwaOrientation, 'system');
929
953
  const mobileKeyboardMode = normalizeMobileKeyboardMode(settings?.mobileKeyboardMode, 'native');
954
+ const inputHistoryScope = sanitized.inputHistoryScope ?? DEFAULT_INPUT_HISTORY_SCOPE;
955
+ const inputHistoryLimit = sanitized.inputHistoryLimit ?? DEFAULT_INPUT_HISTORY_LIMIT;
930
956
 
931
957
  return {
932
958
  ...sanitized,
@@ -937,14 +963,16 @@ export const createSettingsHelpers = (dependencies) => {
937
963
  ...(pwaAppName ? { pwaAppName } : {}),
938
964
  pwaOrientation,
939
965
  mobileKeyboardMode,
966
+ inputHistoryScope,
967
+ inputHistoryLimit,
940
968
  securityScopedBookmarks: bookmarks,
941
969
  pinnedDirectories: normalizeStringArray(settings.pinnedDirectories),
942
970
  typographySizes: sanitizeTypographySizesPartial(settings.typographySizes),
943
- ...(process.env.OPENCHAMBER_RUNTIME === 'desktop'
971
+ ...(process.env.AIWORKER_RUNTIME === 'desktop'
944
972
  ? {
945
- desktopLanAccessActive: process.env.OPENCHAMBER_DESKTOP_LAN_ACCESS_ACTIVE === 'true',
973
+ desktopLanAccessActive: process.env.AIWORKER_DESKTOP_LAN_ACCESS_ACTIVE === 'true',
946
974
  desktopLanAccessBlockedReason:
947
- process.env.OPENCHAMBER_DESKTOP_LAN_ACCESS_BLOCKED_REASON === 'missing-password'
975
+ process.env.AIWORKER_DESKTOP_LAN_ACCESS_BLOCKED_REASON === 'missing-password'
948
976
  ? 'missing-password'
949
977
  : null,
950
978
  }
@@ -1,8 +1,19 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { mkdirSync, mkdtempSync, readdirSync, rmSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { dirname, join } from 'node:path';
5
+ import { fileURLToPath, pathToFileURL } from 'node:url';
1
6
  import { describe, expect, it } from 'vitest';
2
7
 
8
+ import {
9
+ DEFAULT_INPUT_HISTORY_LIMIT,
10
+ } from './input-history-scope.js';
3
11
  import { createSettingsHelpers } from './settings-helpers.js';
4
12
  import { createSettingsNormalizationRuntime } from './settings-normalization-runtime.js';
5
13
 
14
+ const testFilePath = fileURLToPath(import.meta.url);
15
+ const packagesWebDir = join(dirname(testFilePath), '..', '..', '..');
16
+
6
17
  const createTestHelpers = () => createSettingsHelpers({
7
18
  normalizePathForPersistence: (value) => value,
8
19
  normalizeDirectoryPath: (value) => value,
@@ -58,6 +69,66 @@ const createTestHelpersWithRealSanitizers = () => {
58
69
  };
59
70
 
60
71
  describe('settings helpers', () => {
72
+ it('imports from the packed @aiworker/web tarball without escaping the published package', async () => {
73
+ const tempRoot = mkdtempSync(join(tmpdir(), 'settings-helpers-pack-'));
74
+ const packDir = join(tempRoot, 'pack');
75
+ const extractDir = join(tempRoot, 'extract');
76
+
77
+ try {
78
+ mkdirSync(packDir);
79
+ mkdirSync(extractDir);
80
+ execFileSync('npm', ['pack', '--silent', '--pack-destination', packDir], {
81
+ cwd: packagesWebDir,
82
+ stdio: 'pipe',
83
+ });
84
+
85
+ const tarballName = readdirSync(packDir).find((entry) => entry.endsWith('.tgz'));
86
+ expect(tarballName).toBeTruthy();
87
+
88
+ execFileSync('tar', ['-xzf', join(packDir, tarballName), '-C', extractDir], {
89
+ stdio: 'pipe',
90
+ });
91
+
92
+ const extractedModule = await import(
93
+ pathToFileURL(join(extractDir, 'package', 'server', 'lib', 'opencode', 'settings-helpers.js')).href
94
+ );
95
+
96
+ const helpers = extractedModule.createSettingsHelpers({
97
+ normalizePathForPersistence: (value) => value,
98
+ normalizeDirectoryPath: (value) => value,
99
+ normalizeTunnelBootstrapTtlMs: (value) => value,
100
+ normalizeTunnelSessionTtlMs: (value) => value,
101
+ normalizeTunnelProvider: (value) => value,
102
+ normalizeTunnelMode: (value) => value,
103
+ normalizeOptionalPath: (value) => value,
104
+ normalizeManagedRemoteTunnelHostname: (value) => value,
105
+ normalizeManagedRemoteTunnelPresets: () => undefined,
106
+ normalizeManagedRemoteTunnelPresetTokens: () => undefined,
107
+ sanitizeTypographySizesPartial: () => undefined,
108
+ normalizeStringArray: (input) => input,
109
+ sanitizeModelRefs: () => undefined,
110
+ sanitizeSkillCatalogs: () => undefined,
111
+ sanitizeProjects: () => undefined,
112
+ });
113
+
114
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryScope: 'global' })).toEqual({
115
+ inputHistoryScope: 'global',
116
+ });
117
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryScope: 'session' })).toEqual({
118
+ inputHistoryScope: 'session',
119
+ });
120
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryLimit: 40 })).toEqual({
121
+ inputHistoryLimit: 40,
122
+ });
123
+ expect(helpers.formatSettingsResponse({})).toMatchObject({
124
+ inputHistoryScope: 'session',
125
+ inputHistoryLimit: DEFAULT_INPUT_HISTORY_LIMIT,
126
+ });
127
+ } finally {
128
+ rmSync(tempRoot, { recursive: true, force: true });
129
+ }
130
+ });
131
+
61
132
  it('accepts only booleans for draft starter visibility', () => {
62
133
  const helpers = createTestHelpers();
63
134
 
@@ -66,6 +137,14 @@ describe('settings helpers', () => {
66
137
  expect(helpers.sanitizeSettingsUpdate({ draftStartersVisible: 'false' })).toEqual({});
67
138
  });
68
139
 
140
+ it('sanitizes both Enter settings independently', () => {
141
+ const helpers = createTestHelpers();
142
+
143
+ expect(helpers.sanitizeSettingsUpdate({ enterToSend: true })).toEqual({ enterToSend: true });
144
+ expect(helpers.sanitizeSettingsUpdate({ enterToSendConfigured: false })).toEqual({ enterToSendConfigured: false });
145
+ expect(helpers.sanitizeSettingsUpdate({ enterToSend: 'true', enterToSendConfigured: 1 })).toEqual({});
146
+ });
147
+
69
148
  it('sanitizes shared sidebar display preferences', () => {
70
149
  const helpers = createTestHelpers();
71
150
 
@@ -88,6 +167,15 @@ describe('settings helpers', () => {
88
167
  })).toEqual({});
89
168
  });
90
169
 
170
+ it('persists valid tool JSON view modes', () => {
171
+ const helpers = createTestHelpers();
172
+
173
+ expect(helpers.sanitizeSettingsUpdate({ toolJsonViewMode: 'summary' })).toEqual({ toolJsonViewMode: 'summary' });
174
+ expect(helpers.sanitizeSettingsUpdate({ toolJsonViewMode: 'formatted' })).toEqual({ toolJsonViewMode: 'formatted' });
175
+ expect(helpers.sanitizeSettingsUpdate({ toolJsonViewMode: 'raw' })).toEqual({ toolJsonViewMode: 'raw' });
176
+ expect(helpers.sanitizeSettingsUpdate({ toolJsonViewMode: 'unknown' })).toEqual({});
177
+ });
178
+
91
179
  it('accepts only booleans for wide chat layout', () => {
92
180
  const helpers = createTestHelpers();
93
181
 
@@ -134,6 +222,74 @@ describe('settings helpers', () => {
134
222
  expect(helpers.sanitizeSettingsUpdate({ messageStreamTransport: 'websocket' })).toEqual({});
135
223
  });
136
224
 
225
+ it('accepts inputHistoryScope as a persisted shared setting', () => {
226
+ const helpers = createTestHelpers();
227
+
228
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryScope: 'global' })).toEqual({
229
+ inputHistoryScope: 'global',
230
+ });
231
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryScope: 'session' })).toEqual({
232
+ inputHistoryScope: 'session',
233
+ });
234
+ });
235
+
236
+ it('accepts valid inputHistoryLimit values as a persisted shared setting', () => {
237
+ const helpers = createTestHelpers();
238
+
239
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryLimit: 1 })).toEqual({
240
+ inputHistoryLimit: 1,
241
+ });
242
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryLimit: 40 })).toEqual({
243
+ inputHistoryLimit: 40,
244
+ });
245
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryLimit: 100 })).toEqual({
246
+ inputHistoryLimit: 100,
247
+ });
248
+ });
249
+
250
+ it('rejects invalid inputHistoryLimit values', () => {
251
+ const helpers = createTestHelpers();
252
+
253
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryLimit: 0 })).toEqual({});
254
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryLimit: 101 })).toEqual({});
255
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryLimit: 1.5 })).toEqual({});
256
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryLimit: '40' })).toEqual({});
257
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryLimit: Number.NaN })).toEqual({});
258
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryLimit: Number.POSITIVE_INFINITY })).toEqual({});
259
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryLimit: Number.NEGATIVE_INFINITY })).toEqual({});
260
+ });
261
+
262
+ it('rejects invalid inputHistoryScope values', () => {
263
+ const helpers = createTestHelpers();
264
+
265
+ expect(helpers.sanitizeSettingsUpdate({ inputHistoryScope: 'workspace' })).toEqual({});
266
+ });
267
+
268
+ it('defaults inputHistoryScope to session in formatted settings responses', () => {
269
+ const helpers = createTestHelpers();
270
+
271
+ expect(helpers.formatSettingsResponse({ inputHistoryScope: 'global' })).toMatchObject({
272
+ inputHistoryScope: 'global',
273
+ });
274
+ expect(helpers.formatSettingsResponse({})).toMatchObject({
275
+ inputHistoryScope: 'session',
276
+ });
277
+ });
278
+
279
+ it('defaults missing inputHistoryLimit to 40 in formatted settings responses and preserves valid values', () => {
280
+ const helpers = createTestHelpers();
281
+
282
+ expect(helpers.formatSettingsResponse({})).toMatchObject({
283
+ inputHistoryLimit: DEFAULT_INPUT_HISTORY_LIMIT,
284
+ });
285
+ expect(helpers.formatSettingsResponse({ inputHistoryLimit: 1 })).toMatchObject({
286
+ inputHistoryLimit: 1,
287
+ });
288
+ expect(helpers.formatSettingsResponse({ inputHistoryLimit: 100 })).toMatchObject({
289
+ inputHistoryLimit: 100,
290
+ });
291
+ });
292
+
137
293
  it('sanitizes the persisted terminal shell', () => {
138
294
  const helpers = createTestHelpers();
139
295
 
@@ -316,6 +472,27 @@ describe('settings helpers', () => {
316
472
  });
317
473
  });
318
474
 
475
+ it('accepts and rejects invalid Enter-to-send preference values', () => {
476
+ const helpers = createTestHelpers();
477
+
478
+ expect(helpers.sanitizeSettingsUpdate({ enterToSend: true, enterToSendConfigured: true })).toEqual({
479
+ enterToSend: true,
480
+ enterToSendConfigured: true,
481
+ });
482
+ expect(helpers.sanitizeSettingsUpdate({ enterToSend: false, enterToSendConfigured: true })).toEqual({
483
+ enterToSend: false,
484
+ enterToSendConfigured: true,
485
+ });
486
+ expect(helpers.sanitizeSettingsUpdate({ enterToSend: false, enterToSendConfigured: false })).toEqual({
487
+ enterToSend: false,
488
+ enterToSendConfigured: false,
489
+ });
490
+ expect(helpers.sanitizeSettingsUpdate({ enterToSend: 'true' })).toEqual({});
491
+ expect(helpers.sanitizeSettingsUpdate({ enterToSend: 1 })).toEqual({});
492
+ expect(helpers.sanitizeSettingsUpdate({ enterToSendConfigured: 'true' })).toEqual({});
493
+ expect(helpers.sanitizeSettingsUpdate({ enterToSendConfigured: 1 })).toEqual({});
494
+ });
495
+
319
496
  it('accepts dismissed OpenCode update toast version as a persisted shared setting', () => {
320
497
  const helpers = createTestHelpers();
321
498
 
@@ -353,24 +530,24 @@ describe('settings helpers', () => {
353
530
 
354
531
  it('includes transient desktop LAN access runtime status in desktop settings response', () => {
355
532
  const helpers = createTestHelpers();
356
- const previousRuntime = process.env.OPENCHAMBER_RUNTIME;
357
- const previousActive = process.env.OPENCHAMBER_DESKTOP_LAN_ACCESS_ACTIVE;
358
- const previousReason = process.env.OPENCHAMBER_DESKTOP_LAN_ACCESS_BLOCKED_REASON;
533
+ const previousRuntime = process.env.AIWORKER_RUNTIME;
534
+ const previousActive = process.env.AIWORKER_DESKTOP_LAN_ACCESS_ACTIVE;
535
+ const previousReason = process.env.AIWORKER_DESKTOP_LAN_ACCESS_BLOCKED_REASON;
359
536
  try {
360
- process.env.OPENCHAMBER_RUNTIME = 'desktop';
361
- process.env.OPENCHAMBER_DESKTOP_LAN_ACCESS_ACTIVE = 'false';
362
- process.env.OPENCHAMBER_DESKTOP_LAN_ACCESS_BLOCKED_REASON = 'missing-password';
537
+ process.env.AIWORKER_RUNTIME = 'desktop';
538
+ process.env.AIWORKER_DESKTOP_LAN_ACCESS_ACTIVE = 'false';
539
+ process.env.AIWORKER_DESKTOP_LAN_ACCESS_BLOCKED_REASON = 'missing-password';
363
540
 
364
541
  const response = helpers.formatSettingsResponse({ desktopLanAccessEnabled: true });
365
542
  expect(response.desktopLanAccessActive).toBe(false);
366
543
  expect(response.desktopLanAccessBlockedReason).toBe('missing-password');
367
544
  } finally {
368
- if (typeof previousRuntime === 'string') process.env.OPENCHAMBER_RUNTIME = previousRuntime;
369
- else delete process.env.OPENCHAMBER_RUNTIME;
370
- if (typeof previousActive === 'string') process.env.OPENCHAMBER_DESKTOP_LAN_ACCESS_ACTIVE = previousActive;
371
- else delete process.env.OPENCHAMBER_DESKTOP_LAN_ACCESS_ACTIVE;
372
- if (typeof previousReason === 'string') process.env.OPENCHAMBER_DESKTOP_LAN_ACCESS_BLOCKED_REASON = previousReason;
373
- else delete process.env.OPENCHAMBER_DESKTOP_LAN_ACCESS_BLOCKED_REASON;
545
+ if (typeof previousRuntime === 'string') process.env.AIWORKER_RUNTIME = previousRuntime;
546
+ else delete process.env.AIWORKER_RUNTIME;
547
+ if (typeof previousActive === 'string') process.env.AIWORKER_DESKTOP_LAN_ACCESS_ACTIVE = previousActive;
548
+ else delete process.env.AIWORKER_DESKTOP_LAN_ACCESS_ACTIVE;
549
+ if (typeof previousReason === 'string') process.env.AIWORKER_DESKTOP_LAN_ACCESS_BLOCKED_REASON = previousReason;
550
+ else delete process.env.AIWORKER_DESKTOP_LAN_ACCESS_BLOCKED_REASON;
374
551
  }
375
552
  });
376
553
 
@@ -692,8 +692,8 @@ export const createSettingsRuntime = (deps) => {
692
692
  return { settings, changed: false };
693
693
  }
694
694
 
695
- const defaultLight = 'flexoki-light';
696
- const defaultDark = 'flexoki-dark';
695
+ const defaultLight = 'openchamber-light';
696
+ const defaultDark = 'openchamber-dark';
697
697
 
698
698
  let nextLightThemeId = hasLight ? settings.lightThemeId : undefined;
699
699
  let nextDarkThemeId = hasDark ? settings.darkThemeId : undefined;
@@ -39,6 +39,35 @@ const createRuntime = async () => {
39
39
  };
40
40
 
41
41
  describe('settings runtime', () => {
42
+ it('uses AiWorker themes when a new install has no theme preferences', async () => {
43
+ const { runtime, cleanup } = await createRuntime();
44
+ try {
45
+ await expect(runtime.readSettingsFromDiskMigrated()).resolves.toMatchObject({
46
+ lightThemeId: 'openchamber-light',
47
+ darkThemeId: 'openchamber-dark',
48
+ });
49
+ } finally {
50
+ await cleanup();
51
+ }
52
+ });
53
+
54
+ it('preserves existing theme preferences during theme migration', async () => {
55
+ const { runtime, settingsFilePath, cleanup } = await createRuntime();
56
+ try {
57
+ await fsPromises.writeFile(settingsFilePath, JSON.stringify({
58
+ lightThemeId: 'flexoki-light',
59
+ darkThemeId: 'flexoki-dark',
60
+ }), 'utf8');
61
+
62
+ await expect(runtime.readSettingsFromDiskMigrated()).resolves.toMatchObject({
63
+ lightThemeId: 'flexoki-light',
64
+ darkThemeId: 'flexoki-dark',
65
+ });
66
+ } finally {
67
+ await cleanup();
68
+ }
69
+ });
70
+
42
71
  it('round-trips shared sidebar preferences through settings.json', async () => {
43
72
  const { runtime, settingsFilePath, cleanup } = await createRuntime();
44
73
  const preferences = {
@@ -6,7 +6,10 @@ import { parse as parseJsonc, printParseErrorCode } from 'jsonc-parser';
6
6
 
7
7
  // ============== PATH CONSTANTS ==============
8
8
 
9
- const OPENCODE_CONFIG_DIR = path.join(os.homedir(), '.config', 'opencode');
9
+ const OPENCODE_CONFIG_DIR = path.join(
10
+ process.env.XDG_CONFIG_HOME?.trim() || path.join(os.homedir(), '.config'),
11
+ 'opencode',
12
+ );
10
13
  const AGENT_DIR = path.join(OPENCODE_CONFIG_DIR, 'agents');
11
14
  const COMMAND_DIR = path.join(OPENCODE_CONFIG_DIR, 'commands');
12
15
  const SKILL_DIR = path.join(OPENCODE_CONFIG_DIR, 'skills');
@@ -320,7 +323,7 @@ function writeConfig(config, filePath = CONFIG_FILE) {
320
323
  parseConfigObject(existing, filePath);
321
324
  }
322
325
 
323
- const backupFile = `${filePath}.openchamber.backup`;
326
+ const backupFile = `${filePath}.aiworker.backup`;
324
327
  fs.copyFileSync(filePath, backupFile);
325
328
  console.log(`Created config backup: ${backupFile}`);
326
329
  }
@@ -49,7 +49,7 @@ describe('parseMdFile', () => {
49
49
  });
50
50
 
51
51
  it('parses frontmatter whose closing --- is at end-of-file without a trailing newline', () => {
52
- // gray-matter (used by OpenCode) accepts this shape; OpenChamber must too,
52
+ // gray-matter (used by OpenCode) accepts this shape; AiWorker must too,
53
53
  // otherwise a later save duplicates the YAML block.
54
54
  const file = writeFixture('eof-close.md', [
55
55
  '---',
@@ -147,7 +147,7 @@ describe('updateAgent frontmatter preservation', () => {
147
147
 
148
148
  it('updates the model in place without duplicating YAML for a file with EOF-closed frontmatter', () => {
149
149
  // Repro of OPE-178: the file's closing --- sits at EOF (no trailing
150
- // newline). OpenCode parses it; OpenChamber previously treated the whole
150
+ // newline). OpenCode parses it; AiWorker previously treated the whole
151
151
  // file as the prompt body and prepended a second frontmatter block on save.
152
152
  const projectDir = path.join(FIXTURE_DIR, 'project');
153
153
  const agentPath = path.join(projectDir, '.opencode', 'agents', 'strateg.md');
@@ -305,7 +305,7 @@ describe('readConfigFile / writeConfig JSONC safety (issue #2923)', () => {
305
305
  /cannot be loaded safely/,
306
306
  );
307
307
  expect(fs.readFileSync(file, 'utf8')).toBe(PARTIAL_PARSE_CONFIG);
308
- expect(fs.existsSync(`${file}.openchamber.backup`)).toBe(false);
308
+ expect(fs.existsSync(`${file}.aiworker.backup`)).toBe(false);
309
309
  });
310
310
 
311
311
  it('preserves a valid config across MCP updates', () => {
@@ -318,7 +318,7 @@ describe('readConfigFile / writeConfig JSONC safety (issue #2923)', () => {
318
318
  expect(rewritten.plugin).toEqual(['opencode-see-image']);
319
319
  expect(rewritten.provider['ollama-cloud'].name).toBe('Ollama Cloud');
320
320
  expect(rewritten.mcp.openproject.enabled).toBe(false);
321
- expect(fs.readFileSync(`${file}.openchamber.backup`, 'utf8')).toBe(VALID_CONFIG);
321
+ expect(fs.readFileSync(`${file}.aiworker.backup`, 'utf8')).toBe(VALID_CONFIG);
322
322
  });
323
323
 
324
324
  it('does not wipe an unparseable user config during MCP mutation attempts', () => {
@@ -331,7 +331,7 @@ describe('readConfigFile / writeConfig JSONC safety (issue #2923)', () => {
331
331
  /cannot be loaded safely/,
332
332
  );
333
333
  expect(fs.readFileSync(file, 'utf8')).toBe(PARTIAL_PARSE_CONFIG);
334
- expect(fs.existsSync(`${file}.openchamber.backup`)).toBe(false);
334
+ expect(fs.existsSync(`${file}.aiworker.backup`)).toBe(false);
335
335
  } finally {
336
336
  if (previousOpenCodeConfig === undefined) delete process.env.OPENCODE_CONFIG;
337
337
  else process.env.OPENCODE_CONFIG = previousOpenCodeConfig;
@@ -350,7 +350,7 @@ describe('readConfigFile / writeConfig JSONC safety (issue #2923)', () => {
350
350
  /cannot be loaded safely/,
351
351
  );
352
352
  expect(fs.readFileSync(yamlish, 'utf8')).toBe('mcp:\n openproject:\n type: remote\n');
353
- expect(fs.existsSync(`${yamlish}.openchamber.backup`)).toBe(false);
353
+ expect(fs.existsSync(`${yamlish}.aiworker.backup`)).toBe(false);
354
354
  });
355
355
 
356
356
  it('keeps a valid custom layer readable when a project layer is unparseable', () => {
@@ -377,7 +377,7 @@ describe('readConfigFile / writeConfig JSONC safety (issue #2923)', () => {
377
377
  expect(rewritten.plugin).toEqual(['opencode-see-image']);
378
378
  expect(rewritten.mcp.openproject.enabled).toBe(false);
379
379
  expect(fs.readFileSync(projectFile, 'utf8')).toBe(PARTIAL_PARSE_CONFIG);
380
- expect(fs.existsSync(`${projectFile}.openchamber.backup`)).toBe(false);
380
+ expect(fs.existsSync(`${projectFile}.aiworker.backup`)).toBe(false);
381
381
  } finally {
382
382
  if (previousOpenCodeConfig === undefined) delete process.env.OPENCODE_CONFIG;
383
383
  else process.env.OPENCODE_CONFIG = previousOpenCodeConfig;
@@ -11,6 +11,7 @@ export const createGracefulShutdownRuntime = (dependencies) => {
11
11
  sessionAssistRuntime,
12
12
  sessionGoalRuntime,
13
13
  contextObligatoryRuntime,
14
+ messageQueueRuntime,
14
15
  scheduledTasksRuntime,
15
16
  getHealthCheckInterval,
16
17
  clearHealthCheckInterval,
@@ -47,6 +48,7 @@ export const createGracefulShutdownRuntime = (dependencies) => {
47
48
  sessionAssistRuntime?.stop?.();
48
49
  sessionGoalRuntime?.stop?.();
49
50
  contextObligatoryRuntime?.stop?.();
51
+ messageQueueRuntime?.stop?.();
50
52
  scheduledTasksRuntime?.stop?.();
51
53
 
52
54
  const healthCheckInterval = getHealthCheckInterval();
@@ -1,5 +1,6 @@
1
1
  import { createOpencodeClient } from '@opencode-ai/sdk/v2';
2
2
  import { buildDeferredRestartResponse } from './config-mutation-response.js';
3
+ import { OPENCODE_CONFIG_DIR } from './shared.js';
3
4
 
4
5
  /**
5
6
  * Matches how OpenCode reads its own boolean env flags: any value other than
@@ -110,7 +111,7 @@ export const registerSkillRoutes = (app, dependencies) => {
110
111
  }
111
112
 
112
113
  const userRoots = [
113
- path.join(home, '.config', 'opencode'),
114
+ OPENCODE_CONFIG_DIR,
114
115
  path.join(home, '.opencode'),
115
116
  path.join(home, '.claude', 'skills'),
116
117
  path.join(home, '.agents', 'skills'),
@@ -1,9 +1,8 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import os from 'os';
4
3
  import yaml from 'yaml';
4
+ import { OPENCODE_CONFIG_DIR } from './shared.js';
5
5
 
6
- const OPENCODE_CONFIG_DIR = path.join(os.homedir(), '.config', 'opencode');
7
6
  const GLOBAL_SNIPPET_DIR = path.join(OPENCODE_CONFIG_DIR, 'snippet');
8
7
  const GLOBAL_SNIPPET_DIR_ALT = path.join(OPENCODE_CONFIG_DIR, 'snippets');
9
8
  const SNIPPET_EXTENSION = '.md';
@@ -21,7 +21,7 @@ const finiteNonNegative = (value) => Number.isFinite(value) && value >= 0 ? valu
21
21
  const nonNegativeInteger = (value) => Number.isInteger(value) && value >= 0 ? value : undefined;
22
22
 
23
23
  const isStartupPerformanceEnabled = () => (
24
- ENABLED_VALUES.has(String(process.env.OPENCHAMBER_STARTUP_PERF ?? '').toLowerCase())
24
+ ENABLED_VALUES.has(String(process.env.AIWORKER_STARTUP_PERF ?? '').toLowerCase())
25
25
  );
26
26
 
27
27
  export const recordStartupPerformance = (phase, details = {}) => {