@aiworker/web 1.22.0 → 1.23.0
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.
- package/README.md +4 -4
- package/bin/cli.js +14 -4
- package/bin/cli.test.js +165 -73
- package/bin/lib/cli-api-target.js +2 -2
- package/bin/lib/cli-args.js +119 -119
- package/bin/lib/cli-lifecycle.js +9 -9
- package/bin/lib/cli-network.js +3 -3
- package/bin/lib/cli-paths.js +3 -3
- package/bin/lib/cli-ports.js +2 -2
- package/bin/lib/cli-process.js +4 -4
- package/bin/lib/cli-startup.js +64 -15
- package/bin/lib/cli-tunnel-profiles.js +1 -1
- package/bin/lib/cli-tunnel-utils.js +2 -2
- package/bin/lib/commands-connect-url.js +19 -19
- package/bin/lib/commands-lifecycle.js +27 -27
- package/bin/lib/commands-logs.js +5 -5
- package/bin/lib/commands-models.js +1 -1
- package/bin/lib/commands-projects.js +1 -1
- package/bin/lib/commands-schedule.js +1 -1
- package/bin/lib/commands-serve.js +29 -29
- package/bin/lib/commands-session.js +1 -1
- package/bin/lib/commands-startup.js +45 -10
- package/bin/lib/commands-status.js +1 -1
- package/bin/lib/commands-tunnel.js +40 -40
- package/bin/lib/commands-update.js +1 -1
- package/bin/lib/commands-update.test.js +6 -6
- package/dist/assets/{CodeMirrorCommentWidgets-B3u7UIcE.js → CodeMirrorCommentWidgets-B1Gizi3a.js} +1 -1
- package/dist/assets/DiffView-DXjVsEOw.js +4 -0
- package/dist/assets/DirtyBranchSwitchDialog-aig6zJjg.js +1 -0
- package/dist/assets/FilesView-CJdG0-wk.js +17 -0
- package/dist/assets/GitView-BXsS3jG6.js +6 -0
- package/dist/assets/{JsonTreeView-B0BdZEHG.js → JsonTreeView-D_hpXBnF.js} +1 -1
- package/dist/assets/LinearIssuesView-BoUiLQG1.js +1 -0
- package/dist/assets/MarkdownImageGallery-B_B_a9KS.js +1 -0
- package/dist/assets/MarkdownRendererImpl-xgyyLiBM.js +12 -0
- package/dist/assets/OnboardingScreen-DIp84OWt.js +1 -0
- package/dist/assets/{PatchDiff-DvfqDql7.js → PatchDiff-8p6nLJaU.js} +1 -1
- package/dist/assets/PierreDiffViewer-DjC8nTk9.js +161 -0
- package/dist/assets/PlanView-CJTmOF6I.js +5 -0
- package/dist/assets/SettingsView-DD-JqIJx.js +28 -0
- package/dist/assets/{SettingsWindow-i45U1Cy1.js → SettingsWindow-Cpb4hM6q.js} +1 -1
- package/dist/assets/SymbolsNerdFontMono-Regular-aK5vsLov.woff2 +0 -0
- package/dist/assets/{ToolOutputDialog-BTwyh5OF.js → ToolOutputDialog-DfaKZXNU.js} +6 -6
- package/dist/assets/ToolPartDiffPreview-DtZLzrSK.js +8 -0
- package/dist/assets/{VirtualizedFileDiff-DD8lDVej.js → VirtualizedFileDiff-C8i9HpTB.js} +1 -1
- package/dist/assets/WalkthroughView-DeKMvZlL.js +4 -0
- package/dist/assets/{computeVirtualFileMetrics-BMIRgMHv.js → computeVirtualFileMetrics-BBI7ZwrC.js} +2 -2
- package/dist/assets/contextPanelEmbeddedChat-BdA6bdky.js +1 -0
- package/dist/assets/de-DCrsQ5zS.js +10 -0
- package/dist/assets/es-Dwv4YfH6.js +16 -0
- package/dist/assets/fr-BCWg4Cnx.js +14 -0
- package/dist/assets/ghostty-vt-DdA0Zryv.wasm +0 -0
- package/dist/assets/index-B68h5S5B.css +1 -0
- package/dist/assets/index-DVwMarHI.js +39 -0
- package/dist/assets/{index-CODwDsU_.js → index-jXSK5RrB.js} +1 -1
- package/dist/assets/{isDiffPlainText-BqayB8d3.js → isDiffPlainText-B_x_rVon.js} +1 -1
- package/dist/assets/{isFilePlainText-QfoiKJNY.js → isFilePlainText-DW_xMer1.js} +1 -1
- package/dist/assets/ja-Bruw3RYC.js +16 -0
- package/dist/assets/ko-idhXGF8j.js +16 -0
- package/dist/assets/main-BkyaQhJX.js +930 -0
- package/dist/assets/{main-C5DVOxc6.js → main-CzdPuL0s.js} +2 -2
- package/dist/assets/markdownCore-Cn4Tyejo.js +5 -0
- package/dist/assets/{miniChat-DUJ4irZc.js → miniChat-CCkqKOLp.js} +2 -2
- package/dist/assets/{mobile-CcaxB0n4.js → mobile-mvxTo055.js} +2 -2
- package/dist/assets/patchFileDiff-Csk4iNUi.js +13 -0
- package/dist/assets/pl-CGZWUqZJ.js +16 -0
- package/dist/assets/pt-BR-B8V7u7tA.js +16 -0
- package/dist/assets/renderElectronMiniChatApp-BxoyujA5.js +2 -0
- package/dist/assets/renderMobileApp-B48CsP4r.js +25 -0
- package/dist/assets/runtimeEndpointReset-Bg5gx18H.js +17 -0
- package/dist/assets/scheduledTasksApi-BW0Etzwz.js +1 -0
- package/dist/assets/{shikiHighlight-DYOWuY65.js → shikiHighlight-CRl0SUC9.js} +1 -1
- package/dist/assets/surface-oMvhsog3.js +1 -0
- package/dist/assets/tr-BK_KiO2V.js +7 -0
- package/dist/assets/uk-CG74xV8N.js +16 -0
- package/dist/assets/useAppFontEffects-CPKeOpUo.js +7284 -0
- package/dist/assets/useGitComparison-DH220WmO.js +1 -0
- package/dist/assets/useInlineCommentController-BiWz4AVb.js +2 -0
- package/dist/assets/useRootScrollLock-BS4-kr7P.js +1 -0
- package/dist/assets/{vendor-base-ui-BeMD8X_w.js → vendor-base-ui-DdV8vhHn.js} +1 -1
- package/dist/assets/{vendor-codemirror-language-data-DFZik9R2.js → vendor-codemirror-language-data-Bg4AEeCr.js} +2 -2
- package/dist/assets/vendor-zod-BPAANqvH.js +39 -0
- package/dist/assets/{web-components-Bhg83tjf.js → web-components-z7hfnS8n.js} +1 -1
- package/dist/assets/zh-CN-T4AXofZI.js +16 -0
- package/dist/assets/zh-TW-Dte40sxp.js +16 -0
- package/dist/index.html +21 -59
- package/dist/mini-chat.html +7 -7
- package/dist/mobile.html +5 -5
- package/package.json +3 -4
- package/server/index.d.ts +15 -0
- package/server/index.js +158 -89
- package/server/lib/agent-memory/actions.js +2 -2
- package/server/lib/agent-memory/feature-flag.js +1 -1
- package/server/lib/agent-memory/feature-flag.test.js +8 -8
- package/server/lib/agent-memory/routes.js +2 -2
- package/server/lib/agent-tool/runtime.js +37 -54
- package/server/lib/agent-tool/runtime.test.js +59 -59
- package/server/lib/browser-control/broker.js +3 -3
- package/server/lib/browser-control/broker.test.js +1 -1
- package/server/lib/changelog/update-notes.js +82 -0
- package/server/lib/changelog/update-notes.test.js +59 -0
- package/server/lib/client-auth/remote-clients.test.js +5 -5
- package/server/lib/context-obligatory/runtime.js +7 -7
- package/server/lib/context-obligatory/runtime.test.js +5 -5
- package/server/lib/data-dir-migration.js +40 -0
- package/server/lib/data-dir-migration.test.js +59 -0
- package/server/lib/dev-servers/parse.js +2 -2
- package/server/lib/dev-servers/parse.test.js +2 -2
- package/server/lib/dev-servers/routes.js +1 -1
- package/server/lib/dev-tunnel/DOCUMENTATION.md +13 -4
- package/server/lib/dev-tunnel/client.js +1 -1
- package/server/lib/dev-tunnel/runtime.js +5 -5
- package/server/lib/dev-tunnel/tunnel.test.js +21 -1
- package/server/lib/dictation/local/model-catalog.js +1 -1
- package/server/lib/dictation/local/worker-process.js +2 -2
- package/server/lib/event-stream/directory-ws-bridge.js +1 -1
- package/server/lib/event-stream/global-ws-bridge.js +1 -1
- package/server/lib/event-stream/protocol.test.js +4 -4
- package/server/lib/event-stream/runtime.test.js +18 -18
- package/server/lib/fs/DOCUMENTATION.md +5 -0
- package/server/lib/fs/routes.js +68 -26
- package/server/lib/fs/routes.test.js +208 -22
- package/server/lib/git/DOCUMENTATION.md +32 -6
- package/server/lib/git/identity-storage.js +1 -1
- package/server/lib/git/issue-2746-longpaths.test.js +4 -4
- package/server/lib/git/routes.js +41 -5
- package/server/lib/git/service.js +300 -224
- package/server/lib/git/service.test.js +596 -28
- package/server/lib/github/auth.js +8 -8
- package/server/lib/github/pr-status.js +1 -1
- package/server/lib/github/routes.js +2 -2
- package/server/lib/inherited-env.js +17 -10
- package/server/lib/inherited-env.test.js +10 -11
- package/server/lib/linear/auth.js +8 -8
- package/server/lib/linear/auth.test.js +24 -24
- package/server/lib/linear/issues.test.js +6 -6
- package/server/lib/linear/mapping.test.js +4 -4
- package/server/lib/linear/oauth.js +2 -2
- package/server/lib/linear/oauth.test.js +14 -14
- package/server/lib/linear/routes.js +5 -5
- package/server/lib/linear/routes.test.js +16 -16
- package/server/lib/linear/status-runtime.test.js +9 -9
- package/server/lib/linear/status.js +1 -1
- package/server/lib/linear/status.test.js +15 -15
- package/server/lib/linear/teams.test.js +4 -4
- package/server/lib/magic-prompts/routes.js +2 -2
- package/server/lib/mcp-reconnect/DOCUMENTATION.md +55 -0
- package/server/lib/mcp-reconnect/runtime.js +122 -0
- package/server/lib/mcp-reconnect/runtime.test.js +140 -0
- package/server/lib/message-queue/DOCUMENTATION.md +161 -0
- package/server/lib/message-queue/runtime.js +870 -0
- package/server/lib/message-queue/runtime.test.js +482 -0
- package/server/lib/network-defaults.js +23 -0
- package/server/lib/network-defaults.test.js +52 -0
- package/server/lib/notifications/apns-runtime.js +17 -17
- package/server/lib/notifications/apns-runtime.test.js +11 -11
- package/server/lib/notifications/emitter-runtime.js +1 -1
- package/server/lib/notifications/emitter-runtime.test.js +1 -1
- package/server/lib/notifications/push-runtime.js +7 -7
- package/server/lib/notifications/routes.js +1 -1
- package/server/lib/notifications/runtime.js +1 -1
- package/server/lib/openchamber-control/action-resolution.test.js +10 -10
- package/server/lib/openchamber-control/actions.js +24 -24
- package/server/lib/openchamber-control/error.js +4 -4
- package/server/lib/openchamber-control/routes.js +2 -2
- package/server/lib/openchamber-control/routes.test.js +5 -5
- package/server/lib/openchamber-control/screenshots.js +1 -1
- package/server/lib/openchamber-control/screenshots.test.js +1 -1
- package/server/lib/openchamber-control/service.js +50 -50
- package/server/lib/openchamber-control/service.test.js +5 -5
- package/server/lib/openchamber-sessions/routes.js +124 -22
- package/server/lib/openchamber-sessions/routes.test.js +99 -11
- package/server/lib/opencode/DOCUMENTATION.md +30 -6
- package/server/lib/opencode/auth.js +1 -1
- package/server/lib/opencode/bootstrap-runtime.js +8 -6
- package/server/lib/opencode/cli-options.js +8 -8
- package/server/lib/opencode/config-paths.test.js +116 -0
- package/server/lib/opencode/core-routes.js +8 -7
- package/server/lib/opencode/core-routes.test.js +11 -11
- package/server/lib/opencode/env-config.js +5 -5
- package/server/lib/opencode/env-config.test.js +7 -7
- package/server/lib/opencode/env-runtime.js +10 -10
- package/server/lib/opencode/env-runtime.test.js +18 -18
- package/server/lib/opencode/feature-routes-runtime.js +19 -12
- package/server/lib/opencode/hmr-state-runtime.js +2 -2
- package/server/lib/opencode/hmr-state-runtime.test.js +1 -1
- package/server/lib/opencode/input-history-scope.js +14 -0
- package/server/lib/opencode/lifecycle.js +8 -8
- package/server/lib/opencode/lifecycle.test.js +4 -4
- package/server/lib/opencode/managed-plugin-config.js +35 -0
- package/server/lib/opencode/managed-process-registry.js +3 -3
- package/server/lib/opencode/mcp-oauth-callback.test.js +2 -2
- package/server/lib/opencode/openchamber-routes.js +79 -19
- package/server/lib/opencode/openchamber-routes.test.js +139 -12
- package/server/lib/opencode/plugins.js +2 -2
- package/server/lib/opencode/plugins.test.js +1 -1
- package/server/lib/opencode/project-icon-routes.js +2 -2
- package/server/lib/opencode/project-icon-routes.test.js +1 -1
- package/server/lib/opencode/providers.js +44 -2
- package/server/lib/opencode/providers.test.js +131 -4
- package/server/lib/opencode/proxy.js +2 -2
- package/server/lib/opencode/pwa-manifest-routes.js +1 -1
- package/server/lib/opencode/restart-session-recovery.test.js +1 -1
- package/server/lib/opencode/routes-upgrade.test.js +4 -4
- package/server/lib/opencode/routes.js +19 -17
- package/server/lib/opencode/server-startup-runtime.js +6 -6
- package/server/lib/opencode/session-runtime.js +3 -3
- package/server/lib/opencode/session-runtime.test.js +6 -6
- package/server/lib/opencode/settings-files.js +214 -0
- package/server/lib/opencode/settings-helpers.js +116 -44
- package/server/lib/opencode/settings-helpers.test.js +354 -12
- package/server/lib/opencode/settings-registry.json +747 -0
- package/server/lib/opencode/settings-runtime.js +141 -20
- package/server/lib/opencode/settings-runtime.test.js +191 -4
- package/server/lib/opencode/shared.js +5 -2
- package/server/lib/opencode/shared.test.js +7 -7
- package/server/lib/opencode/shutdown-runtime.js +2 -0
- package/server/lib/opencode/skill-routes.js +2 -1
- package/server/lib/opencode/snippets.js +1 -2
- package/server/lib/opencode/startup-performance.js +1 -1
- package/server/lib/opencode/startup-performance.test.js +6 -6
- package/server/lib/opencode/static-routes-runtime.js +8 -8
- package/server/lib/opencode/static-routes-runtime.test.js +7 -7
- package/server/lib/opencode/upgrade-capability.js +2 -2
- package/server/lib/opencode/upgrade-capability.test.js +3 -3
- package/server/lib/package-manager.js +17 -42
- package/server/lib/package-manager.test.js +19 -19
- package/server/lib/permission-auto-accept/runtime.js +1 -1
- package/server/lib/project-context/DOCUMENTATION.md +25 -1
- package/server/lib/project-context/routes.http.test.js +18 -0
- package/server/lib/project-context/routes.js +16 -1
- package/server/lib/project-context/runtime.js +248 -23
- package/server/lib/project-context/runtime.test.js +106 -3
- package/server/lib/projects/DOCUMENTATION.md +76 -0
- package/server/lib/projects/project-config.js +144 -11
- package/server/lib/projects/project-id.js +17 -0
- package/server/lib/projects/project-setup.js +409 -0
- package/server/lib/projects/project-setup.test.js +557 -0
- package/server/lib/projects/routes.js +59 -0
- package/server/lib/quota/DOCUMENTATION.md +40 -2
- package/server/lib/quota/credentials/providers.js +4 -0
- package/server/lib/quota/credentials/store.js +4 -4
- package/server/lib/quota/credentials/store.test.js +8 -8
- package/server/lib/quota/index.js +1 -0
- package/server/lib/quota/providers/cline-pass.js +125 -0
- package/server/lib/quota/providers/cline-pass.test.js +103 -0
- package/server/lib/quota/providers/exe-dev.js +75 -0
- package/server/lib/quota/providers/exe-dev.test.js +47 -0
- package/server/lib/quota/providers/hyper.js +118 -0
- package/server/lib/quota/providers/hyper.test.js +126 -0
- package/server/lib/quota/providers/index.js +22 -0
- package/server/lib/quota/providers/neuralwatt.js +3 -6
- package/server/lib/quota/providers/neuralwatt.test.js +7 -7
- package/server/lib/quota/providers/ollama-cloud.js +32 -1
- package/server/lib/quota/providers/ollama-cloud.test.js +33 -1
- package/server/lib/quota/providers/opencode-go.js +3 -2
- package/server/lib/quota/providers/opencode-go.test.js +35 -6
- package/server/lib/quota/providers/openrouter.js +119 -24
- package/server/lib/quota/providers/openrouter.test.js +330 -0
- package/server/lib/quota/providers/xai.js +1 -1
- package/server/lib/quota/routes.js +2 -0
- package/server/lib/quota/utils/auth.js +1 -1
- package/server/lib/relay/DOCUMENTATION.md +56 -1
- package/server/lib/relay/cross-compat.test.js +26 -0
- package/server/lib/relay/downstream-scheduler.js +154 -0
- package/server/lib/relay/downstream-scheduler.test.js +162 -0
- package/server/lib/relay/e2ee.js +10 -8
- package/server/lib/relay/flow-control.test.js +177 -0
- package/server/lib/relay/host-client.js +38 -9
- package/server/lib/relay/host-client.test.js +9 -1
- package/server/lib/relay/host-lock.js +1 -1
- package/server/lib/relay/service.js +5 -5
- package/server/lib/relay/tunnel-codec.js +9 -0
- package/server/lib/relay/tunnel-host.js +69 -18
- package/server/lib/relay/tunnel-host.test.js +9 -1
- package/server/lib/scheduled-tasks/issue-2710-double-execution.test.js +2 -2
- package/server/lib/scheduled-tasks/routes.js +5 -5
- package/server/lib/scheduled-tasks/service.js +25 -25
- package/server/lib/scheduled-tasks/service.test.js +1 -1
- package/server/lib/security/bind-host.js +4 -4
- package/server/lib/security/bind-host.test.js +1 -1
- package/server/lib/security/request-security.js +11 -5
- package/server/lib/security/request-security.test.js +14 -14
- package/server/lib/session-assist/runtime.js +15 -18
- package/server/lib/session-folders/routes.js +2 -2
- package/server/lib/session-folders/routes.test.js +8 -8
- package/server/lib/session-goal/DOCUMENTATION.md +20 -7
- package/server/lib/session-goal/create.js +4 -2
- package/server/lib/session-goal/create.test.js +1 -1
- package/server/lib/session-goal/objectives.js +4 -4
- package/server/lib/session-goal/routes.js +1 -1
- package/server/lib/session-goal/runtime.js +91 -30
- package/server/lib/session-goal/runtime.test.js +428 -2
- package/server/lib/session-knowledge/runtime.js +11 -11
- package/server/lib/session-knowledge/runtime.test.js +5 -5
- package/server/lib/skills-catalog/DOCUMENTATION.md +1 -1
- package/server/lib/skills-catalog/cache.test.js +2 -2
- package/server/lib/skills-catalog/disk-cache.js +5 -5
- package/server/lib/skills-catalog/github-meta.test.js +2 -2
- package/server/lib/skills-catalog/install.js +3 -2
- package/server/lib/small-model/DOCUMENTATION.md +7 -2
- package/server/lib/small-model/call.js +18 -7
- package/server/lib/small-model/call.test.js +58 -6
- package/server/lib/small-model/index.js +12 -16
- package/server/lib/small-model/index.test.js +1 -1
- package/server/lib/small-model/resolve.js +1 -1
- package/server/lib/small-model/resolve.test.js +1 -1
- package/server/lib/small-model/routes.js +2 -1
- package/server/lib/small-model/runtime-providers.js +15 -7
- package/server/lib/small-model/runtime-providers.test.js +7 -1
- package/server/lib/system-prompt/runtime.js +3 -22
- package/server/lib/system-prompt/runtime.test.js +3 -3
- package/server/lib/terminal/DOCUMENTATION.md +14 -10
- package/server/lib/terminal/runtime.js +190 -31
- package/server/lib/terminal/runtime.test.js +572 -38
- package/server/lib/terminal/shells.js +20 -3
- package/server/lib/terminal/shells.test.js +33 -2
- package/server/lib/tts/base-url.js +3 -3
- package/server/lib/tts/routes.test.js +20 -20
- package/server/lib/ui-auth/ui-auth.js +12 -9
- package/server/lib/ui-auth/ui-auth.test.js +19 -3
- package/server/lib/ui-auth/ui-passkeys.js +7 -7
- package/server/lib/walkthrough/DOCUMENTATION.md +33 -14
- package/server/lib/walkthrough/index.js +1 -0
- package/server/lib/walkthrough/jobs.test.js +1 -1
- package/server/lib/walkthrough/language.test.js +1 -1
- package/server/lib/walkthrough/model-settings.js +11 -15
- package/server/lib/walkthrough/model-settings.test.js +1 -1
- package/server/lib/walkthrough/prompt.js +3 -1
- package/server/lib/walkthrough/pull-request.test.js +5 -5
- package/server/lib/walkthrough/reproduce-2607.test.js +2 -2
- package/server/lib/walkthrough/routes.test.js +26 -5
- package/server/lib/walkthrough/sources.js +23 -2
- package/server/lib/walkthrough/store.js +3 -3
- package/server/lib/walkthrough/store.test.js +1 -1
- package/server/opencode-proxy.test.js +2 -2
- package/server/proxy-headers.js +1 -1
- package/server/sse-routes.test.js +4 -4
- package/README.md.bak +0 -250
- package/bin/lib/DOCUMENTATION.md.bak +0 -163
- package/dist/assets/CommitSection-SGBCAW0w.js +0 -1
- package/dist/assets/DiffView-DluiRSla.js +0 -4
- package/dist/assets/FilesView-Bdq8ppva.js +0 -17
- package/dist/assets/GitView-Znn7VJcP.js +0 -6
- package/dist/assets/LinearIssuesView-jP-hXyac.js +0 -1
- package/dist/assets/MarkdownImageGallery-ClOvuZxC.js +0 -1
- package/dist/assets/MarkdownRendererImpl-Dt9mjTRN.js +0 -12
- package/dist/assets/OnboardingScreen-D2DG7K6b.js +0 -1
- package/dist/assets/PierreDiffViewer-B7m3f0d7.js +0 -157
- package/dist/assets/PlanView-B0F3BtPZ.js +0 -5
- package/dist/assets/SettingsView-BBW-S-gh.js +0 -28
- package/dist/assets/ToolPartDiffPreview-CUNe28U1.js +0 -8
- package/dist/assets/WalkthroughView-egQgxel3.js +0 -4
- package/dist/assets/contextPanelEmbeddedChat-C3fjDbdg.js +0 -1
- package/dist/assets/de-C1P6X5Rs.js +0 -9
- package/dist/assets/es-CDgaF1_t.js +0 -15
- package/dist/assets/fr-Bgxqvvz_.js +0 -13
- package/dist/assets/index-C57jT0Sa.css +0 -1
- package/dist/assets/index-DW_E3rnL.js +0 -7
- package/dist/assets/ja-BDRrEcNP.js +0 -15
- package/dist/assets/ko-Ba8sQV79.js +0 -15
- package/dist/assets/main-Bv5Pkngh.js +0 -928
- package/dist/assets/markdownCore-CZwzz5gw.js +0 -3
- package/dist/assets/patchFileDiff-yNfWXN4E.js +0 -10
- package/dist/assets/pl-Dioz29BI.js +0 -15
- package/dist/assets/pt-BR-DIs6ElwV.js +0 -15
- package/dist/assets/renderElectronMiniChatApp-BcKLHXKe.js +0 -2
- package/dist/assets/renderMobileApp-D9yQJy0L.js +0 -25
- package/dist/assets/runtimeEndpointReset-CjhvxLH0.js +0 -16
- package/dist/assets/scheduledTasksApi-DLW0mkQK.js +0 -1
- package/dist/assets/tr-DFnMlPxY.js +0 -6
- package/dist/assets/uk-ZrCNjM7Y.js +0 -15
- package/dist/assets/useAppFontEffects-CjrntdL0.js +0 -7310
- package/dist/assets/useInlineCommentController-CDEuSlPH.js +0 -2
- package/dist/assets/useRootScrollLock-BHYPkrLv.js +0 -1
- package/dist/assets/vendor-ghostty-web-CrxinGGH.js +0 -13
- package/dist/assets/vendor-zod-BLfBSgBh.js +0 -39
- package/dist/assets/zh-CN-iv_AV4EC.js +0 -15
- package/dist/assets/zh-TW-CzEUk38j.js +0 -15
- package/server/index.d.ts.bak +0 -39
- package/server/lib/agent-tool/DOCUMENTATION.md.bak +0 -119
- package/server/lib/browser-control/DOCUMENTATION.md.bak +0 -50
- package/server/lib/context-obligatory/DOCUMENTATION.md.bak +0 -19
- package/server/lib/dev-tunnel/DOCUMENTATION.md.bak +0 -57
- package/server/lib/dictation/DOCUMENTATION.md.bak +0 -100
- package/server/lib/event-stream/DOCUMENTATION.md.bak +0 -62
- package/server/lib/fs/DOCUMENTATION.md.bak +0 -47
- package/server/lib/git/DOCUMENTATION.md.bak +0 -193
- package/server/lib/github/DOCUMENTATION.md.bak +0 -183
- package/server/lib/linear/DOCUMENTATION.md.bak +0 -97
- package/server/lib/linear/OAUTH-BROKER-HANDOFF.md.bak +0 -91
- package/server/lib/markdown-image-grants/DOCUMENTATION.md.bak +0 -40
- package/server/lib/notifications/APNS.md.bak +0 -135
- package/server/lib/notifications/DOCUMENTATION.md.bak +0 -138
- package/server/lib/openchamber-control/DOCUMENTATION.md.bak +0 -64
- package/server/lib/opencode/DOCUMENTATION.md.bak +0 -431
- package/server/lib/opencode/managed-process-registry.d.ts.bak +0 -13
- package/server/lib/opencode/provider-env-aliases.d.ts.bak +0 -3
- package/server/lib/permission-auto-accept/DOCUMENTATION.md.bak +0 -34
- package/server/lib/project-context/DOCUMENTATION.md.bak +0 -160
- package/server/lib/quota/DOCUMENTATION.md.bak +0 -123
- package/server/lib/relay/DOCUMENTATION.md.bak +0 -100
- package/server/lib/scheduled-tasks/DOCUMENTATION.md.bak +0 -182
- package/server/lib/session-assist/DOCUMENTATION.md.bak +0 -66
- package/server/lib/session-goal/DOCUMENTATION.md.bak +0 -213
- package/server/lib/session-knowledge/DOCUMENTATION.md.bak +0 -89
- package/server/lib/skills-catalog/DOCUMENTATION.md.bak +0 -151
- package/server/lib/small-model/DOCUMENTATION.md.bak +0 -212
- package/server/lib/system-prompt/DOCUMENTATION.md.bak +0 -36
- package/server/lib/terminal/DOCUMENTATION.md.bak +0 -50
- package/server/lib/text/DOCUMENTATION.md.bak +0 -35
- package/server/lib/tts/DOCUMENTATION.md.bak +0 -147
- package/server/lib/tunnels/DOCUMENTATION.md.bak +0 -21
- package/server/lib/ui-auth/DOCUMENTATION.md.bak +0 -44
- package/server/lib/walkthrough/DOCUMENTATION.md.bak +0 -411
|
@@ -5,10 +5,10 @@ function resolveSystemdServiceUnit(environment) {
|
|
|
5
5
|
return null;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
const configuredUnit = typeof environment.
|
|
9
|
-
? environment.
|
|
8
|
+
const configuredUnit = typeof environment.AIWORKER_SYSTEMD_UNIT === 'string'
|
|
9
|
+
? environment.AIWORKER_SYSTEMD_UNIT.trim()
|
|
10
10
|
: '';
|
|
11
|
-
const unit = configuredUnit || '
|
|
11
|
+
const unit = configuredUnit || 'aiworker.service';
|
|
12
12
|
return SYSTEMD_SERVICE_UNIT_PATTERN.test(unit) ? unit : null;
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -16,24 +16,26 @@ function quotePosixShell(value) {
|
|
|
16
16
|
return `'${String(value).replace(/'/g, "'\\''")}'`;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export const
|
|
19
|
+
export const registerAiWorkerRoutes = (app, dependencies) => {
|
|
20
20
|
const {
|
|
21
21
|
fs,
|
|
22
22
|
path,
|
|
23
23
|
process,
|
|
24
24
|
server,
|
|
25
25
|
__dirname,
|
|
26
|
-
|
|
26
|
+
aiworkerDataDir,
|
|
27
27
|
modelsDevApiUrl,
|
|
28
28
|
modelsMetadataCacheTtl,
|
|
29
29
|
readSettingsFromDiskMigrated,
|
|
30
30
|
fetchFreeZenModels,
|
|
31
31
|
getCachedZenModels,
|
|
32
|
+
desktopUpdater,
|
|
32
33
|
} = dependencies;
|
|
33
34
|
|
|
35
|
+
let desktopRestartError = null;
|
|
36
|
+
|
|
34
37
|
app.get('/api/openchamber/update-check', async (req, res) => {
|
|
35
38
|
try {
|
|
36
|
-
const { checkForUpdates } = await import('../package-manager.js');
|
|
37
39
|
const parseString = (value) => (typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined);
|
|
38
40
|
const parseReportUsage = (value) => {
|
|
39
41
|
if (typeof value !== 'string') return true;
|
|
@@ -49,8 +51,7 @@ export const registerOpenChamberRoutes = (app, dependencies) => {
|
|
|
49
51
|
return 'desktop';
|
|
50
52
|
};
|
|
51
53
|
const userAgent = typeof req.headers['user-agent'] === 'string' ? req.headers['user-agent'] : '';
|
|
52
|
-
|
|
53
|
-
const updateInfo = await checkForUpdates({
|
|
54
|
+
const updateRequest = {
|
|
54
55
|
appType: parseString(req.query.appType),
|
|
55
56
|
deviceClass: parseString(req.query.deviceClass) || inferDeviceClass(userAgent),
|
|
56
57
|
platform: parseString(req.query.platform),
|
|
@@ -59,7 +60,31 @@ export const registerOpenChamberRoutes = (app, dependencies) => {
|
|
|
59
60
|
currentVersion: parseString(req.query.currentVersion),
|
|
60
61
|
installId: parseString(req.query.installId),
|
|
61
62
|
reportUsage: parseReportUsage(parseString(req.query.reportUsage)),
|
|
62
|
-
}
|
|
63
|
+
};
|
|
64
|
+
let updateInfo;
|
|
65
|
+
if (process.env.AIWORKER_RUNTIME === 'desktop' && updateRequest.appType === 'web') {
|
|
66
|
+
if (desktopRestartError && req.query.updateStatus === 'true') {
|
|
67
|
+
return res.status(503).json({
|
|
68
|
+
code: 'DESKTOP_UPDATE_RESTART_FAILED',
|
|
69
|
+
error: desktopRestartError,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
if (typeof desktopUpdater?.check !== 'function') {
|
|
73
|
+
return res.status(503).json({
|
|
74
|
+
available: false,
|
|
75
|
+
code: 'DESKTOP_UPDATER_UNAVAILABLE',
|
|
76
|
+
error: 'The desktop updater is not available.',
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
updateInfo = {
|
|
80
|
+
...await desktopUpdater.check(),
|
|
81
|
+
packageManager: 'electron',
|
|
82
|
+
updateOwner: 'electron-updater',
|
|
83
|
+
};
|
|
84
|
+
} else {
|
|
85
|
+
const { checkForUpdates } = await import('../package-manager.js');
|
|
86
|
+
updateInfo = await checkForUpdates(updateRequest);
|
|
87
|
+
}
|
|
63
88
|
res.json(updateInfo);
|
|
64
89
|
} catch (error) {
|
|
65
90
|
console.error('Failed to check for updates:', error);
|
|
@@ -72,6 +97,41 @@ export const registerOpenChamberRoutes = (app, dependencies) => {
|
|
|
72
97
|
|
|
73
98
|
app.post('/api/openchamber/update-install', async (_req, res) => {
|
|
74
99
|
try {
|
|
100
|
+
if (process.env.AIWORKER_RUNTIME === 'desktop') {
|
|
101
|
+
if (typeof desktopUpdater?.install !== 'function' || typeof desktopUpdater?.restart !== 'function') {
|
|
102
|
+
return res.status(503).json({
|
|
103
|
+
code: 'DESKTOP_UPDATER_UNAVAILABLE',
|
|
104
|
+
error: 'The desktop updater is not available.',
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
desktopRestartError = null;
|
|
109
|
+
const updateInfo = await desktopUpdater.install();
|
|
110
|
+
if (!updateInfo?.available) {
|
|
111
|
+
return res.status(400).json({ error: 'No update available' });
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
res.json({
|
|
115
|
+
success: true,
|
|
116
|
+
message: 'Desktop update downloaded, host will restart shortly',
|
|
117
|
+
version: updateInfo.version,
|
|
118
|
+
packageManager: 'electron',
|
|
119
|
+
updateOwner: 'electron-updater',
|
|
120
|
+
autoRestart: true,
|
|
121
|
+
restartManager: 'electron-updater',
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
setImmediate(() => {
|
|
125
|
+
Promise.resolve()
|
|
126
|
+
.then(() => desktopUpdater.restart())
|
|
127
|
+
.catch((error) => {
|
|
128
|
+
desktopRestartError = error instanceof Error ? error.message : 'Failed to restart after desktop update';
|
|
129
|
+
console.error('Failed to restart after desktop update:', error);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
75
135
|
const { spawn: spawnChild, spawnSync } = await import('child_process');
|
|
76
136
|
const {
|
|
77
137
|
checkForUpdates,
|
|
@@ -119,7 +179,7 @@ export const registerOpenChamberRoutes = (app, dependencies) => {
|
|
|
119
179
|
}
|
|
120
180
|
|
|
121
181
|
const currentPort = server.address()?.port || 3000;
|
|
122
|
-
const instanceFilePath = path.join(
|
|
182
|
+
const instanceFilePath = path.join(aiworkerDataDir, 'run', `openchamber-${currentPort}.json`);
|
|
123
183
|
let storedOptions = { port: currentPort, daemon: true };
|
|
124
184
|
try {
|
|
125
185
|
const content = await fs.promises.readFile(instanceFilePath, 'utf8');
|
|
@@ -133,7 +193,7 @@ export const registerOpenChamberRoutes = (app, dependencies) => {
|
|
|
133
193
|
if (isForegroundService) {
|
|
134
194
|
if (!systemdServiceUnit) {
|
|
135
195
|
return res.status(409).json({
|
|
136
|
-
error: 'Foreground servers must be updated by their service manager. Set
|
|
196
|
+
error: 'Foreground servers must be updated by their service manager. Set AIWORKER_SYSTEMD_UNIT when running under systemd, or run aiworker update and restart the service.',
|
|
137
197
|
});
|
|
138
198
|
}
|
|
139
199
|
|
|
@@ -168,7 +228,7 @@ export const registerOpenChamberRoutes = (app, dependencies) => {
|
|
|
168
228
|
|
|
169
229
|
return res.json({
|
|
170
230
|
success: true,
|
|
171
|
-
message: 'Update queued;
|
|
231
|
+
message: 'Update queued; AiWorker will restart after installation completes',
|
|
172
232
|
version: updateInfo.version,
|
|
173
233
|
packageManager: pm,
|
|
174
234
|
autoRestart: true,
|
|
@@ -194,7 +254,7 @@ export const registerOpenChamberRoutes = (app, dependencies) => {
|
|
|
194
254
|
String(storedOptions.port),
|
|
195
255
|
];
|
|
196
256
|
let restartCmdPrimary = restartParts.join(' ');
|
|
197
|
-
let restartCmdFallback = `
|
|
257
|
+
let restartCmdFallback = `aiworker serve --port ${storedOptions.port}`;
|
|
198
258
|
if (storedOptions.host) {
|
|
199
259
|
if (isWindows) {
|
|
200
260
|
const escapedHost = storedOptions.host.replace(/"/g, '""');
|
|
@@ -222,10 +282,10 @@ export const registerOpenChamberRoutes = (app, dependencies) => {
|
|
|
222
282
|
restartCmdFallback += ' --api-only';
|
|
223
283
|
}
|
|
224
284
|
const restartCmd = isForegroundService ? '' : `(${restartCmdPrimary}) || (${restartCmdFallback})`;
|
|
225
|
-
const updateLogPath = path.join(
|
|
285
|
+
const updateLogPath = path.join(aiworkerDataDir, 'update-install.log');
|
|
226
286
|
const logPreamble = [
|
|
227
287
|
'',
|
|
228
|
-
`===
|
|
288
|
+
`=== AiWorker update ${new Date().toISOString()} ===`,
|
|
229
289
|
`currentVersion=${updateInfo.currentVersion || 'unknown'}`,
|
|
230
290
|
`targetVersion=${updateInfo.version || 'unknown'}`,
|
|
231
291
|
`packageManager=${pm}`,
|
|
@@ -262,8 +322,8 @@ export const registerOpenChamberRoutes = (app, dependencies) => {
|
|
|
262
322
|
timeout /t 2 /nobreak >nul
|
|
263
323
|
${updateCmd}
|
|
264
324
|
if %ERRORLEVEL% EQU 0 (
|
|
265
|
-
echo Update successful, restarting
|
|
266
|
-
${restartCmd || 'echo Service manager will restart
|
|
325
|
+
echo Update successful, restarting AiWorker...
|
|
326
|
+
${restartCmd || 'echo Service manager will restart AiWorker.'}
|
|
267
327
|
) else (
|
|
268
328
|
echo Update failed
|
|
269
329
|
exit /b 1
|
|
@@ -274,8 +334,8 @@ export const registerOpenChamberRoutes = (app, dependencies) => {
|
|
|
274
334
|
sleep 2
|
|
275
335
|
${updateCmd}
|
|
276
336
|
if [ $? -eq 0 ]; then
|
|
277
|
-
echo "Update successful, restarting
|
|
278
|
-
${restartCmd || 'echo "Service manager will restart
|
|
337
|
+
echo "Update successful, restarting AiWorker..."
|
|
338
|
+
${restartCmd || 'echo "Service manager will restart AiWorker."'}
|
|
279
339
|
else
|
|
280
340
|
echo "Update failed"
|
|
281
341
|
exit 1
|
|
@@ -16,9 +16,9 @@ vi.mock('../package-manager.js', () => ({
|
|
|
16
16
|
|
|
17
17
|
const childProcess = await import('child_process');
|
|
18
18
|
const packageManager = await import('../package-manager.js');
|
|
19
|
-
const {
|
|
19
|
+
const { registerAiWorkerRoutes } = await import('./openchamber-routes.js');
|
|
20
20
|
|
|
21
|
-
const createApp = ({ environment = {}, storedOptions = {} } = {}) => {
|
|
21
|
+
const createApp = ({ environment = {}, storedOptions = {}, desktopUpdater } = {}) => {
|
|
22
22
|
const app = express();
|
|
23
23
|
const dependencies = {
|
|
24
24
|
fs: {
|
|
@@ -41,15 +41,16 @@ const createApp = ({ environment = {}, storedOptions = {} } = {}) => {
|
|
|
41
41
|
address: () => ({ port: 7897 }),
|
|
42
42
|
},
|
|
43
43
|
__dirname: '/opt/openchamber/server',
|
|
44
|
-
|
|
44
|
+
aiworkerDataDir: '/tmp/openchamber',
|
|
45
45
|
modelsDevApiUrl: 'https://models.example.test',
|
|
46
46
|
modelsMetadataCacheTtl: 0,
|
|
47
47
|
readSettingsFromDiskMigrated: vi.fn(),
|
|
48
48
|
fetchFreeZenModels: vi.fn(),
|
|
49
49
|
getCachedZenModels: vi.fn(),
|
|
50
|
+
desktopUpdater,
|
|
50
51
|
};
|
|
51
52
|
|
|
52
|
-
|
|
53
|
+
registerAiWorkerRoutes(app, dependencies);
|
|
53
54
|
return { app, dependencies };
|
|
54
55
|
};
|
|
55
56
|
|
|
@@ -61,7 +62,7 @@ beforeEach(() => {
|
|
|
61
62
|
packageManager.detectPackageManagerDetails.mockReturnValue({
|
|
62
63
|
packageManager: 'npm',
|
|
63
64
|
});
|
|
64
|
-
packageManager.getUpdateCommand.mockReturnValue('npm install -g @
|
|
65
|
+
packageManager.getUpdateCommand.mockReturnValue('npm install -g @aiworker/web@latest');
|
|
65
66
|
});
|
|
66
67
|
|
|
67
68
|
afterEach(() => {
|
|
@@ -69,14 +70,140 @@ afterEach(() => {
|
|
|
69
70
|
vi.clearAllMocks();
|
|
70
71
|
});
|
|
71
72
|
|
|
72
|
-
describe('
|
|
73
|
+
describe('AiWorker desktop host update route', () => {
|
|
74
|
+
it('reports a restart rejection until the user retries installation', async () => {
|
|
75
|
+
const desktopUpdater = {
|
|
76
|
+
check: vi.fn(async () => ({ available: true, currentVersion: '1.17.0', version: '1.17.1' })),
|
|
77
|
+
install: vi.fn(async () => ({ available: true, version: '1.17.1' })),
|
|
78
|
+
restart: vi.fn().mockRejectedValueOnce(new Error('Signature rejected')).mockResolvedValue(undefined),
|
|
79
|
+
};
|
|
80
|
+
const { app } = createApp({ environment: { AIWORKER_RUNTIME: 'desktop' }, desktopUpdater });
|
|
81
|
+
const logError = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
82
|
+
|
|
83
|
+
await request(app).post('/api/openchamber/update-install').expect(200);
|
|
84
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
85
|
+
await request(app).get('/api/openchamber/update-check?appType=web&reportUsage=false&updateStatus=true').expect(503, {
|
|
86
|
+
code: 'DESKTOP_UPDATE_RESTART_FAILED', error: 'Signature rejected',
|
|
87
|
+
});
|
|
88
|
+
expect(desktopUpdater.check).not.toHaveBeenCalled();
|
|
89
|
+
expect(logError).toHaveBeenCalledOnce();
|
|
90
|
+
// Availability remains reachable after a browser reload, so users can retry.
|
|
91
|
+
await request(app).get('/api/openchamber/update-check?appType=web&reportUsage=false').expect(200);
|
|
92
|
+
|
|
93
|
+
await request(app).post('/api/openchamber/update-install').expect(200);
|
|
94
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
95
|
+
const response = await request(app).get('/api/openchamber/update-check?appType=web&reportUsage=false').expect(200);
|
|
96
|
+
expect(response.body.currentVersion).toBe('1.17.0');
|
|
97
|
+
expect(response.body.updateOwner).toBe('electron-updater');
|
|
98
|
+
expect(packageManager.checkForUpdates).not.toHaveBeenCalled();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('rejects native checks without a bridge and preserves explicit non-web checks', async () => {
|
|
102
|
+
const { app } = createApp({ environment: { AIWORKER_RUNTIME: 'desktop' } });
|
|
103
|
+
await request(app).get('/api/openchamber/update-check?appType=web').expect(503, {
|
|
104
|
+
available: false, code: 'DESKTOP_UPDATER_UNAVAILABLE', error: 'The desktop updater is not available.',
|
|
105
|
+
});
|
|
106
|
+
expect(packageManager.checkForUpdates).not.toHaveBeenCalled();
|
|
107
|
+
await request(app).get('/api/openchamber/update-check?appType=desktop-electron').expect(200);
|
|
108
|
+
expect(packageManager.checkForUpdates).toHaveBeenCalledOnce();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('uses electron-updater to check for Web client updates', async () => {
|
|
112
|
+
const desktopUpdater = {
|
|
113
|
+
check: vi.fn(async () => ({
|
|
114
|
+
available: true,
|
|
115
|
+
currentVersion: '1.17.0',
|
|
116
|
+
version: '1.17.1',
|
|
117
|
+
})),
|
|
118
|
+
install: vi.fn(),
|
|
119
|
+
restart: vi.fn(),
|
|
120
|
+
};
|
|
121
|
+
const { app } = createApp({
|
|
122
|
+
environment: {
|
|
123
|
+
AIWORKER_RUNTIME: 'desktop',
|
|
124
|
+
},
|
|
125
|
+
desktopUpdater,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
await request(app)
|
|
129
|
+
.get('/api/openchamber/update-check?appType=web&reportUsage=false')
|
|
130
|
+
.expect(200, {
|
|
131
|
+
available: true,
|
|
132
|
+
currentVersion: '1.17.0',
|
|
133
|
+
version: '1.17.1',
|
|
134
|
+
packageManager: 'electron',
|
|
135
|
+
updateOwner: 'electron-updater',
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
expect(desktopUpdater.check).toHaveBeenCalledOnce();
|
|
139
|
+
expect(packageManager.checkForUpdates).not.toHaveBeenCalled();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('installs through electron-updater and restarts after responding', async () => {
|
|
143
|
+
const desktopUpdater = {
|
|
144
|
+
check: vi.fn(),
|
|
145
|
+
install: vi.fn(async () => ({
|
|
146
|
+
available: true,
|
|
147
|
+
version: '1.17.1',
|
|
148
|
+
})),
|
|
149
|
+
restart: vi.fn(),
|
|
150
|
+
};
|
|
151
|
+
const { app } = createApp({
|
|
152
|
+
environment: {
|
|
153
|
+
AIWORKER_RUNTIME: 'desktop',
|
|
154
|
+
},
|
|
155
|
+
desktopUpdater,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
await request(app)
|
|
159
|
+
.post('/api/openchamber/update-install')
|
|
160
|
+
.expect(200, {
|
|
161
|
+
success: true,
|
|
162
|
+
message: 'Desktop update downloaded, host will restart shortly',
|
|
163
|
+
version: '1.17.1',
|
|
164
|
+
packageManager: 'electron',
|
|
165
|
+
updateOwner: 'electron-updater',
|
|
166
|
+
autoRestart: true,
|
|
167
|
+
restartManager: 'electron-updater',
|
|
168
|
+
});
|
|
169
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
170
|
+
|
|
171
|
+
expect(desktopUpdater.install).toHaveBeenCalledOnce();
|
|
172
|
+
expect(desktopUpdater.restart).toHaveBeenCalledOnce();
|
|
173
|
+
expect(packageManager.checkForUpdates).not.toHaveBeenCalled();
|
|
174
|
+
expect(packageManager.detectPackageManagerDetails).not.toHaveBeenCalled();
|
|
175
|
+
expect(packageManager.getUpdateCommand).not.toHaveBeenCalled();
|
|
176
|
+
expect(childProcess.spawn).not.toHaveBeenCalled();
|
|
177
|
+
expect(childProcess.spawnSync).not.toHaveBeenCalled();
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('fails safely when the Electron updater bridge is unavailable', async () => {
|
|
181
|
+
const { app } = createApp({
|
|
182
|
+
environment: {
|
|
183
|
+
AIWORKER_RUNTIME: 'desktop',
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
await request(app)
|
|
188
|
+
.post('/api/openchamber/update-install')
|
|
189
|
+
.expect(503, {
|
|
190
|
+
code: 'DESKTOP_UPDATER_UNAVAILABLE',
|
|
191
|
+
error: 'The desktop updater is not available.',
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
expect(packageManager.checkForUpdates).not.toHaveBeenCalled();
|
|
195
|
+
expect(childProcess.spawn).not.toHaveBeenCalled();
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
describe('AiWorker foreground update route', () => {
|
|
73
200
|
it('rejects a foreground update when the server is not owned by systemd', async () => {
|
|
74
201
|
const { app } = createApp();
|
|
75
202
|
|
|
76
203
|
await request(app)
|
|
77
204
|
.post('/api/openchamber/update-install')
|
|
78
205
|
.expect(409, {
|
|
79
|
-
error: 'Foreground servers must be updated by their service manager. Set
|
|
206
|
+
error: 'Foreground servers must be updated by their service manager. Set AIWORKER_SYSTEMD_UNIT when running under systemd, or run aiworker update and restart the service.',
|
|
80
207
|
});
|
|
81
208
|
|
|
82
209
|
expect(childProcess.spawnSync).not.toHaveBeenCalled();
|
|
@@ -86,14 +213,14 @@ describe('OpenChamber foreground update route', () => {
|
|
|
86
213
|
const { app } = createApp({
|
|
87
214
|
environment: {
|
|
88
215
|
INVOCATION_ID: 'systemd-invocation',
|
|
89
|
-
|
|
216
|
+
AIWORKER_SYSTEMD_UNIT: 'aiworker.service; rm -rf /',
|
|
90
217
|
},
|
|
91
218
|
});
|
|
92
219
|
|
|
93
220
|
await request(app)
|
|
94
221
|
.post('/api/openchamber/update-install')
|
|
95
222
|
.expect(409, {
|
|
96
|
-
error: 'Foreground servers must be updated by their service manager. Set
|
|
223
|
+
error: 'Foreground servers must be updated by their service manager. Set AIWORKER_SYSTEMD_UNIT when running under systemd, or run aiworker update and restart the service.',
|
|
97
224
|
});
|
|
98
225
|
|
|
99
226
|
expect(childProcess.spawnSync).not.toHaveBeenCalled();
|
|
@@ -105,7 +232,7 @@ describe('OpenChamber foreground update route', () => {
|
|
|
105
232
|
const { app } = createApp({
|
|
106
233
|
environment: {
|
|
107
234
|
INVOCATION_ID: 'systemd-invocation',
|
|
108
|
-
|
|
235
|
+
AIWORKER_SYSTEMD_UNIT: 'aiworker@wsl.service',
|
|
109
236
|
PATH: '/home/syu/.npm-global/bin:/usr/bin:/bin',
|
|
110
237
|
},
|
|
111
238
|
});
|
|
@@ -114,7 +241,7 @@ describe('OpenChamber foreground update route', () => {
|
|
|
114
241
|
.post('/api/openchamber/update-install')
|
|
115
242
|
.expect(200, {
|
|
116
243
|
success: true,
|
|
117
|
-
message: 'Update queued;
|
|
244
|
+
message: 'Update queued; AiWorker will restart after installation completes',
|
|
118
245
|
version: '1.17.1',
|
|
119
246
|
packageManager: 'npm',
|
|
120
247
|
autoRestart: true,
|
|
@@ -131,7 +258,7 @@ describe('OpenChamber foreground update route', () => {
|
|
|
131
258
|
'--setenv=PATH=/home/syu/.npm-global/bin:/usr/bin:/bin',
|
|
132
259
|
'/bin/sh',
|
|
133
260
|
'-c',
|
|
134
|
-
"set -eu\nnpm install -g @
|
|
261
|
+
"set -eu\nnpm install -g @aiworker/web@latest\nsystemctl --user restart 'aiworker@wsl.service'",
|
|
135
262
|
], {
|
|
136
263
|
encoding: 'utf8',
|
|
137
264
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
-
import os from 'os';
|
|
3
2
|
import path from 'path';
|
|
4
3
|
import {
|
|
5
4
|
AGENT_SCOPE,
|
|
5
|
+
OPENCODE_CONFIG_DIR,
|
|
6
6
|
readConfigFile,
|
|
7
7
|
readConfigLayer,
|
|
8
8
|
writeConfig,
|
|
@@ -71,7 +71,7 @@ function getActiveOpencodeConfigDir() {
|
|
|
71
71
|
if (customConfigPath) {
|
|
72
72
|
return path.dirname(path.resolve(customConfigPath));
|
|
73
73
|
}
|
|
74
|
-
return
|
|
74
|
+
return OPENCODE_CONFIG_DIR;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
function getActiveUserConfigPaths() {
|
|
@@ -136,7 +136,7 @@ describe('opencode plugins data layer', () => {
|
|
|
136
136
|
|
|
137
137
|
expect(plugins.listPluginEntries(projectDir).map((entry) => entry.spec)).toEqual(['user-plugin']);
|
|
138
138
|
expect(fs.readFileSync(projectFile, 'utf8')).toBe(partialProject);
|
|
139
|
-
expect(fs.existsSync(`${projectFile}.
|
|
139
|
+
expect(fs.existsSync(`${projectFile}.aiworker.backup`)).toBe(false);
|
|
140
140
|
});
|
|
141
141
|
|
|
142
142
|
test('lists entries from user and project layers with scopes and parsed kinds', () => {
|
|
@@ -3,7 +3,7 @@ export const registerProjectIconRoutes = (app, dependencies) => {
|
|
|
3
3
|
fsPromises,
|
|
4
4
|
path,
|
|
5
5
|
crypto,
|
|
6
|
-
|
|
6
|
+
aiworkerDataDir,
|
|
7
7
|
sanitizeProjects,
|
|
8
8
|
readSettingsFromDiskMigrated,
|
|
9
9
|
persistSettings,
|
|
@@ -12,7 +12,7 @@ export const registerProjectIconRoutes = (app, dependencies) => {
|
|
|
12
12
|
resolveGitBinaryForSpawn,
|
|
13
13
|
} = dependencies;
|
|
14
14
|
|
|
15
|
-
const projectIconsDirPath = path.join(
|
|
15
|
+
const projectIconsDirPath = path.join(aiworkerDataDir, 'project-icons');
|
|
16
16
|
const projectIconMimeToExtension = {
|
|
17
17
|
'image/png': 'png',
|
|
18
18
|
'image/jpeg': 'jpg',
|
|
@@ -79,7 +79,7 @@ describe('project icon routes', () => {
|
|
|
79
79
|
fsPromises,
|
|
80
80
|
path,
|
|
81
81
|
crypto,
|
|
82
|
-
|
|
82
|
+
aiworkerDataDir: '/tmp/openchamber-test',
|
|
83
83
|
sanitizeProjects: (projects) => projects,
|
|
84
84
|
readSettingsFromDiskMigrated: async () => ({
|
|
85
85
|
projects: [{
|
|
@@ -152,6 +152,37 @@ function validateCustomProviderConfig(providerId, config, options = {}) {
|
|
|
152
152
|
return { ok: true, value: { providerId, config: normalized } };
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
function mergeCustomProviderConfig(existingValue, normalizedConfig) {
|
|
156
|
+
const existing = isPlainObject(existingValue) ? existingValue : {};
|
|
157
|
+
const existingOptions = isPlainObject(existing.options) ? existing.options : {};
|
|
158
|
+
const normalizedOptions = isPlainObject(normalizedConfig.options) ? normalizedConfig.options : {};
|
|
159
|
+
const mergedOptions = { ...existingOptions, ...normalizedOptions };
|
|
160
|
+
if (!Object.prototype.hasOwnProperty.call(normalizedOptions, 'headers')) {
|
|
161
|
+
delete mergedOptions.headers;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const existingModels = isPlainObject(existing.models) ? existing.models : {};
|
|
165
|
+
const normalizedModels = isPlainObject(normalizedConfig.models) ? normalizedConfig.models : {};
|
|
166
|
+
const mergedModels = Object.fromEntries(
|
|
167
|
+
Object.entries(normalizedModels).map(([modelId, normalizedModel]) => {
|
|
168
|
+
const existingModel = isPlainObject(existingModels[modelId]) ? existingModels[modelId] : {};
|
|
169
|
+
const nextModel = isPlainObject(normalizedModel) ? normalizedModel : {};
|
|
170
|
+
return [modelId, { ...existingModel, ...nextModel }];
|
|
171
|
+
}),
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
const merged = {
|
|
175
|
+
...existing,
|
|
176
|
+
...normalizedConfig,
|
|
177
|
+
options: mergedOptions,
|
|
178
|
+
models: mergedModels,
|
|
179
|
+
};
|
|
180
|
+
if (!Object.prototype.hasOwnProperty.call(normalizedConfig, 'env')) {
|
|
181
|
+
delete merged.env;
|
|
182
|
+
}
|
|
183
|
+
return merged;
|
|
184
|
+
}
|
|
185
|
+
|
|
155
186
|
/**
|
|
156
187
|
* Persist (create or update) a custom provider block in OpenCode user/project/custom config.
|
|
157
188
|
* Does not write secrets — API keys remain in auth.json via the OpenCode auth API.
|
|
@@ -183,8 +214,19 @@ function upsertProviderConfig(providerId, config, workingDirectory, scope = 'use
|
|
|
183
214
|
|
|
184
215
|
const targetConfig = getConfigForPath(layers, targetPath);
|
|
185
216
|
const providerConfig = isPlainObject(targetConfig.provider) ? { ...targetConfig.provider } : {};
|
|
186
|
-
|
|
217
|
+
const providersAlias = isPlainObject(targetConfig.providers) ? { ...targetConfig.providers } : {};
|
|
218
|
+
const existingProvider = providerConfig[validated.value.providerId] ?? providersAlias[validated.value.providerId];
|
|
219
|
+
const mergedConfig = mergeCustomProviderConfig(existingProvider, validated.value.config);
|
|
220
|
+
providerConfig[validated.value.providerId] = mergedConfig;
|
|
187
221
|
targetConfig.provider = providerConfig;
|
|
222
|
+
if (Object.prototype.hasOwnProperty.call(providersAlias, validated.value.providerId)) {
|
|
223
|
+
delete providersAlias[validated.value.providerId];
|
|
224
|
+
if (Object.keys(providersAlias).length === 0) {
|
|
225
|
+
delete targetConfig.providers;
|
|
226
|
+
} else {
|
|
227
|
+
targetConfig.providers = providersAlias;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
188
230
|
|
|
189
231
|
if (Array.isArray(targetConfig.disabled_providers)) {
|
|
190
232
|
targetConfig.disabled_providers = targetConfig.disabled_providers.filter(
|
|
@@ -198,7 +240,7 @@ function upsertProviderConfig(providerId, config, workingDirectory, scope = 'use
|
|
|
198
240
|
return {
|
|
199
241
|
providerId: validated.value.providerId,
|
|
200
242
|
path: writePath,
|
|
201
|
-
config:
|
|
243
|
+
config: mergedConfig,
|
|
202
244
|
};
|
|
203
245
|
}
|
|
204
246
|
|