@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
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
- # <picture><source media="(prefers-color-scheme: dark)" srcset="https://github.com/openchamber/openchamber/raw/HEAD/docs/references/badges/openchamber-logo-dark.svg"><img src="https://github.com/openchamber/openchamber/raw/HEAD/docs/references/badges/openchamber-logo-light.svg" width="32" height="32" align="absmiddle" /></picture> @aiworker/web
1
+ # <picture><source media="(prefers-color-scheme: dark)" srcset="https://roweb.cn/roweb/openchamber/raw/HEAD/docs/references/badges/openchamber-logo-dark.svg"><img src="https://roweb.cn/roweb/openchamber/raw/HEAD/docs/references/badges/openchamber-logo-light.svg" width="32" height="32" align="absmiddle" /></picture> @aiworker/web
2
2
 
3
- [![GitHub stars](https://img.shields.io/github/stars/openchamber/openchamber?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1NiAyNTYiPjxwYXRoIGQ9Ik0yMjkuMDYsMTA4Ljc5bC00OC43LDQyLDE0Ljg4LDYyLjc5YTguNCw4LjQsMCwwLDEtMTIuNTIsOS4xN0wxMjgsMTg5LjA5LDczLjI4LDIyMi43NGE4LjQsOC40LDAsMCwxLTEyLjUyLTkuMTdsMTQuODgtNjIuNzktNDguNy00MkE4LjQ2LDguNDYsMCwwLDEsMzEuNzMsOTRMOTUuNjQsODguOGwyNC42Mi01OS42YTguMzYsOC4zNiwwLDAsMSwxNS40OCwwbDI0LjYyLDU5LjZMMjI0LjI3LDk0QTguNDYsOC40NiwwLDAsMSwyMjkuMDYsMTA4Ljc5WiIgb3BhY2l0eT0iMC4yIj48L3BhdGg%2BPHBhdGggZD0iTTIzOS4xOCw5Ny4yNkExNi4zOCwxNi4zOCwwLDAsMCwyMjQuOTIsODZsLTU5LTQuNzZMMTQzLjE0LDI2LjE1YTE2LjM2LDE2LjM2LDAsMCwwLTMwLjI3LDBMOTAuMTEsODEuMjMsMzEuMDgsODZhMTYuNDYsMTYuNDYsMCwwLDAtOS4zNywyOC44Nmw0NSwzOC44M0w1MywyMTEuNzVhMTYuMzgsMTYuMzgsMCwwLDAsMjQuNSwxNy44MkwxMjgsMTk4LjQ5bDUwLjUzLDMxLjA4QTE2LjQsMTYuNCwwLDAsMCwyMDMsMjExLjc1bC0xMy43Ni01OC4wNyw0NS0zOC44M0ExNi40MywxNi40MywwLDAsMCwyMzkuMTgsOTcuMjZabS0xNS4zNCw1LjQ3LTQ4LjcsNDJhOCw4LDAsMCwwLTIuNTYsNy45MWwxNC44OCw2Mi44YS4zNy4zNywwLDAsMS0uMTcuNDhjLS4xOC4xNC0uMjMuMTEtLjM4LDBsLTU0LjcyLTMzLjY1YTgsOCwwLDAsMC04LjM4LDBMNjkuMDksMjE1Ljk0Yy0uMTUuMDktLjE5LjEyLS4zOCwwYS4zNy4zNywwLDAsMS0uMTctLjQ4bDE0Ljg4LTYyLjhhOCw4LDAsMCwwLTIuNTYtNy45MWwtNDguNy00MmMtLjEyLS4xLS4yMy0uMTktLjEzLS41cy4xOC0uMjcuMzMtLjI5bDYzLjkyLTUuMTZBOCw4LDAsMCwwLDEwMyw5MS44NmwyNC42Mi01OS42MWMuMDgtLjE3LjExLS4yNS4zNS0uMjVzLjI3LjA4LjM1LjI1TDE1Myw5MS44NmE4LDgsMCwwLDAsNi43NSw0LjkybDYzLjkyLDUuMTZjLjE1LDAsLjI0LDAsLjMzLjI5UzIyNCwxMDIuNjMsMjIzLjg0LDEwMi43M1oiPjwvcGF0aD48L3N2Zz4%3D&logoColor=FFFCF0&labelColor=100F0F&color=66800B)](https://github.com/openchamber/openchamber/stargazers)
4
- [![GitHub release](https://img.shields.io/github/v/release/openchamber/openchamber?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1NiAyNTYiPjxwYXRoIGQ9Ik0xMjgsMTI5LjA5VjIzMmE4LDgsMCwwLDEtMy44NC0xbC04OC00OC4xOGE4LDgsMCwwLDEtNC4xNi03VjgwLjE4YTgsOCwwLDAsMSwuNy0zLjI1WiIgb3BhY2l0eT0iMC4yIj48L3BhdGg%2BPHBhdGggZD0iTTIyMy42OCw2Ni4xNSwxMzUuNjgsMThhMTUuODgsMTUuODgsMCwwLDAtMTUuMzYsMGwtODgsNDguMTdhMTYsMTYsMCwwLDAtOC4zMiwxNHY5NS42NGExNiwxNiwwLDAsMCw4LjMyLDE0bDg4LDQ4LjE3YTE1Ljg4LDE1Ljg4LDAsMCwwLDE1LjM2LDBsODgtNDguMTdhMTYsMTYsMCwwLDAsOC4zMi0xNFY4MC4xOEExNiwxNiwwLDAsMCwyMjMuNjgsNjYuMTVaTTEyOCwzMmw4MC4zNCw0NC0yOS43NywxNi4zLTgwLjM1LTQ0Wk0xMjgsMTIwLDQ3LjY2LDc2bDMzLjktMTguNTYsODAuMzQsNDRaTTQwLDkwbDgwLDQzLjc4djg1Ljc5TDQwLDE3NS44MlptMTc2LDg1Ljc4aDBsLTgwLDQzLjc5VjEzMy44MmwzMi0xNy41MVYxNTJhOCw4LDAsMCwwLDE2LDBWMTA3LjU1TDIxNiw5MHY4NS43N1oiPjwvcGF0aD48L3N2Zz4%3D&logoColor=FFFCF0&labelColor=100F0F&color=205EA6)](https://github.com/openchamber/openchamber/releases/latest)
3
+ [![GitHub stars](https://img.shields.io/github/stars/openchamber/openchamber?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1NiAyNTYiPjxwYXRoIGQ9Ik0yMjkuMDYsMTA4Ljc5bC00OC43LDQyLDE0Ljg4LDYyLjc5YTguNCw4LjQsMCwwLDEtMTIuNTIsOS4xN0wxMjgsMTg5LjA5LDczLjI4LDIyMi43NGE4LjQsOC40LDAsMCwxLTEyLjUyLTkuMTdsMTQuODgtNjIuNzktNDguNy00MkE4LjQ2LDguNDYsMCwwLDEsMzEuNzMsOTRMOTUuNjQsODguOGwyNC42Mi01OS42YTguMzYsOC4zNiwwLDAsMSwxNS40OCwwbDI0LjYyLDU5LjZMMjI0LjI3LDk0QTguNDYsOC40NiwwLDAsMSwyMjkuMDYsMTA4Ljc5WiIgb3BhY2l0eT0iMC4yIj48L3BhdGg%2BPHBhdGggZD0iTTIzOS4xOCw5Ny4yNkExNi4zOCwxNi4zOCwwLDAsMCwyMjQuOTIsODZsLTU5LTQuNzZMMTQzLjE0LDI2LjE1YTE2LjM2LDE2LjM2LDAsMCwwLTMwLjI3LDBMOTAuMTEsODEuMjMsMzEuMDgsODZhMTYuNDYsMTYuNDYsMCwwLDAtOS4zNywyOC44Nmw0NSwzOC44M0w1MywyMTEuNzVhMTYuMzgsMTYuMzgsMCwwLDAsMjQuNSwxNy44MkwxMjgsMTk4LjQ5bDUwLjUzLDMxLjA4QTE2LjQsMTYuNCwwLDAsMCwyMDMsMjExLjc1bC0xMy43Ni01OC4wNyw0NS0zOC44M0ExNi40MywxNi40MywwLDAsMCwyMzkuMTgsOTcuMjZabS0xNS4zNCw1LjQ3LTQ4LjcsNDJhOCw4LDAsMCwwLTIuNTYsNy45MWwxNC44OCw2Mi44YS4zNy4zNywwLDAsMS0uMTcuNDhjLS4xOC4xNC0uMjMuMTEtLjM4LDBsLTU0LjcyLTMzLjY1YTgsOCwwLDAsMC04LjM4LDBMNjkuMDksMjE1Ljk0Yy0uMTUuMDktLjE5LjEyLS4zOCwwYS4zNy4zNywwLDAsMS0uMTctLjQ4bDE0Ljg4LTYyLjhhOCw4LDAsMCwwLTIuNTYtNy45MWwtNDguNy00MmMtLjEyLS4xLS4yMy0uMTktLjEzLS41cy4xOC0uMjcuMzMtLjI5bDYzLjkyLTUuMTZBOCw4LDAsMCwwLDEwMyw5MS44NmwyNC42Mi01OS42MWMuMDgtLjE3LjExLS4yNS4zNS0uMjVzLjI3LjA4LjM1LjI1TDE1Myw5MS44NmE4LDgsMCwwLDAsNi43NSw0LjkybDYzLjkyLDUuMTZjLjE1LDAsLjI0LDAsLjMzLjI5UzIyNCwxMDIuNjMsMjIzLjg0LDEwMi43M1oiPjwvcGF0aD48L3N2Zz4%3D&logoColor=FFFCF0&labelColor=100F0F&color=66800B)](https://roweb.cn/roweb/openchamber/stargazers)
4
+ [![GitHub release](https://img.shields.io/github/v/release/openchamber/openchamber?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1NiAyNTYiPjxwYXRoIGQ9Ik0xMjgsMTI5LjA5VjIzMmE4LDgsMCwwLDEtMy44NC0xbC04OC00OC4xOGE4LDgsMCwwLDEtNC4xNi03VjgwLjE4YTgsOCwwLDAsMSwuNy0zLjI1WiIgb3BhY2l0eT0iMC4yIj48L3BhdGg%2BPHBhdGggZD0iTTIyMy42OCw2Ni4xNSwxMzUuNjgsMThhMTUuODgsMTUuODgsMCwwLDAtMTUuMzYsMGwtODgsNDguMTdhMTYsMTYsMCwwLDAtOC4zMiwxNHY5NS42NGExNiwxNiwwLDAsMCw4LjMyLDE0bDg4LDQ4LjE3YTE1Ljg4LDE1Ljg4LDAsMCwwLDE1LjM2LDBsODgtNDguMTdhMTYsMTYsMCwwLDAsOC4zMi0xNFY4MC4xOEExNiwxNiwwLDAsMCwyMjMuNjgsNjYuMTVaTTEyOCwzMmw4MC4zNCw0NC0yOS43NywxNi4zLTgwLjM1LTQ0Wk0xMjgsMTIwLDQ3LjY2LDc2bDMzLjktMTguNTYsODAuMzQsNDRaTTQwLDkwbDgwLDQzLjc4djg1Ljc5TDQwLDE3NS44MlptMTc2LDg1Ljc4aDBsLTgwLDQzLjc5VjEzMy44MmwzMi0xNy41MVYxNTJhOCw4LDAsMCwwLDE2LDBWMTA3LjU1TDIxNiw5MHY4NS43N1oiPjwvcGF0aD48L3N2Zz4%3D&logoColor=FFFCF0&labelColor=100F0F&color=205EA6)](https://roweb.cn/roweb/openchamber/releases/latest)
5
5
  [![Discord](https://img.shields.io/badge/Discord-join.svg?style=flat&labelColor=100F0F&color=8B7EC8&logo=discord&logoColor=FFFCF0)](https://discord.gg/ZYRSdnwwKA)
6
6
 
7
7
  Run [OpenCode](https://opencode.ai) in your browser. Install the CLI, open `localhost:3000`, done. Works on desktop browsers, tablets, and phones as a PWA.
8
8
 
9
- Full project overview, screenshots, and all features: [github.com/openchamber/openchamber](https://github.com/openchamber/openchamber)
9
+ Full project overview, screenshots, and all features: [roweb.cn/roweb/openchamber](https://roweb.cn/roweb/openchamber)
10
10
 
11
11
  ## Install
12
12
 
package/bin/cli.js CHANGED
@@ -48,7 +48,7 @@ import { createTunnelCommand, isValidTunnelDoctorResponse, shouldDisplayTunnelQr
48
48
  import {
49
49
  resolveDoctorPortStatuses,
50
50
  discoverRunningInstances,
51
- discoverOpenChamberInstanceOnPort,
51
+ discoverAiWorkerInstanceOnPort,
52
52
  discoverLifecycleInstances,
53
53
  discoverUnconfirmedRegistryInstanceOnPort,
54
54
  resolveTunnelProviders,
@@ -117,7 +117,10 @@ function getBunBinary() {
117
117
  return process.env.BUN_BINARY.trim();
118
118
  }
119
119
  if (typeof process.env.BUN_INSTALL === 'string' && process.env.BUN_INSTALL.trim().length > 0) {
120
- return path.join(process.env.BUN_INSTALL.trim(), 'bin', 'bun');
120
+ // The Windows installer places bun.exe there; spawnSync does not append
121
+ // the extension to an explicit path, so without it the probe fails and
122
+ // the CLI silently falls back to Node.
123
+ return path.join(process.env.BUN_INSTALL.trim(), 'bin', process.platform === 'win32' ? 'bun.exe' : 'bun');
121
124
  }
122
125
  return 'bun';
123
126
  }
@@ -345,7 +348,7 @@ async function main() {
345
348
  await commands[command](options);
346
349
  }
347
350
 
348
- const isCliExecution = isModuleCliExecution(process.argv[1], import.meta.url, fs.realpathSync, 'openchamber');
351
+ const isCliExecution = isModuleCliExecution(process.argv[1], import.meta.url, fs.realpathSync, 'aiworker');
349
352
 
350
353
  if (isCliExecution) {
351
354
  let isHandlingSigint = false;
@@ -445,7 +448,7 @@ export {
445
448
  fetchTunnelProvidersFromPort,
446
449
  fetchSystemInfoFromPort,
447
450
  discoverRunningInstances,
448
- discoverOpenChamberInstanceOnPort,
451
+ discoverAiWorkerInstanceOnPort,
449
452
  discoverLifecycleInstances,
450
453
  discoverUnconfirmedRegistryInstanceOnPort,
451
454
  ensureTunnelProfilesMigrated,
package/bin/cli.test.js CHANGED
@@ -11,6 +11,7 @@ import { isModuleCliExecution, normalizeCliEntryPath } from './cli-entry.js';
11
11
  import { requestJson } from './lib/cli-http.js';
12
12
  import { requestControlAction } from './lib/cli-control.js';
13
13
  import { inspectTunnelAttachability } from './lib/cli-lifecycle.js';
14
+ import { startupCommand } from './lib/commands-startup.js';
14
15
  import { formatGoal } from './lib/commands-schedule.js';
15
16
  import {
16
17
  buildSessionCreatePayload,
@@ -29,11 +30,12 @@ import {
29
30
  import {
30
31
  assertAuthenticatedNetworkExposure,
31
32
  commands,
32
- discoverOpenChamberInstanceOnPort,
33
+ discoverAiWorkerInstanceOnPort,
33
34
  discoverLifecycleInstances,
34
35
  discoverRunningInstances,
35
36
  discoverUnconfirmedRegistryInstanceOnPort,
36
37
  ensureTunnelProfilesMigrated,
38
+ EXIT_CODE,
37
39
  generateUiPassword,
38
40
  getInstanceFilePath,
39
41
  getPidFilePath,
@@ -45,17 +47,17 @@ import {
45
47
  } from './cli.js';
46
48
  import { buildWindowsStartupTaskCommand } from './lib/cli-startup.js';
47
49
 
48
- async function withTempOpenChamberDataDir(fn) {
49
- const previous = process.env.OPENCHAMBER_DATA_DIR;
50
+ async function withTempAiWorkerDataDir(fn) {
51
+ const previous = process.env.AIWORKER_DATA_DIR;
50
52
  const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'openchamber-cli-test-'));
51
- process.env.OPENCHAMBER_DATA_DIR = dir;
53
+ process.env.AIWORKER_DATA_DIR = dir;
52
54
  try {
53
55
  return await fn(dir);
54
56
  } finally {
55
57
  if (typeof previous === 'string') {
56
- process.env.OPENCHAMBER_DATA_DIR = previous;
58
+ process.env.AIWORKER_DATA_DIR = previous;
57
59
  } else {
58
- delete process.env.OPENCHAMBER_DATA_DIR;
60
+ delete process.env.AIWORKER_DATA_DIR;
59
61
  }
60
62
  fs.rmSync(dir, { recursive: true, force: true });
61
63
  }
@@ -85,7 +87,7 @@ async function captureStdout(fn) {
85
87
  }
86
88
  }
87
89
 
88
- async function startMockOpenChamberServer(options = {}) {
90
+ async function startMockAiWorkerServer(options = {}) {
89
91
  const runtime = options.runtime || 'web';
90
92
  const pid = Number.isFinite(options.pid) ? options.pid : null;
91
93
  let shutdownRequested = false;
@@ -173,11 +175,11 @@ async function waitForTcpPort(port, timeoutMs = 3000) {
173
175
  return false;
174
176
  }
175
177
 
176
- function spawnOpenChamberLikeIdleProcess() {
178
+ function spawnAiWorkerLikeIdleProcess() {
177
179
  return spawn(process.execPath, ['-e', 'setInterval(() => {}, 1000)', 'openchamber-idle'], { stdio: 'ignore' });
178
180
  }
179
181
 
180
- function spawnOpenChamberLikeHungServer(port) {
182
+ function spawnAiWorkerLikeHungServer(port) {
181
183
  const script = `
182
184
  const net = require('net');
183
185
  const sockets = new Set();
@@ -315,7 +317,7 @@ describe('cli args', () => {
315
317
  '--worktree',
316
318
  'side-task',
317
319
  '--branch',
318
- 'openchamber/side-task',
320
+ 'aiworker/side-task',
319
321
  '--base',
320
322
  'main',
321
323
  '--no-upstream',
@@ -328,7 +330,7 @@ describe('cli args', () => {
328
330
  expect(parsed.options.prompt).toBe('Investigate cache invalidation');
329
331
  expect(parsed.options.model).toBe('openai/gpt-5.5');
330
332
  expect(parsed.options.worktree).toBe('side-task');
331
- expect(parsed.options.branch).toBe('openchamber/side-task');
333
+ expect(parsed.options.branch).toBe('aiworker/side-task');
332
334
  expect(parsed.options.startRef).toBe('main');
333
335
  expect(parsed.options.setUpstream).toBe(false);
334
336
  });
@@ -347,7 +349,7 @@ describe('cli args', () => {
347
349
  model: 'openai/gpt-5.5',
348
350
  agent: 'build',
349
351
  worktree: 'side-task',
350
- branch: 'openchamber/side-task',
352
+ branch: 'aiworker/side-task',
351
353
  startRef: 'main',
352
354
  setUpstream: true,
353
355
  })).toEqual({
@@ -355,7 +357,7 @@ describe('cli args', () => {
355
357
  title: 'Side task',
356
358
  worktree: {
357
359
  name: 'side-task',
358
- branchName: 'openchamber/side-task',
360
+ branchName: 'aiworker/side-task',
359
361
  startRef: 'main',
360
362
  },
361
363
  prompt: 'Investigate cache invalidation',
@@ -660,7 +662,7 @@ describe('cli API target resolution', () => {
660
662
  discoverDesktopInstance: async () => null,
661
663
  discoverLifecycleInstances: async () => [{ port: 3001 }, { port: 3002 }],
662
664
  isServerHealthReady: async () => false,
663
- })).rejects.toThrow('Multiple OpenChamber instances are running');
665
+ })).rejects.toThrow('Multiple AiWorker instances are running');
664
666
  });
665
667
  });
666
668
 
@@ -681,15 +683,15 @@ describe('network-exposed auth validation', () => {
681
683
  });
682
684
 
683
685
  it('allows explicit unsafe LAN override from process env only', () => {
684
- const previous = process.env.OPENCHAMBER_ALLOW_UNAUTHENTICATED_LAN;
685
- process.env.OPENCHAMBER_ALLOW_UNAUTHENTICATED_LAN = 'true';
686
+ const previous = process.env.AIWORKER_ALLOW_UNAUTHENTICATED_LAN;
687
+ process.env.AIWORKER_ALLOW_UNAUTHENTICATED_LAN = 'true';
686
688
  try {
687
689
  expect(() => assertAuthenticatedNetworkExposure({ host: '0.0.0.0' })).not.toThrow();
688
690
  } finally {
689
691
  if (typeof previous === 'string') {
690
- process.env.OPENCHAMBER_ALLOW_UNAUTHENTICATED_LAN = previous;
692
+ process.env.AIWORKER_ALLOW_UNAUTHENTICATED_LAN = previous;
691
693
  } else {
692
- delete process.env.OPENCHAMBER_ALLOW_UNAUTHENTICATED_LAN;
694
+ delete process.env.AIWORKER_ALLOW_UNAUTHENTICATED_LAN;
693
695
  }
694
696
  }
695
697
  });
@@ -733,30 +735,30 @@ describe('serve UI password resolution', () => {
733
735
  });
734
736
 
735
737
  describe('serve host resolution', () => {
736
- it('uses OPENCHAMBER_HOST when --host is not provided', () => {
737
- const previous = process.env.OPENCHAMBER_HOST;
738
- process.env.OPENCHAMBER_HOST = '192.0.2.20';
738
+ it('uses AIWORKER_HOST when --host is not provided', () => {
739
+ const previous = process.env.AIWORKER_HOST;
740
+ process.env.AIWORKER_HOST = '192.0.2.20';
739
741
  try {
740
742
  expect(resolveServeHost(undefined)).toBe('192.0.2.20');
741
743
  } finally {
742
744
  if (typeof previous === 'string') {
743
- process.env.OPENCHAMBER_HOST = previous;
745
+ process.env.AIWORKER_HOST = previous;
744
746
  } else {
745
- delete process.env.OPENCHAMBER_HOST;
747
+ delete process.env.AIWORKER_HOST;
746
748
  }
747
749
  }
748
750
  });
749
751
 
750
- it('prefers explicit --host over OPENCHAMBER_HOST', () => {
751
- const previous = process.env.OPENCHAMBER_HOST;
752
- process.env.OPENCHAMBER_HOST = '192.0.2.20';
752
+ it('prefers explicit --host over AIWORKER_HOST', () => {
753
+ const previous = process.env.AIWORKER_HOST;
754
+ process.env.AIWORKER_HOST = '192.0.2.20';
753
755
  try {
754
756
  expect(resolveServeHost('192.0.2.21')).toBe('192.0.2.21');
755
757
  } finally {
756
758
  if (typeof previous === 'string') {
757
- process.env.OPENCHAMBER_HOST = previous;
759
+ process.env.AIWORKER_HOST = previous;
758
760
  } else {
759
- delete process.env.OPENCHAMBER_HOST;
761
+ delete process.env.AIWORKER_HOST;
760
762
  }
761
763
  }
762
764
  });
@@ -764,7 +766,7 @@ describe('serve host resolution', () => {
764
766
 
765
767
  describe('compatibility exports', () => {
766
768
  it('allows tunnel profile migration before command options are initialized', async () => {
767
- await withTempOpenChamberDataDir(async () => {
769
+ await withTempAiWorkerDataDir(async () => {
768
770
  const store = ensureTunnelProfilesMigrated();
769
771
 
770
772
  expect(store).toEqual({ version: 1, profiles: [] });
@@ -772,7 +774,7 @@ describe('compatibility exports', () => {
772
774
  });
773
775
 
774
776
  it('includes ngrok in fallback tunnel providers when no server is reachable', async () => {
775
- await withTempOpenChamberDataDir(async () => {
777
+ await withTempAiWorkerDataDir(async () => {
776
778
  const port = await allocateLoopbackPort();
777
779
  const output = await captureStdout(async () => {
778
780
  await commands.tunnel({ json: true, explicitPort: true, port }, 'providers');
@@ -785,7 +787,7 @@ describe('compatibility exports', () => {
785
787
  });
786
788
 
787
789
  it('supports ngrok quick dry-run with an explicit port', async () => {
788
- await withTempOpenChamberDataDir(async () => {
790
+ await withTempAiWorkerDataDir(async () => {
789
791
  const output = await captureStdout(async () => {
790
792
  await commands.tunnel({
791
793
  json: true,
@@ -831,7 +833,7 @@ describe('CLI HTTP helpers', () => {
831
833
  });
832
834
 
833
835
  it('retries UI-authenticated API requests with the stored instance password', async () => {
834
- await withTempOpenChamberDataDir(async () => {
836
+ await withTempAiWorkerDataDir(async () => {
835
837
  const port = 45678;
836
838
  fs.writeFileSync(await getInstanceFilePath(port), JSON.stringify({ port, uiPassword: 'secret' }, null, 2));
837
839
  const originalFetch = globalThis.fetch;
@@ -876,7 +878,7 @@ describe('CLI HTTP helpers', () => {
876
878
  });
877
879
 
878
880
  it('prefers the stored instance password over a non-explicit env password', async () => {
879
- await withTempOpenChamberDataDir(async () => {
881
+ await withTempAiWorkerDataDir(async () => {
880
882
  const port = 45679;
881
883
  fs.writeFileSync(await getInstanceFilePath(port), JSON.stringify({ port, uiPassword: 'stored-secret' }, null, 2));
882
884
  const originalFetch = globalThis.fetch;
@@ -914,7 +916,7 @@ describe('CLI HTTP helpers', () => {
914
916
  });
915
917
 
916
918
  it('authenticates desktop-local API requests with the stored client token', async () => {
917
- await withTempOpenChamberDataDir(async (dir) => {
919
+ await withTempAiWorkerDataDir(async (dir) => {
918
920
  const port = 57123;
919
921
  fs.writeFileSync(path.join(dir, 'settings.json'), JSON.stringify({
920
922
  desktopLocalPort: port,
@@ -982,7 +984,7 @@ describe('cli entry detection', () => {
982
984
 
983
985
  it('accepts wrapper binary name fallback when requested', () => {
984
986
  const wrapperPath = '/home/user/.local/bin/openchamber';
985
- expect(isModuleCliExecution(wrapperPath, moduleUrl, undefined, 'openchamber')).toBe(true);
987
+ expect(isModuleCliExecution(wrapperPath, moduleUrl, undefined, 'aiworker')).toBe(true);
986
988
  });
987
989
 
988
990
  it('normalizes direct paths when realpath fails', () => {
@@ -996,9 +998,9 @@ describe('cli entry detection', () => {
996
998
  });
997
999
 
998
1000
  describe('isOpenchamberCmdline', () => {
999
- it('accepts OpenChamber CLI and daemon cmdlines', () => {
1000
- expect(isOpenchamberCmdline('node /x/@openchamber/web/bin/cli.js serve')).toBe(true);
1001
- expect(isOpenchamberCmdline('node /x/@openchamber/web/server/index.js --port 9090')).toBe(true);
1001
+ it('accepts AiWorker CLI and daemon cmdlines', () => {
1002
+ expect(isOpenchamberCmdline('node /x/@aiworker/web/bin/cli.js serve')).toBe(true);
1003
+ expect(isOpenchamberCmdline('node /x/@aiworker/web/server/index.js --port 9090')).toBe(true);
1002
1004
  expect(isOpenchamberCmdline('bun /home/u/projects/openchamber/packages/web/server/index.js --port 3001')).toBe(true);
1003
1005
  });
1004
1006
 
@@ -1019,7 +1021,7 @@ describe('isOpenchamberProcessRunning', () => {
1019
1021
  // platforms a live but unrelated process (a recycled stale PID) must read as
1020
1022
  // not-running so it can't trip the "already running" guard (issue #1721).
1021
1023
  it.skipIf(process.platform !== 'linux' && process.platform !== 'darwin')(
1022
- 'returns false for a live non-OpenChamber PID',
1024
+ 'returns false for a live non-AiWorker PID',
1023
1025
  async () => {
1024
1026
  const child = spawn('sleep', ['30'], { stdio: 'ignore' });
1025
1027
  try {
@@ -1034,10 +1036,10 @@ describe('isOpenchamberProcessRunning', () => {
1034
1036
 
1035
1037
  describe('lifecycle instance discovery', () => {
1036
1038
  it('does not attribute a desktop runtime response to a different explicit port', async () => {
1037
- await withTempOpenChamberDataDir(async (dir) => {
1039
+ await withTempAiWorkerDataDir(async (dir) => {
1038
1040
  fs.writeFileSync(path.join(dir, 'settings.json'), JSON.stringify({ desktopLocalPort: 57123 }, null, 2));
1039
1041
 
1040
- const instance = await discoverOpenChamberInstanceOnPort(3003, {
1042
+ const instance = await discoverAiWorkerInstanceOnPort(3003, {
1041
1043
  fetchImpl: async () => createMockJsonResponse({ runtime: 'desktop', pid: 934 }),
1042
1044
  });
1043
1045
 
@@ -1046,10 +1048,10 @@ describe('lifecycle instance discovery', () => {
1046
1048
  });
1047
1049
 
1048
1050
  it('attributes a desktop runtime response to its configured desktop port', async () => {
1049
- await withTempOpenChamberDataDir(async (dir) => {
1051
+ await withTempAiWorkerDataDir(async (dir) => {
1050
1052
  fs.writeFileSync(path.join(dir, 'settings.json'), JSON.stringify({ desktopLocalPort: 57123 }, null, 2));
1051
1053
 
1052
- const instance = await discoverOpenChamberInstanceOnPort(57123, {
1054
+ const instance = await discoverAiWorkerInstanceOnPort(57123, {
1053
1055
  fetchImpl: async () => createMockJsonResponse({ runtime: 'desktop', pid: 934 }),
1054
1056
  });
1055
1057
 
@@ -1062,7 +1064,7 @@ describe('lifecycle instance discovery', () => {
1062
1064
  });
1063
1065
 
1064
1066
  it('does not mark tunnel attachability as desktop for a different explicit port', async () => {
1065
- await withTempOpenChamberDataDir(async (dir) => {
1067
+ await withTempAiWorkerDataDir(async (dir) => {
1066
1068
  fs.writeFileSync(path.join(dir, 'settings.json'), JSON.stringify({ desktopLocalPort: 57123 }, null, 2));
1067
1069
  const originalFetch = globalThis.fetch;
1068
1070
  globalThis.fetch = async () => createMockJsonResponse({ runtime: 'desktop', pid: 934 });
@@ -1077,7 +1079,7 @@ describe('lifecycle instance discovery', () => {
1077
1079
  });
1078
1080
 
1079
1081
  it('keeps pid and instance files when live port probe confirms a cmdline mismatch', async () => {
1080
- await withTempOpenChamberDataDir(async () => {
1082
+ await withTempAiWorkerDataDir(async () => {
1081
1083
  const port = 45123;
1082
1084
  const pid = 12345;
1083
1085
  const pidFile = await getPidFilePath(port);
@@ -1099,7 +1101,7 @@ describe('lifecycle instance discovery', () => {
1099
1101
  });
1100
1102
 
1101
1103
  it('removes stale pid and instance files when a cmdline mismatch is not confirmed by live probe', async () => {
1102
- await withTempOpenChamberDataDir(async () => {
1104
+ await withTempAiWorkerDataDir(async () => {
1103
1105
  const port = 45124;
1104
1106
  const pid = 12346;
1105
1107
  const pidFile = await getPidFilePath(port);
@@ -1119,7 +1121,7 @@ describe('lifecycle instance discovery', () => {
1119
1121
  });
1120
1122
 
1121
1123
  it('preserves matched pid and instance files when the recorded port probe is inconclusive', async () => {
1122
- await withTempOpenChamberDataDir(async () => {
1124
+ await withTempAiWorkerDataDir(async () => {
1123
1125
  const port = 45126;
1124
1126
  const pid = 12347;
1125
1127
  const pidFile = await getPidFilePath(port);
@@ -1139,7 +1141,7 @@ describe('lifecycle instance discovery', () => {
1139
1141
  });
1140
1142
 
1141
1143
  it('preserves unknown-identity pid and instance files when the recorded port probe is inconclusive', async () => {
1142
- await withTempOpenChamberDataDir(async () => {
1144
+ await withTempAiWorkerDataDir(async () => {
1143
1145
  const port = 45129;
1144
1146
  const pid = 12350;
1145
1147
  const pidFile = await getPidFilePath(port);
@@ -1158,8 +1160,8 @@ describe('lifecycle instance discovery', () => {
1158
1160
  });
1159
1161
  });
1160
1162
 
1161
- it('uses the live system-info pid instead of a stale OpenChamber-looking pid-file pid', async () => {
1162
- await withTempOpenChamberDataDir(async () => {
1163
+ it('uses the live system-info pid instead of a stale AiWorker-looking pid-file pid', async () => {
1164
+ await withTempAiWorkerDataDir(async () => {
1163
1165
  const port = 45127;
1164
1166
  const stalePid = 12348;
1165
1167
  const livePid = 54321;
@@ -1180,7 +1182,7 @@ describe('lifecycle instance discovery', () => {
1180
1182
  });
1181
1183
 
1182
1184
  it('uses the explicit host when probing a pid-file entry without a stored host', async () => {
1183
- await withTempOpenChamberDataDir(async () => {
1185
+ await withTempAiWorkerDataDir(async () => {
1184
1186
  const port = 45128;
1185
1187
  const pid = 12349;
1186
1188
  const host = '192.0.2.10';
@@ -1207,7 +1209,7 @@ describe('lifecycle instance discovery', () => {
1207
1209
  });
1208
1210
 
1209
1211
  it('tries loopback before treating an explicit-host pid-file probe as inconclusive', async () => {
1210
- await withTempOpenChamberDataDir(async () => {
1212
+ await withTempAiWorkerDataDir(async () => {
1211
1213
  const port = 45130;
1212
1214
  const pid = 12351;
1213
1215
  const host = '192.0.2.11';
@@ -1237,7 +1239,7 @@ describe('lifecycle instance discovery', () => {
1237
1239
  });
1238
1240
 
1239
1241
  it('does not accept a fallback loopback probe with a different pid for a concrete host registry', async () => {
1240
- await withTempOpenChamberDataDir(async () => {
1242
+ await withTempAiWorkerDataDir(async () => {
1241
1243
  const port = 45131;
1242
1244
  const pid = 12352;
1243
1245
  const otherPid = 54322;
@@ -1265,8 +1267,8 @@ describe('lifecycle instance discovery', () => {
1265
1267
  });
1266
1268
  });
1267
1269
 
1268
- it('discovers an explicit live OpenChamber port without a pid-file registry entry', async () => {
1269
- await withTempOpenChamberDataDir(async () => {
1270
+ it('discovers an explicit live AiWorker port without a pid-file registry entry', async () => {
1271
+ await withTempAiWorkerDataDir(async () => {
1270
1272
  const port = 45125;
1271
1273
  const instances = await discoverLifecycleInstances(
1272
1274
  { explicitPort: true, port },
@@ -1280,9 +1282,9 @@ describe('lifecycle instance discovery', () => {
1280
1282
  });
1281
1283
 
1282
1284
  it('cleans a matched pid-file entry without stopping it when the recorded port is free', async () => {
1283
- await withTempOpenChamberDataDir(async () => {
1285
+ await withTempAiWorkerDataDir(async () => {
1284
1286
  const port = await allocateLoopbackPort();
1285
- const child = spawnOpenChamberLikeIdleProcess();
1287
+ const child = spawnAiWorkerLikeIdleProcess();
1286
1288
  const pidFile = await getPidFilePath(port);
1287
1289
  const instanceFile = await getInstanceFilePath(port);
1288
1290
  try {
@@ -1304,9 +1306,9 @@ describe('lifecycle instance discovery', () => {
1304
1306
  });
1305
1307
 
1306
1308
  describe('lifecycle commands with unmanaged explicit ports', () => {
1307
- it('serve refuses to start on a live OpenChamber port without requiring pid files', async () => {
1308
- await withTempOpenChamberDataDir(async () => {
1309
- const server = await startMockOpenChamberServer();
1309
+ it('serve refuses to start on a live AiWorker port without requiring pid files', async () => {
1310
+ await withTempAiWorkerDataDir(async () => {
1311
+ const server = await startMockAiWorkerServer();
1310
1312
  try {
1311
1313
  await expect(commands.serve({ explicitPort: true, port: server.port, quiet: true })).rejects.toThrow(
1312
1314
  /already running on port/
@@ -1318,8 +1320,8 @@ describe('lifecycle commands with unmanaged explicit ports', () => {
1318
1320
  });
1319
1321
 
1320
1322
  it('status --port reports a live unmanaged server when the registry is empty', async () => {
1321
- await withTempOpenChamberDataDir(async () => {
1322
- const server = await startMockOpenChamberServer();
1323
+ await withTempAiWorkerDataDir(async () => {
1324
+ const server = await startMockAiWorkerServer();
1323
1325
  try {
1324
1326
  const output = await captureStdout(() => commands.status({ explicitPort: true, port: server.port, json: true }));
1325
1327
  const payload = JSON.parse(output);
@@ -1335,8 +1337,8 @@ describe('lifecycle commands with unmanaged explicit ports', () => {
1335
1337
  });
1336
1338
 
1337
1339
  it('stop --port reaches unmanaged shutdown when the registry is empty', async () => {
1338
- await withTempOpenChamberDataDir(async () => {
1339
- const server = await startMockOpenChamberServer();
1340
+ await withTempAiWorkerDataDir(async () => {
1341
+ const server = await startMockAiWorkerServer();
1340
1342
  try {
1341
1343
  await commands.stop({ explicitPort: true, port: server.port, quiet: true, suppressQuietOutput: true });
1342
1344
  expect(server.shutdownRequested).toBe(true);
@@ -1347,9 +1349,9 @@ describe('lifecycle commands with unmanaged explicit ports', () => {
1347
1349
  });
1348
1350
 
1349
1351
  it('stop --port can recover a matched pid-file instance whose HTTP endpoint is unresponsive', async () => {
1350
- await withTempOpenChamberDataDir(async () => {
1352
+ await withTempAiWorkerDataDir(async () => {
1351
1353
  const port = await allocateLoopbackPort();
1352
- const child = spawnOpenChamberLikeHungServer(port);
1354
+ const child = spawnAiWorkerLikeHungServer(port);
1353
1355
  const pidFile = await getPidFilePath(port);
1354
1356
  const instanceFile = await getInstanceFilePath(port);
1355
1357
  try {
@@ -1369,8 +1371,8 @@ describe('lifecycle commands with unmanaged explicit ports', () => {
1369
1371
  });
1370
1372
 
1371
1373
  it('plain stop ignores a stale CLI registry entry that resolves to desktop runtime', async () => {
1372
- await withTempOpenChamberDataDir(async () => {
1373
- const server = await startMockOpenChamberServer({ runtime: 'desktop' });
1374
+ await withTempAiWorkerDataDir(async () => {
1375
+ const server = await startMockAiWorkerServer({ runtime: 'desktop' });
1374
1376
  const child = spawn('sleep', ['30'], { stdio: 'ignore' });
1375
1377
  const pidFile = await getPidFilePath(server.port);
1376
1378
  const instanceFile = await getInstanceFilePath(server.port);
@@ -1392,8 +1394,8 @@ describe('lifecycle commands with unmanaged explicit ports', () => {
1392
1394
  });
1393
1395
 
1394
1396
  it('restart --port restarts a live unmanaged server through the shared explicit-port discovery path', async () => {
1395
- await withTempOpenChamberDataDir(async () => {
1396
- const server = await startMockOpenChamberServer();
1397
+ await withTempAiWorkerDataDir(async () => {
1398
+ const server = await startMockAiWorkerServer();
1397
1399
  const calls = [];
1398
1400
  const host = '127.0.0.1';
1399
1401
  try {
@@ -1426,19 +1428,19 @@ describe('lifecycle commands with unmanaged explicit ports', () => {
1426
1428
  describe('Windows startup task command builder', () => {
1427
1429
  it('default-path length stays under 200 chars', () => {
1428
1430
  const cmd = buildWindowsStartupTaskCommand(
1429
- 'C:\\Users\\test\\.config\\openchamber\\bin\\OpenChamber.ps1'
1431
+ 'C:\\Users\\test\\.config\\aiworker\\bin\\AiWorker.ps1'
1430
1432
  );
1431
1433
  expect(cmd).toMatch(/^powershell\.exe -NoProfile -ExecutionPolicy Bypass -File /);
1432
1434
  expect(cmd.length).toBeLessThan(200);
1433
1435
  });
1434
1436
 
1435
1437
  it('worst-case long path stays under 261-char Task Scheduler ceiling', () => {
1436
- // Build a wrapper path >= 180 chars (simulates long OPENCHAMBER_DATA_DIR)
1438
+ // Build a wrapper path >= 180 chars (simulates long AIWORKER_DATA_DIR)
1437
1439
  // Overhead = 57 chars (prefix + closing quote), so max wrapper for <261 total is 203
1438
1440
  const longPath =
1439
1441
  'C:\\Users\\' +
1440
1442
  'a'.repeat(139) +
1441
- '\\.config\\openchamber\\bin\\OpenChamber.ps1';
1443
+ '\\.config\\aiworker\\bin\\AiWorker.ps1';
1442
1444
  expect(longPath.length).toBeGreaterThanOrEqual(180);
1443
1445
 
1444
1446
  const cmd = buildWindowsStartupTaskCommand(longPath);
@@ -1456,3 +1458,93 @@ describe('Windows startup task command builder', () => {
1456
1458
  expect(cmd).not.toContain('-Command ');
1457
1459
  });
1458
1460
  });
1461
+
1462
+ describe('startup command lingering output', () => {
1463
+ const linuxStatus = (lingerEnabled, lingerUser = 'alice') => ({
1464
+ supported: true,
1465
+ platform: 'linux',
1466
+ enabled: true,
1467
+ active: true,
1468
+ activeState: 'active',
1469
+ servicePath: '/home/alice/.config/systemd/user/openchamber.service',
1470
+ lingerEnabled,
1471
+ lingerUser,
1472
+ });
1473
+
1474
+ const dependenciesFor = (status) => ({
1475
+ getStartupStatus: () => status,
1476
+ enableStartupService: () => status,
1477
+ disableStartupService: () => status,
1478
+ });
1479
+
1480
+ const runCommand = (status, options, action) => startupCommand(options, action, dependenciesFor(status));
1481
+
1482
+ it.each([
1483
+ ['enable', true, 'ok', undefined],
1484
+ ['enable', false, 'warning', 'LINGER_DISABLED'],
1485
+ ['enable', null, 'warning', 'LINGER_UNKNOWN'],
1486
+ ['status', true, 'ok', undefined],
1487
+ ['status', false, 'warning', 'LINGER_DISABLED'],
1488
+ ['status', null, 'warning', 'LINGER_UNKNOWN'],
1489
+ ])('reports %s with Linux linger=%s as JSON-only output', async (action, lingerEnabled, expectedStatus, warningCode) => {
1490
+ const output = await captureStdout(() => runCommand(linuxStatus(lingerEnabled), { json: true }, action));
1491
+ const payload = JSON.parse(output);
1492
+
1493
+ expect(payload.status).toBe(expectedStatus);
1494
+ expect(payload.action).toBe(action);
1495
+ expect(payload.lingerEnabled).toBe(lingerEnabled);
1496
+ expect(payload.messages?.[0]?.code).toBe(warningCode);
1497
+ });
1498
+
1499
+ it.each([
1500
+ ['enable', true, 'yes'],
1501
+ ['enable', false, 'no'],
1502
+ ['enable', null, 'unknown'],
1503
+ ['status', true, 'yes'],
1504
+ ['status', false, 'no'],
1505
+ ['status', null, 'unknown'],
1506
+ ])('reports %s with Linux linger=%s in one quiet result line', async (action, lingerEnabled, label) => {
1507
+ const output = await captureStdout(() => runCommand(linuxStatus(lingerEnabled), { quiet: true }, action));
1508
+
1509
+ expect(output.split('\n')).toHaveLength(2);
1510
+ expect(output).toContain(` linger:${label}\n`);
1511
+ expect(output).not.toContain('loginctl');
1512
+ });
1513
+
1514
+ it.each([true, false])('warns with an actionable command in human TTY=%s output', async (isTTY) => {
1515
+ const descriptor = Object.getOwnPropertyDescriptor(process.stdout, 'isTTY');
1516
+ Object.defineProperty(process.stdout, 'isTTY', { configurable: true, value: isTTY });
1517
+ try {
1518
+ const output = await captureStdout(() => runCommand(linuxStatus(false), {}, 'enable'));
1519
+
1520
+ expect(output).toContain('[LINGER_DISABLED]');
1521
+ expect(output).toContain('sudo loginctl enable-linger alice');
1522
+ } finally {
1523
+ if (descriptor) Object.defineProperty(process.stdout, 'isTTY', descriptor);
1524
+ else delete process.stdout.isTTY;
1525
+ }
1526
+ });
1527
+
1528
+ it('reports unknown state without inventing a user when detection is unavailable', async () => {
1529
+ const output = await captureStdout(() => runCommand(linuxStatus(null, null), {}, 'status'));
1530
+
1531
+ expect(output).toContain('[LINGER_UNKNOWN]');
1532
+ expect(output).toContain('loginctl show-user "$USER" -p Linger');
1533
+ });
1534
+
1535
+ it('reports disabled-service linger state without warning or remediation', async () => {
1536
+ const output = await captureStdout(() => runCommand({ ...linuxStatus(false), enabled: false }, {}, 'status'));
1537
+
1538
+ expect(output).toContain('user lingering is disabled');
1539
+ expect(output).not.toContain('[LINGER_DISABLED]');
1540
+ expect(output).not.toContain('loginctl enable-linger');
1541
+ });
1542
+
1543
+ it('does not emit linger guidance for unsupported systems', async () => {
1544
+ await expect(runCommand(
1545
+ { supported: false, platform: 'freebsd', enabled: false, servicePath: null },
1546
+ { json: true },
1547
+ 'status'
1548
+ )).rejects.toMatchObject({ exitCode: EXIT_CODE.USAGE_ERROR });
1549
+ });
1550
+ });
@@ -56,7 +56,7 @@ async function resolveTargetPort(options = {}, deps = {}) {
56
56
  return DEFAULT_PORT;
57
57
  }
58
58
  throw new TunnelCliError(
59
- `Multiple OpenChamber instances are running (ports: ${ports.join(', ')}). Choose one with --port <port>.`,
59
+ `Multiple AiWorker instances are running (ports: ${ports.join(', ')}). Choose one with --port <port>.`,
60
60
  EXIT_CODE.USAGE_ERROR,
61
61
  );
62
62
  }
@@ -66,7 +66,7 @@ async function resolveTargetPort(options = {}, deps = {}) {
66
66
  }
67
67
 
68
68
  throw new TunnelCliError(
69
- 'No running OpenChamber server found. Start one with `openchamber serve`, or pass --port <port>.',
69
+ 'No running AiWorker server found. Start one with `aiworker serve`, or pass --port <port>.',
70
70
  EXIT_CODE.GENERAL_ERROR,
71
71
  );
72
72
  }