@vantran-se/openchamber-web 1.24.4 → 2.0.1
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 +2 -8
- package/bin/lib/commands-connect-url.js +3 -8
- package/bin/lib/commands-tunnel.js +3 -0
- package/dist/assets/{CodeMirrorCommentWidgets-B4a0JkUz.js → CodeMirrorCommentWidgets-ntXIbhV2.js} +1 -1
- package/dist/assets/DiffView-CjxUovbM.js +4 -0
- package/dist/assets/FilesView-DFWD0RQR.js +17 -0
- package/dist/assets/{GitView-Byu2DY7s.js → GitView-BWa7e5vw.js} +4 -4
- package/dist/assets/{GuestAttachDialog-B808E0-d.js → GuestAttachDialog-DdOuyZzp.js} +1 -1
- package/dist/assets/GuestSurfacePane-DDfzid3U.js +1 -0
- package/dist/assets/{JsonTreeView-VW_7czo3.js → JsonTreeView-3sGwqexh.js} +1 -1
- package/dist/assets/LinearIssuesView-C6dpIdjw.js +1 -0
- package/dist/assets/MarkdownImageGallery-Q7YR_tl4.js +1 -0
- package/dist/assets/MarkdownRendererImpl-DxDV56bL.js +12 -0
- package/dist/assets/OnboardingScreen-rK4Stg__.js +1 -0
- package/dist/assets/{PatchDiff-DCjGhlYV.js → PatchDiff-DS-IMU1j.js} +1 -1
- package/dist/assets/{PierreDiffViewer-CEDZNkU2.js → PierreDiffViewer-DW23KWKZ.js} +1 -1
- package/dist/assets/PlanView-BCk_VobP.js +5 -0
- package/dist/assets/PluginPane-BPP1dbck.js +3 -0
- package/dist/assets/SettingsView-kMmrpn43.js +29 -0
- package/dist/assets/SettingsWindow-BpvD6IYQ.js +1 -0
- package/dist/assets/SubmoduleDiffSummary-BLttSS1X.js +1 -0
- package/dist/assets/ToolOutputDialog-CtqDqbyr.js +15 -0
- package/dist/assets/ToolPartDiffPreview-5FcKdyRy.js +8 -0
- package/dist/assets/{VirtualizedFileDiff-NU0FHFhT.js → VirtualizedFileDiff-C763hNCR.js} +4 -4
- package/dist/assets/{WalkthroughView-BZyjhqHv.js → WalkthroughView-lap5btCF.js} +2 -2
- package/dist/assets/appThemeRegistry-u4zw1l0B.js +1 -0
- package/dist/assets/{commitAndPush-BDftrjr6.js → commitAndPush-CwGJfJG-.js} +1 -1
- package/dist/assets/{computeVirtualFileMetrics-DlWlEM3x.js → computeVirtualFileMetrics-DW5jjX4n.js} +1 -1
- package/dist/assets/de-CndEg67T.js +10 -0
- package/dist/assets/es-DglvPlaC.js +16 -0
- package/dist/assets/fr-DejPCpbS.js +14 -0
- package/dist/assets/index-C2r64QfD.js +1 -0
- package/dist/assets/index-CLcM8HKx.css +1 -0
- package/dist/assets/index-CvLgnuNI.js +41 -0
- package/dist/assets/{isDiffPlainText-CO4e5J_S.js → isDiffPlainText-D47a6hMP.js} +1 -1
- package/dist/assets/{isFilePlainText-ue6kCou7.js → isFilePlainText-B-mGgeKl.js} +1 -1
- package/dist/assets/ja-CVpQawCd.js +16 -0
- package/dist/assets/ko-Bw446h9j.js +16 -0
- package/dist/assets/main-Bz4WWXbr.js +2 -0
- package/dist/assets/main-oreqDsOV.js +896 -0
- package/dist/assets/{markdownCore-CK48LG0z.js → markdownCore-D2e5sp9y.js} +4 -4
- package/dist/assets/miniChat-D1v2gsBI.js +2 -0
- package/dist/assets/mobile-DBj3lCf2.js +2 -0
- package/dist/assets/{patchFileDiff-D7QVlovD.js → patchFileDiff-BpeUOV91.js} +3 -3
- package/dist/assets/pl-BYNlPdhm.js +16 -0
- package/dist/assets/pt-BR-CL-Yfv9H.js +16 -0
- package/dist/assets/renderElectronMiniChatApp-DVtfEB2z.js +2 -0
- package/dist/assets/renderMobileApp-DFp9-xbG.js +25 -0
- package/dist/assets/runtimeEndpointReset-CsIpUep1.js +27 -0
- package/dist/assets/scheduledTasksApi-B5OHVpPM.js +1 -0
- package/dist/assets/{shikiHighlight-BPu3JiQs.js → shikiHighlight-DNm2Z_Jc.js} +1 -1
- package/dist/assets/{textMateThemeFromAppTheme-DWqRPo9A.js → textMateThemeFromAppTheme-DGF2kG7g.js} +1 -1
- package/dist/assets/tr-DzmbxLy-.js +7 -0
- package/dist/assets/uk-C7vQnwro.js +16 -0
- package/dist/assets/useAppFontEffects-Ci3FEaPf.js +7337 -0
- package/dist/assets/{useInlineCommentController-CgS0fnw_.js → useInlineCommentController-CuUuakrt.js} +2 -2
- package/dist/assets/useRootScrollLock-CQIsyERq.js +2 -0
- package/dist/assets/{vendor-codemirror-language-data-Bx2EHc1O.js → vendor-codemirror-language-data-CQa7_1cr.js} +2 -2
- package/dist/assets/vendor-cron-parser-CjvYVigk.js +2 -0
- package/dist/assets/vendor-opencode-client-_BAHQo4R.js +12 -0
- package/dist/assets/{vendor-remixicon-react-BDmGmFCA.js → vendor-remixicon-react-D6dZ0UwF.js} +1 -1
- package/dist/assets/{vendor-zod-CgAdXWZO.js → vendor-zod-Gea9uBlY.js} +1 -1
- package/dist/assets/{web-components-DxX8bZ1o.js → web-components-B6tKQyJN.js} +2 -2
- package/dist/assets/zh-CN-Cl0srS-z.js +16 -0
- package/dist/assets/zh-TW-DtII5bDb.js +16 -0
- package/dist/index.html +13 -7
- package/dist/mini-chat.html +5 -5
- package/dist/mobile.html +5 -5
- package/package.json +6 -5
- package/server/index.d.ts +1 -0
- package/server/index.js +246 -91
- package/server/lib/agent-tool/DOCUMENTATION.md +32 -15
- package/server/lib/agent-tool/runtime.js +135 -54
- package/server/lib/agent-tool/runtime.test.js +155 -87
- package/server/lib/browser-control/DOCUMENTATION.md +37 -2
- package/server/lib/browser-control/provider.js +217 -0
- package/server/lib/browser-control/provider.test.js +251 -0
- package/server/lib/context-obligatory/runtime.js +61 -50
- package/server/lib/context-obligatory/runtime.test.js +62 -162
- package/server/lib/event-stream/DOCUMENTATION.md +12 -1
- package/server/lib/event-stream/delta-coalescer.js +0 -0
- package/server/lib/event-stream/delta-coalescer.test.js +68 -57
- package/server/lib/event-stream/directory-ws-bridge.js +1 -1
- package/server/lib/event-stream/global-hub.js +10 -1
- package/server/lib/event-stream/global-hub.test.js +27 -26
- package/server/lib/event-stream/index.js +6 -0
- package/server/lib/event-stream/protocol.js +26 -19
- package/server/lib/event-stream/protocol.test.js +18 -7
- package/server/lib/event-stream/rebind.test.js +5 -5
- package/server/lib/event-stream/runtime.test.js +17 -15
- package/server/lib/event-stream/translate-v2.js +313 -0
- package/server/lib/event-stream/translate-v2.test.js +209 -0
- package/server/lib/event-stream/upstream-reader.test.js +16 -16
- package/server/lib/fs/DOCUMENTATION.md +4 -2
- package/server/lib/fs/byte-range.js +35 -0
- package/server/lib/fs/byte-range.test.js +31 -0
- package/server/lib/fs/routes.js +47 -42
- package/server/lib/fs/routes.test.js +123 -18
- package/server/lib/git/service.js +12 -0
- package/server/lib/github/DOCUMENTATION.md +1 -1
- package/server/lib/github/pr-status.js +22 -2
- package/server/lib/github/pr-status.test.js +27 -14
- package/server/lib/guests/DOCUMENTATION.md +13 -0
- package/server/lib/guests/catalog.js +12 -0
- package/server/lib/guests/catalog.test.js +33 -0
- package/server/lib/guests/routes.js +10 -1
- package/server/lib/guests/service.js +192 -14
- package/server/lib/guests/service.test.js +201 -1
- package/server/lib/guests/surface.js +630 -0
- package/server/lib/guests/surface.test.js +486 -0
- package/server/lib/markdown-image-grants/routes.js +18 -5
- package/server/lib/markdown-image-grants/routes.test.js +9 -6
- package/server/lib/message-queue/DOCUMENTATION.md +33 -22
- package/server/lib/message-queue/runtime.js +155 -100
- package/server/lib/message-queue/runtime.test.js +168 -82
- package/server/lib/notifications/DOCUMENTATION.md +28 -0
- package/server/lib/notifications/control-stream.http.test.js +68 -0
- package/server/lib/notifications/emitter-runtime.js +15 -0
- package/server/lib/notifications/emitter-runtime.test.js +32 -0
- package/server/lib/notifications/push-runtime.js +5 -1
- package/server/lib/notifications/push-runtime.test.js +2 -2
- package/server/lib/notifications/routes.js +1 -1
- package/server/lib/notifications/runtime.js +115 -26
- package/server/lib/notifications/template-runtime.js +13 -15
- package/server/lib/notifications/template-runtime.test.js +16 -9
- package/server/lib/notifications/trigger-runtime.test.js +187 -0
- package/server/lib/openchamber-control/DOCUMENTATION.md +10 -0
- package/server/lib/openchamber-control/actions.js +3 -2
- package/server/lib/openchamber-control/error.js +1 -1
- package/server/lib/openchamber-control/file-open.js +59 -0
- package/server/lib/openchamber-control/file-open.test.js +57 -0
- package/server/lib/openchamber-control/routes.test.js +12 -0
- package/server/lib/openchamber-control/service.js +102 -49
- package/server/lib/openchamber-control/service.test.js +84 -44
- package/server/lib/openchamber-sessions/archive-store.js +224 -0
- package/server/lib/openchamber-sessions/archive-store.test.js +187 -0
- package/server/lib/openchamber-sessions/opencode-client.js +22 -0
- package/server/lib/openchamber-sessions/routes.js +398 -328
- package/server/lib/openchamber-sessions/routes.test.js +777 -740
- package/server/lib/openchamber-sessions/session-metadata-store.js +285 -0
- package/server/lib/openchamber-sessions/session-metadata-store.test.js +259 -0
- package/server/lib/opencode/DOCUMENTATION.md +449 -29
- package/server/lib/opencode/agents.js +233 -327
- package/server/lib/opencode/auth.js +41 -44
- package/server/lib/opencode/auth.test.js +92 -0
- package/server/lib/opencode/cli-upgrade.d.ts +4 -0
- package/server/lib/opencode/cli-upgrade.js +18 -0
- package/server/lib/opencode/cli-upgrade.test.js +36 -0
- package/server/lib/opencode/commands.js +164 -145
- package/server/lib/opencode/compatibility.d.ts +16 -0
- package/server/lib/opencode/compatibility.js +88 -0
- package/server/lib/opencode/compatibility.test.js +62 -0
- package/server/lib/opencode/config-entity-routes.js +58 -29
- package/server/lib/opencode/config-entity-v2.test.js +290 -0
- package/server/lib/opencode/config-mutation-response.js +17 -7
- package/server/lib/opencode/config-mutation-response.test.js +4 -7
- package/server/lib/opencode/config-paths.test.js +2 -2
- package/server/lib/opencode/config-v2.d.ts +183 -0
- package/server/lib/opencode/config-v2.js +801 -0
- package/server/lib/opencode/config-v2.test.js +466 -0
- package/server/lib/opencode/credential-db.js +144 -0
- package/server/lib/opencode/credential-db.test.js +104 -0
- package/server/lib/opencode/env-runtime.js +48 -9
- package/server/lib/opencode/env-runtime.test.js +45 -0
- package/server/lib/opencode/feature-routes-runtime.js +15 -5
- package/server/lib/opencode/lifecycle-process.test.js +7 -4
- package/server/lib/opencode/lifecycle.js +85 -30
- package/server/lib/opencode/lifecycle.test.js +80 -8
- package/server/lib/opencode/login-shell-env.js +27 -0
- package/server/lib/opencode/managed-config-file.js +119 -0
- package/server/lib/opencode/managed-config-file.test.js +152 -0
- package/server/lib/opencode/managed-plugin-config.js +33 -13
- package/server/lib/opencode/mcp.js +43 -149
- package/server/lib/opencode/network-runtime.js +6 -7
- package/server/lib/opencode/openchamber-routes.test.js +2 -5
- package/server/lib/opencode/plugin-routes.js +3 -3
- package/server/lib/opencode/plugin-routes.test.js +6 -24
- package/server/lib/opencode/plugins.js +91 -40
- package/server/lib/opencode/plugins.test.js +28 -15
- package/server/lib/opencode/providers.js +63 -83
- package/server/lib/opencode/providers.test.js +128 -59
- package/server/lib/opencode/proxy-agent-wiring.test.js +4 -2
- package/server/lib/opencode/proxy.js +179 -129
- package/server/lib/opencode/pwa-manifest-routes.js +4 -2
- package/server/lib/opencode/pwa-manifest-routes.test.js +3 -2
- package/server/lib/opencode/response-envelope.js +14 -0
- package/server/lib/opencode/response-envelope.test.js +23 -0
- package/server/lib/opencode/routes-upgrade.test.js +73 -116
- package/server/lib/opencode/routes.js +121 -428
- package/server/lib/opencode/server-utils-runtime.js +10 -4
- package/server/lib/opencode/session-activity.js +78 -0
- package/server/lib/opencode/session-runtime.js +21 -10
- package/server/lib/opencode/session-runtime.test.js +9 -9
- package/server/lib/opencode/settings-helpers.js +9 -9
- package/server/lib/opencode/settings-helpers.test.js +7 -12
- package/server/lib/opencode/settings-registry.json +6 -8
- package/server/lib/opencode/settings-runtime.js +18 -1
- package/server/lib/opencode/settings-runtime.test.js +31 -2
- package/server/lib/opencode/shared.js +54 -22
- package/server/lib/opencode/shared.test.js +8 -4
- package/server/lib/opencode/shutdown-runtime.js +54 -7
- package/server/lib/opencode/shutdown-runtime.test.js +224 -30
- package/server/lib/opencode/skill-routes.js +23 -24
- package/server/lib/opencode/skills.js +7 -5
- package/server/lib/opencode/tunnel-wiring-runtime.js +2 -1
- package/server/lib/opencode/upgrade-capability.test.js +1 -1
- package/server/lib/opencode/v1-migration-topup.js +288 -0
- package/server/lib/opencode/v1-migration-topup.test.js +266 -0
- package/server/lib/opencode/v2-install.d.ts +8 -0
- package/server/lib/opencode/v2-install.js +158 -0
- package/server/lib/opencode/v2-install.test.js +124 -0
- package/server/lib/opencode/watcher.js +10 -3
- package/server/lib/opencode/watcher.test.js +17 -21
- package/server/lib/opencode/websearch-config.js +66 -0
- package/server/lib/package-manager.js +55 -68
- package/server/lib/package-manager.test.js +241 -75
- package/server/lib/permission-auto-accept/runtime.js +38 -22
- package/server/lib/permission-auto-accept/runtime.test.js +39 -17
- package/server/lib/quota/DOCUMENTATION.md +4 -0
- package/server/lib/quota/providers/xai.js +4 -4
- package/server/lib/relay/tunnel-host.js +4 -1
- package/server/lib/relay/tunnel-host.test.js +7 -0
- package/server/lib/routing/DOCUMENTATION.md +52 -21
- package/server/lib/routing/defaults.js +23 -6
- package/server/lib/routing/jev.js +17 -7
- package/server/lib/routing/routes.http.test.js +68 -33
- package/server/lib/routing/routes.js +65 -22
- package/server/lib/routing/runtime.js +145 -48
- package/server/lib/routing/runtime.test.js +79 -55
- package/server/lib/scheduled-tasks/DOCUMENTATION.md +4 -0
- package/server/lib/scheduled-tasks/issue-2710-double-execution.test.js +51 -46
- package/server/lib/scheduled-tasks/runtime.js +81 -74
- package/server/lib/scheduled-tasks/runtime.test.js +53 -1
- package/server/lib/session-assist/DOCUMENTATION.md +8 -3
- package/server/lib/session-assist/context.js +122 -46
- package/server/lib/session-assist/context.test.js +117 -49
- package/server/lib/session-assist/runtime.js +52 -22
- package/server/lib/session-assist/runtime.test.js +145 -173
- package/server/lib/session-goal/DOCUMENTATION.md +23 -15
- package/server/lib/session-goal/create.js +9 -12
- package/server/lib/session-goal/create.test.js +27 -28
- package/server/lib/session-goal/runtime.js +164 -77
- package/server/lib/session-goal/runtime.test.js +271 -519
- package/server/lib/session-knowledge/DOCUMENTATION.md +5 -0
- package/server/lib/session-knowledge/runtime.js +59 -41
- package/server/lib/session-knowledge/runtime.test.js +90 -20
- package/server/lib/small-model/DOCUMENTATION.md +154 -208
- package/server/lib/small-model/client.js +113 -0
- package/server/lib/small-model/index.js +296 -158
- package/server/lib/small-model/index.test.js +423 -256
- package/server/lib/small-model/routes.js +1 -1
- package/server/lib/spaces/DOCUMENTATION.md +807 -0
- package/server/lib/spaces/code-in-bait.js +185 -0
- package/server/lib/spaces/code-in.js +641 -0
- package/server/lib/spaces/code-in.test.js +1048 -0
- package/server/lib/spaces/errors.js +8 -0
- package/server/lib/spaces/exec-http.js +94 -0
- package/server/lib/spaces/gatekeeper-channel.js +202 -0
- package/server/lib/spaces/gatekeeper-channel.test.js +215 -0
- package/server/lib/spaces/gatekeeper-program.cjs +914 -0
- package/server/lib/spaces/gatekeeper-program.test.js +1391 -0
- package/server/lib/spaces/hardening.js +457 -0
- package/server/lib/spaces/hardening.test.js +368 -0
- package/server/lib/spaces/host-git.js +127 -0
- package/server/lib/spaces/host-git.test.js +137 -0
- package/server/lib/spaces/labels.js +234 -0
- package/server/lib/spaces/labels.test.js +219 -0
- package/server/lib/spaces/layout.js +184 -0
- package/server/lib/spaces/layout.test.js +30 -0
- package/server/lib/spaces/manager.js +82 -0
- package/server/lib/spaces/manager.test.js +114 -0
- package/server/lib/spaces/places/code-in.docker.live.test.js +216 -0
- package/server/lib/spaces/places/contract-suite.js +156 -0
- package/server/lib/spaces/places/contract.docker.live.test.js +7 -0
- package/server/lib/spaces/places/contract.test.js +6 -0
- package/server/lib/spaces/places/docker-engine.js +126 -0
- package/server/lib/spaces/places/docker-live-support.js +202 -0
- package/server/lib/spaces/places/docker-tools.js +186 -0
- package/server/lib/spaces/places/docker.js +587 -0
- package/server/lib/spaces/places/docker.test.js +1610 -0
- package/server/lib/spaces/places/escape-suite.js +1018 -0
- package/server/lib/spaces/places/escape.docker.live.test.js +7 -0
- package/server/lib/spaces/places/fake-docker.js +375 -0
- package/server/lib/spaces/places/memory-place.js +103 -0
- package/server/lib/spaces/places/packed.docker.live.test.js +77 -0
- package/server/lib/spaces/places/registry.js +43 -0
- package/server/lib/spaces/places/registry.test.js +50 -0
- package/server/lib/spaces/places/server.docker.live.test.js +225 -0
- package/server/lib/spaces/run-command.js +261 -0
- package/server/lib/spaces/run-command.test.js +396 -0
- package/server/lib/spaces/space-server.js +190 -0
- package/server/lib/spaces/space-server.test.js +335 -0
- package/server/lib/spaces/tools-filler.js +82 -0
- package/server/lib/spaces/tools-filler.test.js +148 -0
- package/server/lib/spaces/tools-pack.js +49 -0
- package/server/lib/spaces/tools-pack.test.js +57 -0
- package/server/lib/spaces/tools.js +138 -0
- package/server/lib/spaces/tools.test.js +153 -0
- package/server/lib/tts/openai-sdk.js +11 -0
- package/server/lib/tts/service.js +7 -5
- package/server/lib/tts/stt.js +3 -2
- package/server/lib/tunnels/DOCUMENTATION.md +2 -0
- package/server/lib/tunnels/routes.js +7 -0
- package/server/lib/tunnels/routes.test.js +55 -0
- package/server/lib/ui-auth/ui-auth.js +38 -2
- package/server/lib/ui-auth/ui-auth.test.js +42 -0
- package/server/lib/ui-auth/ui-passkeys.js +12 -10
- package/server/lib/walkthrough/DOCUMENTATION.md +10 -1
- package/server/lib/walkthrough/pull-request.js +61 -8
- package/server/lib/walkthrough/pull-request.test.js +54 -1
- package/server/lib/walkthrough/routes.js +20 -0
- package/server/lib/walkthrough/routes.test.js +19 -0
- package/server/opencode-proxy.test.js +190 -166
- package/server/opencode-worktree-readiness.test.js +5 -4
- package/dist/assets/DiffView-B2CD9wC8.js +0 -4
- package/dist/assets/FilesView-C4vMFclc.js +0 -13
- package/dist/assets/LinearIssuesView-EzGNCGrd.js +0 -1
- package/dist/assets/MarkdownImageGallery-B2YUDFaB.js +0 -1
- package/dist/assets/MarkdownRendererImpl-B4ikIzR3.js +0 -12
- package/dist/assets/OnboardingScreen-CQHBSTEi.js +0 -1
- package/dist/assets/PlanView-D3x-pTkZ.js +0 -5
- package/dist/assets/PluginPane-DEcgDQ9h.js +0 -3
- package/dist/assets/SettingsView-CSinuH-1.js +0 -29
- package/dist/assets/SettingsWindow-B5CHoJFZ.js +0 -1
- package/dist/assets/SubmoduleDiffSummary-oxeACCWs.js +0 -1
- package/dist/assets/ToolOutputDialog-tLNWmfcW.js +0 -15
- package/dist/assets/ToolPartDiffPreview-CflzmK-x.js +0 -8
- package/dist/assets/appThemeRegistry-DLicw4dH.js +0 -1
- package/dist/assets/de-Bro6_zyl.js +0 -10
- package/dist/assets/es-Bb9XQZvd.js +0 -16
- package/dist/assets/fr-Dgfzn-IL.js +0 -14
- package/dist/assets/index-CtQNmqUL.js +0 -1
- package/dist/assets/index-DqaMWNrC.css +0 -1
- package/dist/assets/index-Dqc6USl3.js +0 -40
- package/dist/assets/ja-BYsakGFh.js +0 -16
- package/dist/assets/ko-BSaQz9aN.js +0 -16
- package/dist/assets/main-B62_pjL5.js +0 -2
- package/dist/assets/main-BEdcOI2P.js +0 -896
- package/dist/assets/miniChat-LT8Rqofr.js +0 -2
- package/dist/assets/mobile-CqarEynh.js +0 -2
- package/dist/assets/pl-OIviPdoj.js +0 -16
- package/dist/assets/pt-BR-Cltg-E6s.js +0 -16
- package/dist/assets/renderElectronMiniChatApp-COyLTtZx.js +0 -2
- package/dist/assets/renderMobileApp-BC1MHg6g.js +0 -25
- package/dist/assets/runtimeEndpointReset-DdrazOVH.js +0 -25
- package/dist/assets/scheduledTasksApi-B2SWMGEU.js +0 -1
- package/dist/assets/tr-CQI-KPre.js +0 -7
- package/dist/assets/uk-CqW7R4DA.js +0 -16
- package/dist/assets/useAppFontEffects-ne84JBVL.js +0 -7333
- package/dist/assets/useRootScrollLock-Cpf1qoGp.js +0 -2
- package/dist/assets/vendor-cron-parser-CUcP7OfX.js +0 -2
- package/dist/assets/vendor-opencode-sdk-BJ73u-bH.js +0 -7
- package/dist/assets/zh-CN-CVZG_o_J.js +0 -16
- package/dist/assets/zh-TW-D5ZxzCZp.js +0 -16
- package/server/lib/opencode/mcp-oauth-callback.test.js +0 -111
- package/server/lib/routing/feature-flag.js +0 -11
- package/server/lib/small-model/call.js +0 -851
- package/server/lib/small-model/call.test.js +0 -1292
- package/server/lib/small-model/catalog.js +0 -13
- package/server/lib/small-model/resolve.js +0 -131
- package/server/lib/small-model/resolve.test.js +0 -197
- package/server/lib/small-model/runtime-providers.js +0 -164
- package/server/lib/small-model/runtime-providers.test.js +0 -118
- package/server/lib/system-prompt/DOCUMENTATION.md +0 -36
- package/server/lib/system-prompt/runtime.js +0 -49
- package/server/lib/system-prompt/runtime.test.js +0 -76
- package/server/lib/walkthrough/reproduce-2607.test.js +0 -148
|
@@ -11,12 +11,10 @@ const __dirname = path.dirname(__filename);
|
|
|
11
11
|
|
|
12
12
|
const PACKAGE_NAME = '@vantran-se/openchamber-web';
|
|
13
13
|
const PACKAGE_PATH_SEGMENTS = PACKAGE_NAME.split('/');
|
|
14
|
-
const
|
|
15
|
-
const
|
|
14
|
+
const NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME.replace('/', '%2F')}`;
|
|
15
|
+
const GITHUB_RELEASES_URL = 'https://github.com/openchamber/openchamber/releases';
|
|
16
|
+
const GITHUB_RELEASES_API_URL = 'https://api.github.com/repos/openchamber/openchamber/releases';
|
|
16
17
|
const FORK_RELEASES_URL = 'https://github.com/vantran-se/openchamber/releases';
|
|
17
|
-
const FORK_LATEST_RELEASE_API_URL = 'https://api.github.com/repos/vantran-se/openchamber/releases/latest';
|
|
18
|
-
const UPSTREAM_RELEASES_URL = 'https://github.com/openchamber/openchamber/releases';
|
|
19
|
-
const UPSTREAM_RELEASES_API_URL = 'https://api.github.com/repos/openchamber/openchamber/releases';
|
|
20
18
|
let cachedDetectedPm = null;
|
|
21
19
|
|
|
22
20
|
function getSpawnSyncBaseOptions() {
|
|
@@ -99,7 +97,7 @@ async function resolveAndroidApkUrl(version, candidateUrl) {
|
|
|
99
97
|
}
|
|
100
98
|
|
|
101
99
|
try {
|
|
102
|
-
const response = await fetch(`${
|
|
100
|
+
const response = await fetch(`${GITHUB_RELEASES_API_URL}/tags/v${version}`, {
|
|
103
101
|
headers: {
|
|
104
102
|
Accept: 'application/vnd.github+json',
|
|
105
103
|
'User-Agent': 'openchamber-update-check',
|
|
@@ -161,7 +159,7 @@ async function checkForUpdatesFromApi(currentVersion, options = {}) {
|
|
|
161
159
|
const versionComparison = compareVersions(data.latestVersion, currentVersion);
|
|
162
160
|
if (versionComparison < 0) return null;
|
|
163
161
|
|
|
164
|
-
const releaseUrl = `${
|
|
162
|
+
const releaseUrl = `${GITHUB_RELEASES_URL}/tag/v${data.latestVersion}`;
|
|
165
163
|
const downloadUrl = typeof data.downloadUrl === 'string'
|
|
166
164
|
? data.downloadUrl
|
|
167
165
|
: typeof data.download?.url === 'string'
|
|
@@ -661,13 +659,27 @@ export function getUpdateCommand(pm = detectPackageManager()) {
|
|
|
661
659
|
const pmCommand = quoteCommand(resolvePackageManagerCommand(pm));
|
|
662
660
|
switch (pm) {
|
|
663
661
|
case 'pnpm':
|
|
664
|
-
return `${pmCommand} add -g ${PACKAGE_NAME}@latest
|
|
662
|
+
return `${pmCommand} add -g ${PACKAGE_NAME}@latest`;
|
|
665
663
|
case 'yarn':
|
|
666
|
-
return `${pmCommand} global add ${PACKAGE_NAME}@latest
|
|
664
|
+
return `${pmCommand} global add ${PACKAGE_NAME}@latest`;
|
|
667
665
|
case 'bun':
|
|
668
|
-
return `${pmCommand} add -g ${PACKAGE_NAME}@latest
|
|
666
|
+
return `${pmCommand} add -g ${PACKAGE_NAME}@latest`;
|
|
669
667
|
default:
|
|
670
|
-
return `${pmCommand} install -g ${PACKAGE_NAME}@latest
|
|
668
|
+
return `${pmCommand} install -g ${PACKAGE_NAME}@latest`;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
function getUpdateInvocation(pm = detectPackageManager()) {
|
|
673
|
+
const command = resolvePackageManagerCommand(pm);
|
|
674
|
+
switch (pm) {
|
|
675
|
+
case 'pnpm':
|
|
676
|
+
return { command, args: ['add', '-g', `${PACKAGE_NAME}@latest`] };
|
|
677
|
+
case 'yarn':
|
|
678
|
+
return { command, args: ['global', 'add', `${PACKAGE_NAME}@latest`] };
|
|
679
|
+
case 'bun':
|
|
680
|
+
return { command, args: ['add', '-g', `${PACKAGE_NAME}@latest`] };
|
|
681
|
+
default:
|
|
682
|
+
return { command, args: ['install', '-g', `${PACKAGE_NAME}@latest`] };
|
|
671
683
|
}
|
|
672
684
|
}
|
|
673
685
|
|
|
@@ -687,9 +699,9 @@ export function getCurrentVersion() {
|
|
|
687
699
|
/**
|
|
688
700
|
* Fetch latest version from npm registry
|
|
689
701
|
*/
|
|
690
|
-
async function
|
|
702
|
+
async function getLatestVersion() {
|
|
691
703
|
try {
|
|
692
|
-
const response = await fetch(
|
|
704
|
+
const response = await fetch(NPM_REGISTRY_URL, {
|
|
693
705
|
headers: { Accept: 'application/json' },
|
|
694
706
|
signal: AbortSignal.timeout(10000),
|
|
695
707
|
});
|
|
@@ -700,34 +712,7 @@ async function getLatestUpstreamVersion() {
|
|
|
700
712
|
|
|
701
713
|
const data = await response.json();
|
|
702
714
|
return data['dist-tags']?.latest || null;
|
|
703
|
-
} catch {
|
|
704
|
-
return null;
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
async function getLatestForkRelease() {
|
|
709
|
-
try {
|
|
710
|
-
const response = await fetch(FORK_LATEST_RELEASE_API_URL, {
|
|
711
|
-
headers: {
|
|
712
|
-
Accept: 'application/vnd.github+json',
|
|
713
|
-
'User-Agent': 'openchamber-update-check',
|
|
714
|
-
},
|
|
715
|
-
signal: AbortSignal.timeout(10000),
|
|
716
|
-
});
|
|
717
|
-
if (!response.ok) return null;
|
|
718
|
-
|
|
719
|
-
const release = await response.json();
|
|
720
|
-
const tagName = String(release?.tag_name || '');
|
|
721
|
-
const versionMatch = tagName.match(/^v?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/);
|
|
722
|
-
if (!versionMatch) return null;
|
|
723
|
-
|
|
724
|
-
const releaseBody = String(release?.body || '').trim();
|
|
725
|
-
return {
|
|
726
|
-
version: versionMatch[1],
|
|
727
|
-
body: releaseBody || undefined,
|
|
728
|
-
releaseUrl: `${FORK_RELEASES_URL}/tag/v${versionMatch[1]}`,
|
|
729
|
-
};
|
|
730
|
-
} catch {
|
|
715
|
+
} catch (error) {
|
|
731
716
|
return null;
|
|
732
717
|
}
|
|
733
718
|
}
|
|
@@ -778,39 +763,40 @@ export async function checkForUpdates(options = {}) {
|
|
|
778
763
|
const appType = normalizeAppType(options.appType);
|
|
779
764
|
const platform = normalizePlatform(options.platform);
|
|
780
765
|
|
|
781
|
-
if (
|
|
766
|
+
if (currentVersion !== 'unknown') {
|
|
782
767
|
const remote = await checkForUpdatesFromApi(currentVersion, options);
|
|
783
768
|
if (remote) {
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
769
|
+
if (appType !== 'web') {
|
|
770
|
+
return {
|
|
771
|
+
...remote,
|
|
772
|
+
packageManager: pm,
|
|
773
|
+
updateCommand: 'openchamber update',
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
const latestVersion = await getLatestVersion();
|
|
778
|
+
if (!latestVersion) {
|
|
779
|
+
return {
|
|
780
|
+
available: false,
|
|
781
|
+
currentVersion,
|
|
782
|
+
error: 'Unable to determine versions',
|
|
783
|
+
};
|
|
784
|
+
}
|
|
791
785
|
|
|
792
|
-
|
|
793
|
-
const release = await getLatestForkRelease();
|
|
794
|
-
if (!release || currentVersion === 'unknown') {
|
|
786
|
+
const available = compareVersions(latestVersion, currentVersion) > 0;
|
|
795
787
|
return {
|
|
796
|
-
available
|
|
788
|
+
available,
|
|
789
|
+
version: latestVersion,
|
|
797
790
|
currentVersion,
|
|
798
|
-
|
|
791
|
+
body: available && remote.version === latestVersion ? remote.body : undefined,
|
|
792
|
+
releaseUrl: `${FORK_RELEASES_URL}/tag/v${latestVersion}`,
|
|
793
|
+
packageManager: pm,
|
|
794
|
+
updateCommand: 'openchamber update',
|
|
799
795
|
};
|
|
800
796
|
}
|
|
801
|
-
|
|
802
|
-
return {
|
|
803
|
-
available: compareVersions(release.version, currentVersion) > 0,
|
|
804
|
-
version: release.version,
|
|
805
|
-
currentVersion,
|
|
806
|
-
body: release.body,
|
|
807
|
-
releaseUrl: release.releaseUrl,
|
|
808
|
-
packageManager: pm,
|
|
809
|
-
updateCommand: 'openchamber update',
|
|
810
|
-
};
|
|
811
797
|
}
|
|
812
798
|
|
|
813
|
-
const latestVersion = await
|
|
799
|
+
const latestVersion = await getLatestVersion();
|
|
814
800
|
|
|
815
801
|
if (!latestVersion || currentVersion === 'unknown') {
|
|
816
802
|
return {
|
|
@@ -835,9 +821,10 @@ export async function checkForUpdates(options = {}) {
|
|
|
835
821
|
version: latestVersion,
|
|
836
822
|
currentVersion,
|
|
837
823
|
body: changelog,
|
|
838
|
-
releaseUrl: `${
|
|
824
|
+
releaseUrl: `${FORK_RELEASES_URL}/tag/v${latestVersion}`,
|
|
839
825
|
downloadUrl,
|
|
840
826
|
packageManager: pm,
|
|
827
|
+
// Show our CLI command, not raw package manager command
|
|
841
828
|
updateCommand: 'openchamber update',
|
|
842
829
|
};
|
|
843
830
|
}
|
|
@@ -847,14 +834,14 @@ export async function checkForUpdates(options = {}) {
|
|
|
847
834
|
*/
|
|
848
835
|
export function executeUpdate(pm = detectPackageManager(), options = {}) {
|
|
849
836
|
const command = getUpdateCommand(pm);
|
|
837
|
+
const invocation = getUpdateInvocation(pm);
|
|
850
838
|
if (!options?.silent) {
|
|
851
839
|
console.log(`Updating ${PACKAGE_NAME} using ${pm}...`);
|
|
852
840
|
console.log(`Running: ${command}`);
|
|
853
841
|
}
|
|
854
842
|
|
|
855
|
-
const result = spawnSync(command, {
|
|
843
|
+
const result = spawnSync(invocation.command, invocation.args, {
|
|
856
844
|
stdio: 'inherit',
|
|
857
|
-
shell: true,
|
|
858
845
|
...getSpawnSyncBaseOptions(),
|
|
859
846
|
});
|
|
860
847
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
2
3
|
|
|
4
|
+
// Mock child_process to prevent real spawnSync calls that would hang in tests
|
|
3
5
|
vi.mock('node:child_process', () => ({
|
|
4
6
|
spawn: vi.fn(),
|
|
5
7
|
spawnSync: vi.fn(() => ({ status: 0, stdout: '/usr/local/bin', stderr: '' })),
|
|
@@ -13,22 +15,46 @@ const {
|
|
|
13
15
|
getUpdateCommand,
|
|
14
16
|
} = await import('./package-manager.js');
|
|
15
17
|
|
|
18
|
+
/** Helper: create a fetch mock that routes by URL pattern */
|
|
16
19
|
function createFetchMock() {
|
|
17
20
|
const handlers = new Map();
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
|
|
22
|
+
const mock = vi.fn((url, options) => {
|
|
23
|
+
const urlStr = typeof url === 'string' ? url : url.toString();
|
|
24
|
+
|
|
20
25
|
for (const [pattern, response] of handlers) {
|
|
21
|
-
if (
|
|
26
|
+
if (urlStr.includes(pattern)) {
|
|
27
|
+
return Promise.resolve(response);
|
|
28
|
+
}
|
|
22
29
|
}
|
|
23
|
-
|
|
30
|
+
|
|
31
|
+
return Promise.reject(new Error(`Unexpected fetch call: ${urlStr}`));
|
|
24
32
|
});
|
|
33
|
+
|
|
25
34
|
mock.when = (pattern, response) => {
|
|
26
35
|
handlers.set(pattern, response);
|
|
27
36
|
return mock;
|
|
28
37
|
};
|
|
38
|
+
|
|
29
39
|
return mock;
|
|
30
40
|
}
|
|
31
41
|
|
|
42
|
+
describe('fork package update command', () => {
|
|
43
|
+
it('targets the published fork without a runtime environment override', () => {
|
|
44
|
+
expect(getUpdateCommand('npm')).toBe('npm install -g @vantran-se/openchamber-web@latest');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('executes the package manager without a shell', () => {
|
|
48
|
+
spawnSync.mockClear();
|
|
49
|
+
executeUpdate('npm', { silent: true });
|
|
50
|
+
expect(spawnSync).toHaveBeenCalledWith(
|
|
51
|
+
'npm',
|
|
52
|
+
['install', '-g', '@vantran-se/openchamber-web@latest'],
|
|
53
|
+
expect.not.objectContaining({ shell: true }),
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
32
58
|
describe('checkForUpdates', () => {
|
|
33
59
|
let fetchMock;
|
|
34
60
|
let originalFetch;
|
|
@@ -43,86 +69,97 @@ describe('checkForUpdates', () => {
|
|
|
43
69
|
globalThis.fetch = originalFetch;
|
|
44
70
|
});
|
|
45
71
|
|
|
46
|
-
|
|
47
|
-
fetchMock.when('api.github.com/repos/vantran-se/openchamber/releases/latest', {
|
|
48
|
-
ok: true,
|
|
49
|
-
json: async () => ({
|
|
50
|
-
tag_name: 'v1.22.1',
|
|
51
|
-
body: 'Fork release notes',
|
|
52
|
-
}),
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
const result = await checkForUpdates({ currentVersion: '1.22.0' });
|
|
72
|
+
// --- Scenario: API says update available, npm confirms ---
|
|
56
73
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
it('returns available=true when both API and npm confirm a newer version', async () => {
|
|
75
|
+
fetchMock
|
|
76
|
+
.when('api.openchamber.dev', {
|
|
77
|
+
ok: true,
|
|
78
|
+
json: async () => ({
|
|
79
|
+
latestVersion: '1.10.0',
|
|
80
|
+
updateAvailable: true,
|
|
81
|
+
releaseNotes: '## [1.10.0] - 2026-05-01\n\n- Great new feature',
|
|
82
|
+
}),
|
|
83
|
+
})
|
|
84
|
+
.when('registry.npmjs.org', {
|
|
85
|
+
ok: true,
|
|
86
|
+
json: async () => ({
|
|
87
|
+
'dist-tags': { latest: '1.10.0' },
|
|
88
|
+
}),
|
|
89
|
+
})
|
|
90
|
+
.when('raw.githubusercontent.com', {
|
|
91
|
+
ok: true,
|
|
92
|
+
text: async () => '## [1.10.0] - 2026-05-01\n\n- Great new feature',
|
|
93
|
+
});
|
|
73
94
|
|
|
74
|
-
const result = await checkForUpdates({ currentVersion: '1.
|
|
95
|
+
const result = await checkForUpdates({ currentVersion: '1.9.10' });
|
|
75
96
|
|
|
76
|
-
expect(result.available).toBe(
|
|
77
|
-
expect(result.version).toBe('1.
|
|
97
|
+
expect(result.available).toBe(true);
|
|
98
|
+
expect(result.version).toBe('1.10.0');
|
|
99
|
+
expect(result.currentVersion).toBe('1.9.10');
|
|
78
100
|
});
|
|
79
101
|
|
|
80
|
-
|
|
81
|
-
fetchMock.when('api.github.com/repos/vantran-se/openchamber/releases/latest', {
|
|
82
|
-
ok: true,
|
|
83
|
-
json: async () => ({ tag_name: 'v1.22.0-beta.1' }),
|
|
84
|
-
});
|
|
102
|
+
// --- Scenario (THE FIX): API says update available, npm does NOT have it ---
|
|
85
103
|
|
|
86
|
-
|
|
104
|
+
it('returns available=false when API claims update but npm has same version', async () => {
|
|
105
|
+
fetchMock
|
|
106
|
+
.when('api.openchamber.dev', {
|
|
107
|
+
ok: true,
|
|
108
|
+
json: async () => ({
|
|
109
|
+
latestVersion: '1.10.0',
|
|
110
|
+
updateAvailable: true,
|
|
111
|
+
releaseNotes: '## [1.10.0] - 2026-05-01\n\n- Great new feature',
|
|
112
|
+
}),
|
|
113
|
+
})
|
|
114
|
+
.when('registry.npmjs.org', {
|
|
115
|
+
ok: true,
|
|
116
|
+
json: async () => ({
|
|
117
|
+
'dist-tags': { latest: '1.9.10' },
|
|
118
|
+
}),
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const result = await checkForUpdates({ currentVersion: '1.9.10' });
|
|
87
122
|
|
|
88
123
|
expect(result.available).toBe(false);
|
|
89
124
|
});
|
|
90
125
|
|
|
91
|
-
it('
|
|
92
|
-
fetchMock
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
126
|
+
it('returns available=false when npm only has a prerelease of the current version', async () => {
|
|
127
|
+
fetchMock
|
|
128
|
+
.when('api.openchamber.dev', Promise.reject(new Error('Network error')))
|
|
129
|
+
.when('registry.npmjs.org', {
|
|
130
|
+
ok: true,
|
|
131
|
+
json: async () => ({
|
|
132
|
+
'dist-tags': { latest: '1.10.0-beta.1' },
|
|
133
|
+
}),
|
|
134
|
+
});
|
|
96
135
|
|
|
97
|
-
const result = await checkForUpdates({ currentVersion: '1.
|
|
136
|
+
const result = await checkForUpdates({ currentVersion: '1.10.0' });
|
|
98
137
|
|
|
99
|
-
expect(result).
|
|
100
|
-
available: false,
|
|
101
|
-
currentVersion: '1.22.0',
|
|
102
|
-
error: 'Unable to determine versions',
|
|
103
|
-
});
|
|
138
|
+
expect(result.available).toBe(false);
|
|
104
139
|
});
|
|
105
140
|
|
|
106
|
-
it('
|
|
107
|
-
fetchMock
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
141
|
+
it('accepts electron desktop update claims without npm cross-checking', async () => {
|
|
142
|
+
fetchMock
|
|
143
|
+
.when('api.openchamber.dev', {
|
|
144
|
+
ok: true,
|
|
145
|
+
json: async () => ({
|
|
146
|
+
latestVersion: '1.10.0',
|
|
147
|
+
updateAvailable: true,
|
|
148
|
+
releaseNotes: '## [1.10.0] - 2026-05-01\n\n- Great new feature',
|
|
149
|
+
}),
|
|
150
|
+
});
|
|
115
151
|
|
|
116
152
|
const result = await checkForUpdates({
|
|
117
153
|
appType: 'desktop-electron',
|
|
118
|
-
currentVersion: '1.
|
|
154
|
+
currentVersion: '1.9.10',
|
|
119
155
|
installId: '4f4dfead-9688-4c4f-97d7-4607fbbfc3ab',
|
|
120
156
|
platform: 'windows',
|
|
121
157
|
arch: 'arm64',
|
|
122
158
|
});
|
|
123
159
|
|
|
124
160
|
expect(result.available).toBe(true);
|
|
125
|
-
expect(result.version).toBe('1.
|
|
161
|
+
expect(result.version).toBe('1.10.0');
|
|
162
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
126
163
|
expect(JSON.parse(fetchMock.mock.calls[0][1].body)).toMatchObject({
|
|
127
164
|
installId: '4f4dfead-9688-4c4f-97d7-4607fbbfc3ab',
|
|
128
165
|
platform: 'windows',
|
|
@@ -130,23 +167,31 @@ describe('checkForUpdates', () => {
|
|
|
130
167
|
});
|
|
131
168
|
});
|
|
132
169
|
|
|
133
|
-
it('resolves an Android APK asset
|
|
170
|
+
it('resolves an Android APK asset when the update API returns an AAB', async () => {
|
|
134
171
|
fetchMock
|
|
135
172
|
.when('api.openchamber.dev', {
|
|
136
173
|
ok: true,
|
|
137
174
|
json: async () => ({
|
|
138
|
-
latestVersion: '1.
|
|
175
|
+
latestVersion: '1.10.0',
|
|
139
176
|
updateAvailable: true,
|
|
140
|
-
downloadUrl: 'https://github.com/openchamber/openchamber/releases/download/v1.
|
|
177
|
+
downloadUrl: 'https://github.com/openchamber/openchamber/releases/download/v1.10.0/OpenChamber-1.10.0-42-android.aab',
|
|
141
178
|
}),
|
|
142
179
|
})
|
|
143
|
-
.when('api.github.com/repos/openchamber/openchamber/releases/tags/v1.
|
|
180
|
+
.when('api.github.com/repos/openchamber/openchamber/releases/tags/v1.10.0', {
|
|
144
181
|
ok: true,
|
|
145
182
|
json: async () => ({
|
|
146
183
|
assets: [
|
|
147
184
|
{
|
|
148
|
-
name: 'OpenChamber-1.
|
|
149
|
-
browser_download_url: 'https://downloads.example/OpenChamber-1.
|
|
185
|
+
name: 'OpenChamber-1.10.0-42-android.aab',
|
|
186
|
+
browser_download_url: 'https://downloads.example/OpenChamber-1.10.0-42-android.aab',
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
name: 'app-release.apk',
|
|
190
|
+
browser_download_url: 'https://downloads.example/app-release.apk',
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: 'OpenChamber-1.10.0-42-android.apk',
|
|
194
|
+
browser_download_url: 'https://downloads.example/OpenChamber-1.10.0-42-android.apk',
|
|
150
195
|
},
|
|
151
196
|
],
|
|
152
197
|
}),
|
|
@@ -155,18 +200,139 @@ describe('checkForUpdates', () => {
|
|
|
155
200
|
const result = await checkForUpdates({
|
|
156
201
|
appType: 'mobile-capacitor',
|
|
157
202
|
platform: 'android',
|
|
158
|
-
currentVersion: '1.
|
|
203
|
+
currentVersion: '1.9.10',
|
|
159
204
|
});
|
|
160
205
|
|
|
161
|
-
expect(result.downloadUrl).toBe('https://downloads.example/OpenChamber-1.
|
|
206
|
+
expect(result.downloadUrl).toBe('https://downloads.example/OpenChamber-1.10.0-42-android.apk');
|
|
162
207
|
});
|
|
163
|
-
});
|
|
164
208
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
209
|
+
it('keeps a direct Android APK URL from the update API', async () => {
|
|
210
|
+
const apkUrl = 'https://github.com/openchamber/openchamber/releases/download/v1.10.0/OpenChamber-1.10.0-42-android.apk';
|
|
211
|
+
fetchMock.when('api.openchamber.dev', {
|
|
212
|
+
ok: true,
|
|
213
|
+
json: async () => ({
|
|
214
|
+
latestVersion: '1.10.0',
|
|
215
|
+
updateAvailable: true,
|
|
216
|
+
downloadUrl: apkUrl,
|
|
217
|
+
}),
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
const result = await checkForUpdates({
|
|
221
|
+
appType: 'mobile-capacitor',
|
|
222
|
+
platform: 'android',
|
|
223
|
+
currentVersion: '1.9.10',
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
expect(result.downloadUrl).toBe(apkUrl);
|
|
227
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('returns available=false when API claims update but npm is behind', async () => {
|
|
231
|
+
fetchMock
|
|
232
|
+
.when('api.openchamber.dev', {
|
|
233
|
+
ok: true,
|
|
234
|
+
json: async () => ({
|
|
235
|
+
latestVersion: '1.10.0',
|
|
236
|
+
updateAvailable: true,
|
|
237
|
+
releaseNotes: '## [1.10.0] - 2026-05-01\n\n- Great new feature',
|
|
238
|
+
}),
|
|
239
|
+
})
|
|
240
|
+
.when('registry.npmjs.org', {
|
|
241
|
+
ok: true,
|
|
242
|
+
json: async () => ({
|
|
243
|
+
'dist-tags': { latest: '1.9.9' },
|
|
244
|
+
}),
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const result = await checkForUpdates({ currentVersion: '1.9.10' });
|
|
248
|
+
|
|
249
|
+
expect(result.available).toBe(false);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
// --- Scenario: API says no update, npm agrees ---
|
|
253
|
+
|
|
254
|
+
it('returns available=false when API says no update and versions match', async () => {
|
|
255
|
+
fetchMock.when('api.openchamber.dev', {
|
|
256
|
+
ok: true,
|
|
257
|
+
json: async () => ({
|
|
258
|
+
latestVersion: '1.9.10',
|
|
259
|
+
updateAvailable: false,
|
|
260
|
+
}),
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
const result = await checkForUpdates({ currentVersion: '1.9.10' });
|
|
264
|
+
|
|
265
|
+
expect(result.available).toBe(false);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// --- Scenario: API unreachable, npm fallback ---
|
|
269
|
+
|
|
270
|
+
it('returns available=true from npm fallback when API is unreachable and npm has newer version', async () => {
|
|
271
|
+
fetchMock
|
|
272
|
+
.when('api.openchamber.dev', Promise.reject(new Error('Network error')))
|
|
273
|
+
.when('registry.npmjs.org', {
|
|
274
|
+
ok: true,
|
|
275
|
+
json: async () => ({
|
|
276
|
+
'dist-tags': { latest: '1.10.0' },
|
|
277
|
+
}),
|
|
278
|
+
})
|
|
279
|
+
.when('raw.githubusercontent.com', {
|
|
280
|
+
ok: true,
|
|
281
|
+
text: async () => '## [1.10.0] - 2026-05-01\n\n- Great new feature',
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const result = await checkForUpdates({ currentVersion: '1.9.10' });
|
|
285
|
+
|
|
286
|
+
expect(result.available).toBe(true);
|
|
287
|
+
expect(result.version).toBe('1.10.0');
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('returns available=false from npm fallback when API is unreachable and versions match', async () => {
|
|
291
|
+
fetchMock
|
|
292
|
+
.when('api.openchamber.dev', Promise.reject(new Error('Network error')))
|
|
293
|
+
.when('registry.npmjs.org', {
|
|
294
|
+
ok: true,
|
|
295
|
+
json: async () => ({
|
|
296
|
+
'dist-tags': { latest: '1.9.10' },
|
|
297
|
+
}),
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
const result = await checkForUpdates({ currentVersion: '1.9.10' });
|
|
301
|
+
|
|
302
|
+
expect(result.available).toBe(false);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// --- Scenario: API returns null (bad response), npm fallback ---
|
|
306
|
+
|
|
307
|
+
it('returns available=false when API returns non-ok status and versions match on npm', async () => {
|
|
308
|
+
fetchMock
|
|
309
|
+
.when('api.openchamber.dev', {
|
|
310
|
+
ok: false,
|
|
311
|
+
status: 500,
|
|
312
|
+
json: async () => ({}),
|
|
313
|
+
})
|
|
314
|
+
.when('registry.npmjs.org', {
|
|
315
|
+
ok: true,
|
|
316
|
+
json: async () => ({
|
|
317
|
+
'dist-tags': { latest: '1.9.10' },
|
|
318
|
+
}),
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
const result = await checkForUpdates({ currentVersion: '1.9.10' });
|
|
322
|
+
|
|
323
|
+
expect(result.available).toBe(false);
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// --- Scenario: Both API and npm are unreachable ---
|
|
327
|
+
|
|
328
|
+
it('returns available=false when both sources are unreachable', async () => {
|
|
329
|
+
fetchMock
|
|
330
|
+
.when('api.openchamber.dev', Promise.reject(new Error('Network error')))
|
|
331
|
+
.when('registry.npmjs.org', Promise.reject(new Error('Registry unreachable')));
|
|
332
|
+
|
|
333
|
+
const result = await checkForUpdates({ currentVersion: '1.9.10' });
|
|
334
|
+
|
|
335
|
+
expect(result.available).toBe(false);
|
|
170
336
|
});
|
|
171
337
|
});
|
|
172
338
|
|