@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
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// The two settings files and how a merged document is split between them.
|
|
2
|
+
//
|
|
3
|
+
// `settings.json` holds instance facts (and, untouched, whatever legacy keys
|
|
4
|
+
// older builds left there). `preferences.json` holds the user's profile: the
|
|
5
|
+
// keys the settings registry marks `profile`, each with the time the store
|
|
6
|
+
// last accepted a new value for it. Device keys never reach either file.
|
|
7
|
+
//
|
|
8
|
+
// The VS Code extension host writes the same two files with the same shape
|
|
9
|
+
// (`packages/vscode/src/settings-files.ts`); keep the format changes in sync.
|
|
10
|
+
import { createRequire } from 'node:module';
|
|
11
|
+
|
|
12
|
+
const registry = createRequire(import.meta.url)('./settings-registry.json');
|
|
13
|
+
|
|
14
|
+
const PREFERENCES_FILE_NAME = 'preferences.json';
|
|
15
|
+
const PREFERENCES_DOCUMENT_VERSION = 1;
|
|
16
|
+
|
|
17
|
+
/** The registry scope for a key, or `null` when the registry does not know it. */
|
|
18
|
+
const getSettingsScope = (key) => registry.fields[key]?.scope ?? null;
|
|
19
|
+
|
|
20
|
+
export const isProfileSettingsKey = (key) => getSettingsScope(key) === 'profile';
|
|
21
|
+
export const isDeviceSettingsKey = (key) => getSettingsScope(key) === 'device';
|
|
22
|
+
|
|
23
|
+
/** Profile keys the owner chose to store per surface kind (a change on a phone stays on phones). */
|
|
24
|
+
const isPerSurfaceSettingsKey = (key) => registry.fields[key]?.perSurface === true;
|
|
25
|
+
|
|
26
|
+
const SETTINGS_SURFACES = Object.freeze(['web', 'desktop', 'vscode', 'mobile']);
|
|
27
|
+
|
|
28
|
+
export const normalizeSettingsSurface = (value) => (
|
|
29
|
+
typeof value === 'string' && SETTINGS_SURFACES.includes(value.trim()) ? value.trim() : null
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Which surface kind a settings request comes from; `null` means "base".
|
|
34
|
+
* Clients send `?surface=<kind>` (a query parameter keeps the request
|
|
35
|
+
* CORS-simple for cross-origin shells and older instances); the
|
|
36
|
+
* `x-openchamber-surface` header is still honoured for clients that sent it.
|
|
37
|
+
*/
|
|
38
|
+
export const settingsSurfaceOf = (req) => (
|
|
39
|
+
normalizeSettingsSurface(req.query?.surface) ?? normalizeSettingsSurface(req.get?.('x-openchamber-surface'))
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
export const preferencesFilePathFor = (settingsFilePath, path) => path.join(path.dirname(settingsFilePath), PREFERENCES_FILE_NAME);
|
|
43
|
+
|
|
44
|
+
const isPlainObject = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
45
|
+
|
|
46
|
+
const sameValue = (left, right) => {
|
|
47
|
+
if (left === right) return true;
|
|
48
|
+
if (left === undefined || right === undefined) return false;
|
|
49
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const parseStamp = (value) => (Number.isFinite(value) ? value : 0);
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Parse the text of a preferences file. A missing file is the caller's case
|
|
56
|
+
* (ENOENT); anything that is not a version-1 document with a `fields` object
|
|
57
|
+
* is a failure, never an empty profile.
|
|
58
|
+
*
|
|
59
|
+
* An entry is `{ value, updatedAt }` for the base value, optionally with
|
|
60
|
+
* `surfaces: { [surface]: { value, updatedAt } }` for per-surface keys; a
|
|
61
|
+
* per-surface key that was only ever set from one surface kind has no base.
|
|
62
|
+
*/
|
|
63
|
+
export const parsePreferencesDocument = (raw) => {
|
|
64
|
+
let parsed;
|
|
65
|
+
try {
|
|
66
|
+
parsed = JSON.parse(raw);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
return { ok: false, reason: `invalid JSON: ${error instanceof Error ? error.message : String(error)}` };
|
|
69
|
+
}
|
|
70
|
+
if (!isPlainObject(parsed) || parsed.version !== PREFERENCES_DOCUMENT_VERSION || !isPlainObject(parsed.fields)) {
|
|
71
|
+
return { ok: false, reason: 'not a version-1 preferences document' };
|
|
72
|
+
}
|
|
73
|
+
const fields = {};
|
|
74
|
+
for (const [key, entry] of Object.entries(parsed.fields)) {
|
|
75
|
+
if (!isPlainObject(entry) || (!('value' in entry) && !isPlainObject(entry.surfaces))) {
|
|
76
|
+
return { ok: false, reason: `field "${key}" is not a { value, updatedAt } entry` };
|
|
77
|
+
}
|
|
78
|
+
const next = { updatedAt: parseStamp(entry.updatedAt) };
|
|
79
|
+
if ('value' in entry) next.value = entry.value;
|
|
80
|
+
if (isPlainObject(entry.surfaces)) {
|
|
81
|
+
next.surfaces = {};
|
|
82
|
+
for (const [surface, surfaceEntry] of Object.entries(entry.surfaces)) {
|
|
83
|
+
if (!SETTINGS_SURFACES.includes(surface) || !isPlainObject(surfaceEntry) || !('value' in surfaceEntry)) {
|
|
84
|
+
return { ok: false, reason: `field "${key}" has an invalid surface entry "${surface}"` };
|
|
85
|
+
}
|
|
86
|
+
next.surfaces[surface] = { value: surfaceEntry.value, updatedAt: parseStamp(surfaceEntry.updatedAt) };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
fields[key] = next;
|
|
90
|
+
}
|
|
91
|
+
return { ok: true, fields };
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const serializePreferencesDocument = (fields) => JSON.stringify({ version: PREFERENCES_DOCUMENT_VERSION, fields }, null, 2);
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The plain key → value view of preference fields as one surface kind sees it:
|
|
98
|
+
* that surface's own value first, the base value otherwise; a key with neither
|
|
99
|
+
* is absent (the client keeps what it holds, or its default).
|
|
100
|
+
*/
|
|
101
|
+
export const flattenPreferences = (fields, surface = null) => {
|
|
102
|
+
const values = {};
|
|
103
|
+
for (const [key, entry] of Object.entries(fields)) {
|
|
104
|
+
const own = surface && entry.surfaces ? entry.surfaces[surface] : undefined;
|
|
105
|
+
if (own) {
|
|
106
|
+
values[key] = own.value;
|
|
107
|
+
} else if ('value' in entry) {
|
|
108
|
+
values[key] = entry.value;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return values;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* The next preference fields for a merged document: every profile key it
|
|
116
|
+
* carries, stamped `now` when its value differs from what the file held and
|
|
117
|
+
* keeping the earlier stamp otherwise. Profile keys the document no longer
|
|
118
|
+
* carries are dropped (that is how a cleared key leaves the file).
|
|
119
|
+
*
|
|
120
|
+
* Per-surface keys: when the write comes from a surface kind (`surface`) and
|
|
121
|
+
* the key is among the keys that write changed (`changedKeys`), the value goes
|
|
122
|
+
* under `surfaces[surface]` and the base is left as it was; a per-surface key
|
|
123
|
+
* the write did not change keeps its whole entry (the document only carries
|
|
124
|
+
* that surface's resolved view of it). Without a surface (migrations, the
|
|
125
|
+
* one-time seed) the base is written.
|
|
126
|
+
*/
|
|
127
|
+
export const buildPreferencesFields = (previousFields, document, now, { surface = null, changedKeys = null } = {}) => {
|
|
128
|
+
const fields = {};
|
|
129
|
+
const changed = changedKeys ? new Set(changedKeys) : null;
|
|
130
|
+
for (const [key, value] of Object.entries(document)) {
|
|
131
|
+
if (value === undefined || !isProfileSettingsKey(key)) continue;
|
|
132
|
+
const previous = previousFields[key];
|
|
133
|
+
if (isPerSurfaceSettingsKey(key) && surface) {
|
|
134
|
+
if (changed && !changed.has(key)) {
|
|
135
|
+
if (previous) fields[key] = previous;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const previousOwn = previous?.surfaces?.[surface];
|
|
139
|
+
const own = previousOwn && sameValue(previousOwn.value, value) ? previousOwn : { value, updatedAt: now };
|
|
140
|
+
fields[key] = {
|
|
141
|
+
...(previous ?? { updatedAt: 0 }),
|
|
142
|
+
surfaces: { ...(previous?.surfaces ?? {}), [surface]: own },
|
|
143
|
+
};
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (previous && 'value' in previous && sameValue(previous.value, value)) {
|
|
147
|
+
fields[key] = previous;
|
|
148
|
+
} else {
|
|
149
|
+
fields[key] = { ...(previous ?? {}), value, updatedAt: now };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return fields;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* The part of a merged document that belongs in `settings.json`: everything
|
|
157
|
+
* that is not a profile key. Device keys older builds persisted stay in place
|
|
158
|
+
* as a read-once seed for clients; the write path never adds new ones.
|
|
159
|
+
*/
|
|
160
|
+
export const instancePartOf = (document) => {
|
|
161
|
+
const instance = {};
|
|
162
|
+
for (const [key, value] of Object.entries(document)) {
|
|
163
|
+
if (value === undefined || isProfileSettingsKey(key)) continue;
|
|
164
|
+
instance[key] = value;
|
|
165
|
+
}
|
|
166
|
+
return instance;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/** The profile keys of a document (the part `instancePartOf` leaves out). */
|
|
170
|
+
export const profilePartOf = (document) => {
|
|
171
|
+
const profile = {};
|
|
172
|
+
for (const [key, value] of Object.entries(document)) {
|
|
173
|
+
if (value !== undefined && isProfileSettingsKey(key)) profile[key] = value;
|
|
174
|
+
}
|
|
175
|
+
return profile;
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* What `settings.json` holds after a write: the instance part plus a copy of
|
|
180
|
+
* the profile's base values. The copy is for builds that predate the split —
|
|
181
|
+
* they read only this file, so a rollback still finds the user's preferences.
|
|
182
|
+
* Current builds ignore it: `preferences.json` wins in the merged read.
|
|
183
|
+
*/
|
|
184
|
+
export const legacySettingsDocumentOf = (document, preferenceFields) => ({
|
|
185
|
+
...instancePartOf(document),
|
|
186
|
+
...flattenPreferences(preferenceFields),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
/** The profile keys of a document, as they would seed a fresh preferences file. */
|
|
190
|
+
export const seedPreferencesFrom = (document, now) => buildPreferencesFields({}, document, now);
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Synchronous merged read for server modules that consult one or two profile
|
|
194
|
+
* keys on a hot path (small-model resolution, goal/assist toggles). A missing
|
|
195
|
+
* or unreadable preferences file contributes nothing, and the caller's own
|
|
196
|
+
* default applies — the same "missing is not default" rule the clients use.
|
|
197
|
+
*/
|
|
198
|
+
export const readMergedSettingsSync = ({ fs, path, settingsFilePath }) => {
|
|
199
|
+
let settings = {};
|
|
200
|
+
try {
|
|
201
|
+
const parsed = JSON.parse(fs.readFileSync(settingsFilePath, 'utf8'));
|
|
202
|
+
if (isPlainObject(parsed)) settings = parsed;
|
|
203
|
+
} catch {
|
|
204
|
+
settings = {};
|
|
205
|
+
}
|
|
206
|
+
let preferences = {};
|
|
207
|
+
try {
|
|
208
|
+
const parsed = parsePreferencesDocument(fs.readFileSync(preferencesFilePathFor(settingsFilePath, path), 'utf8'));
|
|
209
|
+
if (parsed.ok) preferences = flattenPreferences(parsed.fields);
|
|
210
|
+
} catch {
|
|
211
|
+
preferences = {};
|
|
212
|
+
}
|
|
213
|
+
return { ...settings, ...preferences };
|
|
214
|
+
};
|
|
@@ -1,5 +1,39 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
|
|
1
3
|
import { isAgentMemoryFeatureAvailable } from '../agent-memory/feature-flag.js';
|
|
2
4
|
|
|
5
|
+
// Generated from packages/ui/src/lib/settings/registry.ts by
|
|
6
|
+
// `bun run settings-registry:generate`; `registry.test.ts` fails when stale.
|
|
7
|
+
// The server is plain ESM without a bundler, so the snapshot is read with
|
|
8
|
+
// `createRequire` (import attributes differ across the Node versions we run on).
|
|
9
|
+
const settingsRegistry = createRequire(import.meta.url)('./settings-registry.json');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Whether a client may persist this key through PUT /api/config/settings:
|
|
13
|
+
* it must be a registry key, not a server-computed flag, not a device field
|
|
14
|
+
* that only lives in the browser, and not one the desktop shell writes itself.
|
|
15
|
+
*/
|
|
16
|
+
const isPersistableSettingsKey = (key) => {
|
|
17
|
+
const field = settingsRegistry.fields[key];
|
|
18
|
+
if (!field) return false;
|
|
19
|
+
if (field.computed || field.local) return false;
|
|
20
|
+
if (field.owner === 'desktop-shell') return false;
|
|
21
|
+
return true;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** Keys accepted on write but never returned by a read. */
|
|
25
|
+
const SECRET_SETTINGS_KEYS = Object.freeze(
|
|
26
|
+
Object.entries(settingsRegistry.fields)
|
|
27
|
+
.filter(([, field]) => field.secret === true)
|
|
28
|
+
.map(([key]) => key),
|
|
29
|
+
);
|
|
30
|
+
import {
|
|
31
|
+
DEFAULT_INPUT_HISTORY_LIMIT,
|
|
32
|
+
DEFAULT_INPUT_HISTORY_SCOPE,
|
|
33
|
+
isInputHistoryLimit,
|
|
34
|
+
isInputHistoryScope,
|
|
35
|
+
} from './input-history-scope.js';
|
|
36
|
+
|
|
3
37
|
export const createSettingsHelpers = (dependencies) => {
|
|
4
38
|
const {
|
|
5
39
|
normalizePathForPersistence,
|
|
@@ -12,7 +46,6 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
12
46
|
normalizeManagedRemoteTunnelHostname,
|
|
13
47
|
normalizeManagedRemoteTunnelPresets,
|
|
14
48
|
normalizeManagedRemoteTunnelPresetTokens,
|
|
15
|
-
sanitizeTypographySizesPartial,
|
|
16
49
|
normalizeStringArray,
|
|
17
50
|
sanitizeModelRefs,
|
|
18
51
|
sanitizeSkillCatalogs,
|
|
@@ -140,6 +173,12 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
140
173
|
if (typeof candidate.themeVariant === 'string' && (candidate.themeVariant === 'light' || candidate.themeVariant === 'dark')) {
|
|
141
174
|
result.themeVariant = candidate.themeVariant;
|
|
142
175
|
}
|
|
176
|
+
if (typeof candidate.inputHistoryScope === 'string' && isInputHistoryScope(candidate.inputHistoryScope)) {
|
|
177
|
+
result.inputHistoryScope = candidate.inputHistoryScope;
|
|
178
|
+
}
|
|
179
|
+
if (isInputHistoryLimit(candidate.inputHistoryLimit)) {
|
|
180
|
+
result.inputHistoryLimit = candidate.inputHistoryLimit;
|
|
181
|
+
}
|
|
143
182
|
if (typeof candidate.useSystemTheme === 'boolean') {
|
|
144
183
|
result.useSystemTheme = candidate.useSystemTheme;
|
|
145
184
|
}
|
|
@@ -191,6 +230,9 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
191
230
|
...new Set(candidate.workStatusHiddenSections.filter((entry) => typeof entry === 'string' && entry.length > 0)),
|
|
192
231
|
];
|
|
193
232
|
}
|
|
233
|
+
if (typeof candidate.workStatusHiddenSectionsExplicit === 'boolean') {
|
|
234
|
+
result.workStatusHiddenSectionsExplicit = candidate.workStatusHiddenSectionsExplicit;
|
|
235
|
+
}
|
|
194
236
|
if (typeof candidate.desktopLanAccessEnabled === 'boolean') {
|
|
195
237
|
result.desktopLanAccessEnabled = candidate.desktopLanAccessEnabled;
|
|
196
238
|
}
|
|
@@ -301,9 +343,6 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
301
343
|
if (typeof candidate.monoFont === 'string' && candidate.monoFont.length > 0) {
|
|
302
344
|
result.monoFont = candidate.monoFont;
|
|
303
345
|
}
|
|
304
|
-
if (typeof candidate.markdownDisplayMode === 'string' && candidate.markdownDisplayMode.length > 0) {
|
|
305
|
-
result.markdownDisplayMode = candidate.markdownDisplayMode;
|
|
306
|
-
}
|
|
307
346
|
if (typeof candidate.githubClientId === 'string') {
|
|
308
347
|
const trimmed = candidate.githubClientId.trim();
|
|
309
348
|
if (trimmed.length > 0) {
|
|
@@ -319,6 +358,45 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
319
358
|
if (typeof candidate.showReasoningTraces === 'boolean') {
|
|
320
359
|
result.showReasoningTraces = candidate.showReasoningTraces;
|
|
321
360
|
}
|
|
361
|
+
if (typeof candidate.streamingAutoFollowEnabled === 'boolean') {
|
|
362
|
+
result.streamingAutoFollowEnabled = candidate.streamingAutoFollowEnabled;
|
|
363
|
+
}
|
|
364
|
+
if (typeof candidate.codeBlockLineWrap === 'boolean') {
|
|
365
|
+
result.codeBlockLineWrap = candidate.codeBlockLineWrap;
|
|
366
|
+
}
|
|
367
|
+
if (typeof candidate.autoSaveEnabled === 'boolean') {
|
|
368
|
+
result.autoSaveEnabled = candidate.autoSaveEnabled;
|
|
369
|
+
}
|
|
370
|
+
if (typeof candidate.diffWrapLines === 'boolean') {
|
|
371
|
+
result.diffWrapLines = candidate.diffWrapLines;
|
|
372
|
+
}
|
|
373
|
+
if (typeof candidate.persistChatDraft === 'boolean') {
|
|
374
|
+
result.persistChatDraft = candidate.persistChatDraft;
|
|
375
|
+
}
|
|
376
|
+
if (typeof candidate.allowPromptingSubagentSessions === 'boolean') {
|
|
377
|
+
result.allowPromptingSubagentSessions = candidate.allowPromptingSubagentSessions;
|
|
378
|
+
}
|
|
379
|
+
if (typeof candidate.showOpenCodeRestartConfirm === 'boolean') {
|
|
380
|
+
result.showOpenCodeRestartConfirm = candidate.showOpenCodeRestartConfirm;
|
|
381
|
+
}
|
|
382
|
+
if (typeof candidate.sessionTabsEnabled === 'boolean') {
|
|
383
|
+
result.sessionTabsEnabled = candidate.sessionTabsEnabled;
|
|
384
|
+
}
|
|
385
|
+
if (typeof candidate.largeTextPasteBehavior === 'string') {
|
|
386
|
+
const mode = candidate.largeTextPasteBehavior.trim();
|
|
387
|
+
if (mode === 'ask' || mode === 'attach' || mode === 'inline') {
|
|
388
|
+
result.largeTextPasteBehavior = mode;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
if (typeof candidate.fileEditorKeymap === 'string') {
|
|
392
|
+
const mode = candidate.fileEditorKeymap.trim();
|
|
393
|
+
if (mode === 'default' || mode === 'vim') {
|
|
394
|
+
result.fileEditorKeymap = mode;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
if (Array.isArray(candidate.providerOrder)) {
|
|
398
|
+
result.providerOrder = normalizeStringArray(candidate.providerOrder);
|
|
399
|
+
}
|
|
322
400
|
if (typeof candidate.sessionRecapEnabled === 'boolean') {
|
|
323
401
|
result.sessionRecapEnabled = candidate.sessionRecapEnabled;
|
|
324
402
|
}
|
|
@@ -440,11 +518,6 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
440
518
|
result.managedRemoteTunnelSelectedPresetId = id || undefined;
|
|
441
519
|
}
|
|
442
520
|
|
|
443
|
-
const typography = sanitizeTypographySizesPartial(candidate.typographySizes);
|
|
444
|
-
if (typography) {
|
|
445
|
-
result.typographySizes = typography;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
521
|
if (typeof candidate.defaultModel === 'string') {
|
|
449
522
|
const trimmed = candidate.defaultModel.trim();
|
|
450
523
|
result.defaultModel = trimmed.length > 0 ? trimmed : undefined;
|
|
@@ -490,14 +563,6 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
490
563
|
const trimmed = candidate.zenModel.trim();
|
|
491
564
|
result.zenModel = trimmed.length > 0 ? trimmed : undefined;
|
|
492
565
|
}
|
|
493
|
-
if (typeof candidate.gitProviderId === 'string') {
|
|
494
|
-
const trimmed = candidate.gitProviderId.trim();
|
|
495
|
-
result.gitProviderId = trimmed.length > 0 ? trimmed : undefined;
|
|
496
|
-
}
|
|
497
|
-
if (typeof candidate.gitModelId === 'string') {
|
|
498
|
-
const trimmed = candidate.gitModelId.trim();
|
|
499
|
-
result.gitModelId = trimmed.length > 0 ? trimmed : undefined;
|
|
500
|
-
}
|
|
501
566
|
if (typeof candidate.pwaAppName === 'string') {
|
|
502
567
|
result.pwaAppName = normalizePwaAppName(candidate.pwaAppName, undefined);
|
|
503
568
|
}
|
|
@@ -510,15 +575,15 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
510
575
|
result.mobileKeyboardMode = mode;
|
|
511
576
|
}
|
|
512
577
|
}
|
|
513
|
-
if (typeof candidate.toolCallExpansion === 'string') {
|
|
514
|
-
const mode = candidate.toolCallExpansion.trim();
|
|
515
|
-
if (mode === 'collapsed' || mode === 'activity' || mode === 'detailed' || mode === 'changes') {
|
|
516
|
-
result.toolCallExpansion = mode;
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
578
|
if (typeof candidate.inputSpellcheckEnabled === 'boolean') {
|
|
520
579
|
result.inputSpellcheckEnabled = candidate.inputSpellcheckEnabled;
|
|
521
580
|
}
|
|
581
|
+
if (candidate.enterToSend === true || candidate.enterToSend === false) {
|
|
582
|
+
result.enterToSend = candidate.enterToSend;
|
|
583
|
+
}
|
|
584
|
+
if (candidate.enterToSendConfigured === true || candidate.enterToSendConfigured === false) {
|
|
585
|
+
result.enterToSendConfigured = candidate.enterToSendConfigured;
|
|
586
|
+
}
|
|
522
587
|
if (typeof candidate.showOpenCodeUpdateNotifications === 'boolean') {
|
|
523
588
|
result.showOpenCodeUpdateNotifications = candidate.showOpenCodeUpdateNotifications;
|
|
524
589
|
}
|
|
@@ -601,9 +666,6 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
601
666
|
if (typeof candidate.promptNavigatorEnabled === 'boolean') {
|
|
602
667
|
result.promptNavigatorEnabled = candidate.promptNavigatorEnabled;
|
|
603
668
|
}
|
|
604
|
-
if (typeof candidate.expandedEditorToolbar === 'boolean') {
|
|
605
|
-
result.expandedEditorToolbar = candidate.expandedEditorToolbar;
|
|
606
|
-
}
|
|
607
669
|
if (typeof candidate.wideChatLayoutEnabled === 'boolean') {
|
|
608
670
|
result.wideChatLayoutEnabled = candidate.wideChatLayoutEnabled;
|
|
609
671
|
}
|
|
@@ -687,6 +749,12 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
687
749
|
result.gitChangesViewMode = mode;
|
|
688
750
|
}
|
|
689
751
|
}
|
|
752
|
+
if (typeof candidate.toolJsonViewMode === 'string') {
|
|
753
|
+
const mode = candidate.toolJsonViewMode.trim();
|
|
754
|
+
if (mode === 'summary' || mode === 'formatted' || mode === 'raw') {
|
|
755
|
+
result.toolJsonViewMode = mode;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
690
758
|
if (typeof candidate.directoryShowHidden === 'boolean') {
|
|
691
759
|
result.directoryShowHidden = candidate.directoryShowHidden;
|
|
692
760
|
}
|
|
@@ -700,11 +768,6 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
700
768
|
}
|
|
701
769
|
}
|
|
702
770
|
|
|
703
|
-
// Message limit — single setting for fetch / trim / Load More chunk
|
|
704
|
-
if (typeof candidate.messageLimit === 'number' && Number.isFinite(candidate.messageLimit)) {
|
|
705
|
-
result.messageLimit = Math.max(10, Math.min(500, Math.round(candidate.messageLimit)));
|
|
706
|
-
}
|
|
707
|
-
|
|
708
771
|
const skillCatalogs = sanitizeSkillCatalogs(candidate.skillCatalogs);
|
|
709
772
|
if (skillCatalogs) {
|
|
710
773
|
result.skillCatalogs = skillCatalogs;
|
|
@@ -888,6 +951,16 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
888
951
|
}
|
|
889
952
|
}
|
|
890
953
|
|
|
954
|
+
// The registry is the last word on what a client may persist: a key the
|
|
955
|
+
// code above still names but the registry no longer lists is dropped here,
|
|
956
|
+
// so the two cannot drift apart silently (settings-helpers.test.js checks
|
|
957
|
+
// the other direction).
|
|
958
|
+
for (const key of Object.keys(result)) {
|
|
959
|
+
if (!isPersistableSettingsKey(key)) {
|
|
960
|
+
delete result[key];
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
|
|
891
964
|
return result;
|
|
892
965
|
};
|
|
893
966
|
|
|
@@ -898,13 +971,6 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
898
971
|
? current.securityScopedBookmarks
|
|
899
972
|
: [];
|
|
900
973
|
|
|
901
|
-
const nextTypographySizes = changes.typographySizes
|
|
902
|
-
? {
|
|
903
|
-
...(current.typographySizes || {}),
|
|
904
|
-
...changes.typographySizes
|
|
905
|
-
}
|
|
906
|
-
: current.typographySizes;
|
|
907
|
-
|
|
908
974
|
const next = {
|
|
909
975
|
...current,
|
|
910
976
|
...changes,
|
|
@@ -913,7 +979,6 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
913
979
|
baseBookmarks.filter((entry) => typeof entry === 'string' && entry.length > 0)
|
|
914
980
|
)
|
|
915
981
|
),
|
|
916
|
-
typographySizes: nextTypographySizes
|
|
917
982
|
};
|
|
918
983
|
|
|
919
984
|
return next;
|
|
@@ -921,30 +986,37 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
921
986
|
|
|
922
987
|
const formatSettingsResponse = (settings) => {
|
|
923
988
|
const sanitized = sanitizeSettingsUpdate(settings);
|
|
924
|
-
|
|
989
|
+
for (const key of SECRET_SETTINGS_KEYS) {
|
|
990
|
+
delete sanitized[key];
|
|
991
|
+
}
|
|
925
992
|
const bookmarks = normalizeStringArray(settings.securityScopedBookmarks);
|
|
926
993
|
const hasManagedRemoteTunnelToken = typeof settings?.managedRemoteTunnelToken === 'string' && settings.managedRemoteTunnelToken.trim().length > 0;
|
|
994
|
+
const hasDesktopUiPassword = typeof settings?.desktopUiPassword === 'string' && settings.desktopUiPassword.trim().length > 0;
|
|
927
995
|
const pwaAppName = normalizePwaAppName(settings?.pwaAppName, '');
|
|
928
996
|
const pwaOrientation = normalizePwaOrientation(settings?.pwaOrientation, 'system');
|
|
929
997
|
const mobileKeyboardMode = normalizeMobileKeyboardMode(settings?.mobileKeyboardMode, 'native');
|
|
998
|
+
const inputHistoryScope = sanitized.inputHistoryScope ?? DEFAULT_INPUT_HISTORY_SCOPE;
|
|
999
|
+
const inputHistoryLimit = sanitized.inputHistoryLimit ?? DEFAULT_INPUT_HISTORY_LIMIT;
|
|
930
1000
|
|
|
931
1001
|
return {
|
|
932
1002
|
...sanitized,
|
|
933
1003
|
hasManagedRemoteTunnelToken,
|
|
1004
|
+
hasDesktopUiPassword,
|
|
934
1005
|
// Tells the client whether agent memory exists in this build at all, so
|
|
935
1006
|
// its settings row and panel tab can be absent rather than merely off.
|
|
936
1007
|
agentMemoryFeatureAvailable: isAgentMemoryFeatureAvailable(),
|
|
937
1008
|
...(pwaAppName ? { pwaAppName } : {}),
|
|
938
1009
|
pwaOrientation,
|
|
939
1010
|
mobileKeyboardMode,
|
|
1011
|
+
inputHistoryScope,
|
|
1012
|
+
inputHistoryLimit,
|
|
940
1013
|
securityScopedBookmarks: bookmarks,
|
|
941
1014
|
pinnedDirectories: normalizeStringArray(settings.pinnedDirectories),
|
|
942
|
-
|
|
943
|
-
...(process.env.OPENCHAMBER_RUNTIME === 'desktop'
|
|
1015
|
+
...(process.env.AIWORKER_RUNTIME === 'desktop'
|
|
944
1016
|
? {
|
|
945
|
-
desktopLanAccessActive: process.env.
|
|
1017
|
+
desktopLanAccessActive: process.env.AIWORKER_DESKTOP_LAN_ACCESS_ACTIVE === 'true',
|
|
946
1018
|
desktopLanAccessBlockedReason:
|
|
947
|
-
process.env.
|
|
1019
|
+
process.env.AIWORKER_DESKTOP_LAN_ACCESS_BLOCKED_REASON === 'missing-password'
|
|
948
1020
|
? 'missing-password'
|
|
949
1021
|
: null,
|
|
950
1022
|
}
|