@vantran-se/openchamber-web 1.24.3 → 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-BjJHrzmU.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-CDOJy5Ay.js → GitView-BWa7e5vw.js} +4 -4
- package/dist/assets/{GuestAttachDialog-D3S0Rjic.js → GuestAttachDialog-DdOuyZzp.js} +1 -1
- package/dist/assets/GuestSurfacePane-DDfzid3U.js +1 -0
- package/dist/assets/{JsonTreeView-D0C9nU7K.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-DnEhjXcC.js → PatchDiff-DS-IMU1j.js} +1 -1
- package/dist/assets/{PierreDiffViewer-DyxZVVVR.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-0pyr_mHY.js → VirtualizedFileDiff-C763hNCR.js} +4 -4
- package/dist/assets/{WalkthroughView-yNj4nOP5.js → WalkthroughView-lap5btCF.js} +2 -2
- package/dist/assets/appThemeRegistry-u4zw1l0B.js +1 -0
- package/dist/assets/{commitAndPush-DvJKa3Ks.js → commitAndPush-CwGJfJG-.js} +1 -1
- package/dist/assets/{computeVirtualFileMetrics-DxTBMuu-.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-D7FkBMP6.js → isDiffPlainText-D47a6hMP.js} +1 -1
- package/dist/assets/{isFilePlainText-CL2vsrIZ.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-Dh7WEsdM.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-Bsba8KFp.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-8_3csmr6.js → shikiHighlight-DNm2Z_Jc.js} +1 -1
- package/dist/assets/{textMateThemeFromAppTheme-CHo2fCgW.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-DkQ_gqpn.js → useInlineCommentController-CuUuakrt.js} +2 -2
- package/dist/assets/useRootScrollLock-CQIsyERq.js +2 -0
- package/dist/assets/{vendor-codemirror-language-data-CdzUmUyZ.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-B8IcVQAA.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-COVQhWGd.js +0 -4
- package/dist/assets/FilesView-B1V5JxFX.js +0 -13
- package/dist/assets/LinearIssuesView-D7FKg1XJ.js +0 -1
- package/dist/assets/MarkdownImageGallery-BrFjAVEf.js +0 -1
- package/dist/assets/MarkdownRendererImpl-DWepTafh.js +0 -12
- package/dist/assets/OnboardingScreen-Dyxxiqdt.js +0 -1
- package/dist/assets/PlanView-LW2z_EAP.js +0 -5
- package/dist/assets/PluginPane-B4tKno2h.js +0 -3
- package/dist/assets/SettingsView-DEaMulN9.js +0 -29
- package/dist/assets/SettingsWindow-FLDJXOgQ.js +0 -1
- package/dist/assets/SubmoduleDiffSummary-CvVwD-Vi.js +0 -1
- package/dist/assets/ToolOutputDialog-BiP0x2Rw.js +0 -15
- package/dist/assets/ToolPartDiffPreview-CkR4msKP.js +0 -8
- package/dist/assets/appThemeRegistry-BuUKhbYQ.js +0 -1
- package/dist/assets/de-DgxgFyGG.js +0 -10
- package/dist/assets/es-BFsZj5F_.js +0 -16
- package/dist/assets/fr-jdZ5KKQi.js +0 -14
- package/dist/assets/index-CKHjPKbq.js +0 -1
- package/dist/assets/index-Cbci4i1W.js +0 -40
- package/dist/assets/index-DqaMWNrC.css +0 -1
- package/dist/assets/ja-C5kKrhO4.js +0 -16
- package/dist/assets/ko-DXDTT_0O.js +0 -16
- package/dist/assets/main-CZALtVek.js +0 -896
- package/dist/assets/main-CgXMBNvG.js +0 -2
- package/dist/assets/miniChat-CwTmDixi.js +0 -2
- package/dist/assets/mobile-CLf2vCtO.js +0 -2
- package/dist/assets/pl-D-7x4Y8Q.js +0 -16
- package/dist/assets/pt-BR-CSBZrHa8.js +0 -16
- package/dist/assets/renderElectronMiniChatApp-C5gAFBk0.js +0 -2
- package/dist/assets/renderMobileApp-V4hYd32H.js +0 -25
- package/dist/assets/runtimeEndpointReset-DhlHCn-2.js +0 -25
- package/dist/assets/scheduledTasksApi-DzjbLd8P.js +0 -1
- package/dist/assets/tr-Dr-oJ22L.js +0 -7
- package/dist/assets/uk-9Nx83UcI.js +0 -16
- package/dist/assets/useAppFontEffects-khZXpFL_.js +0 -7333
- package/dist/assets/useRootScrollLock-DdvHf9Pt.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-Bxy_Hj3r.js +0 -16
- package/dist/assets/zh-TW-0BB4gpHM.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
|
@@ -27,8 +27,10 @@ const closeServer = (server) => new Promise((resolve, reject) => {
|
|
|
27
27
|
describe('OpenCode proxy SSE forwarding', () => {
|
|
28
28
|
let upstreamServer;
|
|
29
29
|
let proxyServer;
|
|
30
|
+
const originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
|
|
30
31
|
|
|
31
32
|
afterEach(async () => {
|
|
33
|
+
Object.defineProperty(process, 'platform', originalPlatform);
|
|
32
34
|
await closeServer(proxyServer);
|
|
33
35
|
await closeServer(upstreamServer);
|
|
34
36
|
proxyServer = undefined;
|
|
@@ -39,7 +41,7 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
39
41
|
let seenAuthorization = null;
|
|
40
42
|
|
|
41
43
|
const upstream = express();
|
|
42
|
-
upstream.get('/
|
|
44
|
+
upstream.get('/api/event', (req, res) => {
|
|
43
45
|
seenAuthorization = req.headers.authorization ?? null;
|
|
44
46
|
res.setHeader('Content-Type', 'text/event-stream; charset=utf-8');
|
|
45
47
|
res.setHeader('Cache-Control', 'private, max-age=0');
|
|
@@ -85,7 +87,7 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
85
87
|
it('closes downstream SSE when the OpenCode upstream stalls despite proxy heartbeats', async () => {
|
|
86
88
|
let stallTimeoutReads = 0;
|
|
87
89
|
const upstream = express();
|
|
88
|
-
upstream.get('/
|
|
90
|
+
upstream.get('/api/event', (_req, res) => {
|
|
89
91
|
res.setHeader('Content-Type', 'text/event-stream');
|
|
90
92
|
res.flushHeaders();
|
|
91
93
|
setTimeout(() => res.write(':upstream-alive\n\n'), 40);
|
|
@@ -133,7 +135,7 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
133
135
|
|
|
134
136
|
it('holds a request through OpenCode warmup and succeeds once ready (no 503/backoff)', async () => {
|
|
135
137
|
const upstream = express();
|
|
136
|
-
upstream.get('/config/providers', (_req, res) => {
|
|
138
|
+
upstream.get('/api/config/providers', (_req, res) => {
|
|
137
139
|
res.json({ ok: true });
|
|
138
140
|
});
|
|
139
141
|
upstreamServer = await listen(upstream);
|
|
@@ -227,7 +229,7 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
227
229
|
|
|
228
230
|
it('routes generic API requests through external OpenCode base URL', async () => {
|
|
229
231
|
const upstream = express();
|
|
230
|
-
upstream.get('/config/providers', (_req, res) => {
|
|
232
|
+
upstream.get('/api/config/providers', (_req, res) => {
|
|
231
233
|
res.json({ ok: true, source: 'external-host' });
|
|
232
234
|
});
|
|
233
235
|
upstreamServer = await listen(upstream);
|
|
@@ -262,7 +264,7 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
262
264
|
|
|
263
265
|
it('replays parsed urlencoded bodies to generic API proxy requests', async () => {
|
|
264
266
|
const upstream = express();
|
|
265
|
-
upstream.post('/form', express.urlencoded({ extended: true }), (req, res) => {
|
|
267
|
+
upstream.post('/api/form', express.urlencoded({ extended: true }), (req, res) => {
|
|
266
268
|
res.json({ body: req.body });
|
|
267
269
|
});
|
|
268
270
|
upstreamServer = await listen(upstream);
|
|
@@ -302,7 +304,7 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
302
304
|
|
|
303
305
|
it('replays parsed JSON bodies to generic API proxy requests', async () => {
|
|
304
306
|
const upstream = express();
|
|
305
|
-
upstream.post('/session/abc/
|
|
307
|
+
upstream.post('/api/session/abc/prompt', express.json(), (req, res) => {
|
|
306
308
|
res.json({
|
|
307
309
|
body: req.body,
|
|
308
310
|
authorization: req.headers.authorization,
|
|
@@ -335,7 +337,7 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
335
337
|
const proxyPort = proxyServer.address().port;
|
|
336
338
|
|
|
337
339
|
const payload = { messageID: 'msg_1', parts: [{ type: 'text', text: 'hello' }] };
|
|
338
|
-
const response = await fetch(`http://127.0.0.1:${proxyPort}/api/session/abc/
|
|
340
|
+
const response = await fetch(`http://127.0.0.1:${proxyPort}/api/session/abc/prompt`, {
|
|
339
341
|
method: 'POST',
|
|
340
342
|
headers: { 'content-type': 'application/json' },
|
|
341
343
|
body: JSON.stringify(payload),
|
|
@@ -348,44 +350,44 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
348
350
|
expect(Number(data.contentLength)).toBeGreaterThan(0);
|
|
349
351
|
});
|
|
350
352
|
|
|
351
|
-
it(
|
|
353
|
+
it.each([
|
|
354
|
+
['win32', ''],
|
|
355
|
+
['win32', '&directory=%2Flink%2Frepo'],
|
|
356
|
+
['linux', ''],
|
|
357
|
+
['linux', '&directory=%2Flink%2Frepo'],
|
|
358
|
+
])('sanitizes session pages and forwards query params (%s, %s)', async (platform, directoryQuery) => {
|
|
359
|
+
Object.defineProperty(process, 'platform', { value: platform, configurable: true });
|
|
352
360
|
let seenQuery = null;
|
|
353
361
|
let seenAuth = null;
|
|
354
362
|
|
|
355
363
|
const upstream = express();
|
|
356
|
-
upstream.get('/
|
|
364
|
+
upstream.get('/api/session', (req, res) => {
|
|
357
365
|
seenQuery = req.query;
|
|
358
366
|
seenAuth = req.headers.authorization ?? null;
|
|
359
367
|
res.setHeader('X-Next-Cursor', '123');
|
|
360
|
-
res.json(
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
additions: 5,
|
|
380
|
-
deletions: 3,
|
|
381
|
-
files: 2,
|
|
382
|
-
diffs: [{ patch: '@@ -1 +1 @@', additions: 5, deletions: 3 }],
|
|
368
|
+
res.json({
|
|
369
|
+
data: [
|
|
370
|
+
{
|
|
371
|
+
id: 'ses_1',
|
|
372
|
+
projectID: 'proj_1',
|
|
373
|
+
location: { directory: '/repo/app', workspaceID: 'ws_1' },
|
|
374
|
+
subpath: 'app',
|
|
375
|
+
parentID: 'ses_parent',
|
|
376
|
+
title: 'Alpha',
|
|
377
|
+
agent: 'build',
|
|
378
|
+
model: { id: 'gpt-5', providerID: 'openai', variant: 'default' },
|
|
379
|
+
time: { created: 1, updated: 2, archived: 3 },
|
|
380
|
+
cost: 7,
|
|
381
|
+
tokens: { input: 10, output: 20 },
|
|
382
|
+
outcome: 'succeeded',
|
|
383
|
+
fork: { sessionID: 'ses_source', boundary: { type: 'through' } },
|
|
384
|
+
metadata: { openchamber: { kind: 'review', originalSessionID: 'ses_original' } },
|
|
385
|
+
permissions: [{ action: 'deny', resources: ['*'] }],
|
|
386
|
+
revert: { messageID: 'msg_1', partID: 'part_1', snapshot: 'abc123', files: ['a.ts'] },
|
|
383
387
|
},
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
},
|
|
388
|
-
]);
|
|
388
|
+
],
|
|
389
|
+
cursor: { next: '123' },
|
|
390
|
+
});
|
|
389
391
|
});
|
|
390
392
|
upstreamServer = await listen(upstream);
|
|
391
393
|
const upstreamPort = upstreamServer.address().port;
|
|
@@ -415,74 +417,104 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
415
417
|
proxyServer = await listen(app);
|
|
416
418
|
const proxyPort = proxyServer.address().port;
|
|
417
419
|
|
|
418
|
-
const response = await fetch(`http://127.0.0.1:${proxyPort}/api/
|
|
420
|
+
const response = await fetch(`http://127.0.0.1:${proxyPort}/api/session?archived=false&limit=500&cursor=99&roots=true${directoryQuery}`);
|
|
419
421
|
|
|
420
422
|
expect(response.status).toBe(200);
|
|
421
423
|
expect(response.headers.get('x-next-cursor')).toBe('123');
|
|
422
424
|
expect(seenAuth).toBe('Bearer session-token');
|
|
423
|
-
|
|
425
|
+
const expectedQuery = {
|
|
424
426
|
archived: 'false',
|
|
425
427
|
limit: '500',
|
|
426
428
|
cursor: '99',
|
|
427
429
|
roots: 'true',
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
430
|
+
};
|
|
431
|
+
if (directoryQuery) expectedQuery.directory = '/real/repo';
|
|
432
|
+
expect(seenQuery).toEqual(expectedQuery);
|
|
433
|
+
|
|
434
|
+
// The heavy parts of a revert and the per-session permission ruleset are
|
|
435
|
+
// dropped; everything the list view reads survives.
|
|
436
|
+
await expect(response.json()).resolves.toEqual({
|
|
437
|
+
data: [
|
|
438
|
+
{
|
|
439
|
+
id: 'ses_1',
|
|
440
|
+
projectID: 'proj_1',
|
|
441
|
+
location: { directory: '/repo/app', workspaceID: 'ws_1' },
|
|
442
|
+
subpath: 'app',
|
|
443
|
+
parentID: 'ses_parent',
|
|
444
|
+
title: 'Alpha',
|
|
445
|
+
agent: 'build',
|
|
446
|
+
model: { id: 'gpt-5', providerID: 'openai', variant: 'default' },
|
|
447
|
+
time: { created: 1, updated: 2, archived: 3 },
|
|
448
|
+
cost: 7,
|
|
449
|
+
tokens: { input: 10, output: 20 },
|
|
450
|
+
outcome: 'succeeded',
|
|
451
|
+
fork: { sessionID: 'ses_source', boundary: { type: 'through' } },
|
|
452
|
+
metadata: { openchamber: { kind: 'review', originalSessionID: 'ses_original' } },
|
|
453
|
+
revert: { messageID: 'msg_1', partID: 'part_1' },
|
|
454
|
+
},
|
|
455
|
+
],
|
|
456
|
+
cursor: { next: '123' },
|
|
457
|
+
});
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
it.each([
|
|
461
|
+
[200, { data: [], cursor: {} }],
|
|
462
|
+
[503, { error: 'Upstream unavailable' }],
|
|
463
|
+
])('preserves Windows global list status and empty/error payload (%s)', async (status, payload) => {
|
|
464
|
+
Object.defineProperty(process, 'platform', { value: 'win32', configurable: true });
|
|
465
|
+
const upstream = express();
|
|
466
|
+
upstream.get('/api/session', (_req, res) => res.status(status).json(payload));
|
|
467
|
+
upstreamServer = await listen(upstream);
|
|
468
|
+
const upstreamPort = upstreamServer.address().port;
|
|
469
|
+
const baseUrl = `http://127.0.0.1:${upstreamPort}`;
|
|
470
|
+
const app = express();
|
|
471
|
+
registerOpenCodeProxy(app, {
|
|
472
|
+
fs: {},
|
|
473
|
+
OPEN_CODE_READY_GRACE_MS: 0,
|
|
474
|
+
getRuntime: () => ({
|
|
475
|
+
openCodePort: upstreamPort,
|
|
476
|
+
openCodeBaseUrl: baseUrl,
|
|
477
|
+
isOpenCodeReady: true,
|
|
478
|
+
openCodeNotReadySince: 0,
|
|
479
|
+
isRestartingOpenCode: false,
|
|
480
|
+
}),
|
|
481
|
+
getOpenCodeAuthHeaders: () => ({}),
|
|
482
|
+
buildOpenCodeUrl: (requestPath) => `${baseUrl}${requestPath}`,
|
|
483
|
+
ensureOpenCodeApiPrefix: () => {},
|
|
484
|
+
});
|
|
485
|
+
proxyServer = await listen(app);
|
|
486
|
+
const response = await fetch(`http://127.0.0.1:${proxyServer.address().port}/api/session?limit=1`);
|
|
487
|
+
expect(response.status).toBe(status);
|
|
488
|
+
expect(await response.json()).toEqual(payload);
|
|
454
489
|
});
|
|
455
490
|
|
|
456
491
|
it('sanitizes session list responses without sanitizing session detail responses', async () => {
|
|
457
492
|
let seenListQuery = null;
|
|
458
493
|
|
|
459
494
|
const upstream = express();
|
|
460
|
-
upstream.get('/session', (req, res) => {
|
|
495
|
+
upstream.get('/api/session', (req, res) => {
|
|
461
496
|
seenListQuery = req.query;
|
|
462
|
-
res.json(
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
files:
|
|
472
|
-
diffs: [{ patch: '@@ -1 +1 @@', additions: 5, deletions: 3 }],
|
|
497
|
+
res.json({
|
|
498
|
+
data: [
|
|
499
|
+
{
|
|
500
|
+
id: 'ses_1',
|
|
501
|
+
location: { directory: '/repo/app' },
|
|
502
|
+
title: 'Alpha',
|
|
503
|
+
time: { created: 1, updated: 2 },
|
|
504
|
+
metadata: { custom: { value: 'kept' } },
|
|
505
|
+
permissions: [{ action: 'deny', resources: ['*'] }],
|
|
506
|
+
revert: { messageID: 'msg_1', partID: 'part_1', snapshot: 'abc123', files: ['a.ts'] },
|
|
473
507
|
},
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
]);
|
|
508
|
+
],
|
|
509
|
+
cursor: {},
|
|
510
|
+
});
|
|
478
511
|
});
|
|
479
|
-
upstream.get('/session/abc', (_req, res) => {
|
|
512
|
+
upstream.get('/api/session/abc', (_req, res) => {
|
|
480
513
|
res.json({
|
|
481
514
|
id: 'abc',
|
|
482
|
-
directory: '/repo/app',
|
|
515
|
+
location: { directory: '/repo/app' },
|
|
483
516
|
title: 'Detail',
|
|
484
|
-
|
|
485
|
-
revert: { messageID: 'msg_1', snapshot: 'abc123', diff: 'diff --git a/x b/x' },
|
|
517
|
+
revert: { messageID: 'msg_1', snapshot: 'abc123', files: ['a.ts'] },
|
|
486
518
|
});
|
|
487
519
|
});
|
|
488
520
|
upstreamServer = await listen(upstream);
|
|
@@ -517,79 +549,48 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
517
549
|
|
|
518
550
|
expect(listResponse.status).toBe(200);
|
|
519
551
|
expect(seenListQuery).toMatchObject({ directory: '/real/repo' });
|
|
520
|
-
await expect(listResponse.json()).resolves.toEqual(
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
552
|
+
await expect(listResponse.json()).resolves.toEqual({
|
|
553
|
+
data: [
|
|
554
|
+
{
|
|
555
|
+
id: 'ses_1',
|
|
556
|
+
location: { directory: '/repo/app' },
|
|
557
|
+
title: 'Alpha',
|
|
558
|
+
time: { created: 1, updated: 2 },
|
|
559
|
+
metadata: { custom: { value: 'kept' } },
|
|
560
|
+
revert: { messageID: 'msg_1', partID: 'part_1' },
|
|
561
|
+
},
|
|
562
|
+
],
|
|
563
|
+
cursor: {},
|
|
564
|
+
});
|
|
531
565
|
|
|
532
566
|
const detailResponse = await fetch(`http://127.0.0.1:${proxyPort}/api/session/abc`);
|
|
533
567
|
|
|
534
568
|
expect(detailResponse.status).toBe(200);
|
|
535
569
|
await expect(detailResponse.json()).resolves.toEqual({
|
|
536
570
|
id: 'abc',
|
|
537
|
-
directory: '/repo/app',
|
|
571
|
+
location: { directory: '/repo/app' },
|
|
538
572
|
title: 'Detail',
|
|
539
|
-
|
|
540
|
-
revert: { messageID: 'msg_1', snapshot: 'abc123', diff: 'diff --git a/x b/x' },
|
|
573
|
+
revert: { messageID: 'msg_1', snapshot: 'abc123', files: ['a.ts'] },
|
|
541
574
|
});
|
|
542
575
|
});
|
|
543
576
|
|
|
544
|
-
it('
|
|
577
|
+
it('folds OpenChamber-owned archive state and metadata onto sessions it serves', async () => {
|
|
545
578
|
const upstream = express();
|
|
546
|
-
upstream.
|
|
579
|
+
upstream.get('/api/session', (_req, res) => {
|
|
547
580
|
res.json({
|
|
548
|
-
|
|
549
|
-
|
|
581
|
+
data: [
|
|
582
|
+
{ id: 'ses_1', location: { directory: '/repo/app' }, title: 'Alpha', time: { created: 1, updated: 2 }, metadata: { fromOpenCode: true, shared: 'theirs', removed: 'stale' } },
|
|
583
|
+
{ id: 'ses_2', location: { directory: '/repo/app' }, title: 'Beta', time: { created: 1, updated: 3, archived: 999 }, metadata: { openchamber: { reviewSessionID: 'ses_old' } } },
|
|
584
|
+
{ id: 'ses_3', metadata: { untouched: true } },
|
|
585
|
+
],
|
|
586
|
+
cursor: {},
|
|
550
587
|
});
|
|
551
588
|
});
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
const externalBaseUrl = `http://127.0.0.1:${upstreamPort}`;
|
|
555
|
-
|
|
556
|
-
const app = express();
|
|
557
|
-
registerOpenCodeProxy(app, {
|
|
558
|
-
fs: {},
|
|
559
|
-
os: {},
|
|
560
|
-
path,
|
|
561
|
-
OPEN_CODE_READY_GRACE_MS: 0,
|
|
562
|
-
getRuntime: () => ({
|
|
563
|
-
openCodePort: upstreamPort,
|
|
564
|
-
openCodeBaseUrl: externalBaseUrl,
|
|
565
|
-
isOpenCodeReady: true,
|
|
566
|
-
openCodeNotReadySince: 0,
|
|
567
|
-
isRestartingOpenCode: false,
|
|
568
|
-
}),
|
|
569
|
-
getOpenCodeAuthHeaders: () => ({}),
|
|
570
|
-
buildOpenCodeUrl: (requestPath) => `${externalBaseUrl}${requestPath}`,
|
|
571
|
-
ensureOpenCodeApiPrefix: () => {},
|
|
572
|
-
});
|
|
573
|
-
proxyServer = await listen(app);
|
|
574
|
-
const proxyPort = proxyServer.address().port;
|
|
575
|
-
|
|
576
|
-
const payload = { messageID: 'msg_1' };
|
|
577
|
-
const response = await fetch(`http://127.0.0.1:${proxyPort}/api/session/abc/revert`, {
|
|
578
|
-
method: 'POST',
|
|
579
|
-
headers: { 'content-type': 'application/json' },
|
|
580
|
-
body: JSON.stringify(payload),
|
|
589
|
+
upstream.get('/api/session/ses_1', (_req, res) => {
|
|
590
|
+
res.json({ id: 'ses_1', location: { directory: '/repo/app' }, title: 'Alpha', metadata: { fromOpenCode: true, shared: 'theirs', removed: 'stale' } });
|
|
581
591
|
});
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
const data = await response.json();
|
|
585
|
-
expect(data.body).toEqual(payload);
|
|
586
|
-
expect(Number(data.contentLength)).toBeGreaterThan(0);
|
|
587
|
-
});
|
|
588
|
-
|
|
589
|
-
it('uses the long proxy timeout budget for slow upstream responses', async () => {
|
|
590
|
-
const upstream = express();
|
|
591
|
-
upstream.get('/slow', (_req, _res) => {
|
|
592
|
-
// Leave the response open so the proxy timeout path is exercised.
|
|
592
|
+
upstream.get('/api/session/ses_2', (_req, res) => {
|
|
593
|
+
res.json({ id: 'ses_2', metadata: { openchamber: { reviewSessionID: 'ses_old' } } });
|
|
593
594
|
});
|
|
594
595
|
upstreamServer = await listen(upstream);
|
|
595
596
|
const upstreamPort = upstreamServer.address().port;
|
|
@@ -601,7 +602,6 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
601
602
|
os: {},
|
|
602
603
|
path,
|
|
603
604
|
OPEN_CODE_READY_GRACE_MS: 0,
|
|
604
|
-
LONG_REQUEST_TIMEOUT_MS: 50,
|
|
605
605
|
getRuntime: () => ({
|
|
606
606
|
openCodePort: upstreamPort,
|
|
607
607
|
openCodeBaseUrl: externalBaseUrl,
|
|
@@ -612,24 +612,48 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
612
612
|
getOpenCodeAuthHeaders: () => ({}),
|
|
613
613
|
buildOpenCodeUrl: (requestPath) => `${externalBaseUrl}${requestPath}`,
|
|
614
614
|
ensureOpenCodeApiPrefix: () => {},
|
|
615
|
+
getArchivedSessions: async () => ({ ses_1: 4242 }),
|
|
616
|
+
getStoredSessionMetadata: async () => ({
|
|
617
|
+
ses_1: { fromOpenCode: true, openchamber: { goal: { status: 'active' } }, shared: 'ours' },
|
|
618
|
+
ses_2: {},
|
|
619
|
+
}),
|
|
615
620
|
});
|
|
616
621
|
proxyServer = await listen(app);
|
|
617
622
|
const proxyPort = proxyServer.address().port;
|
|
618
623
|
|
|
619
|
-
const
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
624
|
+
const list = await (await fetch(`http://127.0.0.1:${proxyPort}/api/session`)).json();
|
|
625
|
+
// The seeded metadata includes unchanged upstream fields but excludes
|
|
626
|
+
// deleted keys. Empty metadata is authoritative too.
|
|
627
|
+
expect(list.data[0]).toMatchObject({
|
|
628
|
+
id: 'ses_1',
|
|
629
|
+
time: { created: 1, updated: 2, archived: 4242 },
|
|
630
|
+
metadata: { fromOpenCode: true, shared: 'ours', openchamber: { goal: { status: 'active' } } },
|
|
631
|
+
});
|
|
632
|
+
expect(list.data[0].metadata).not.toHaveProperty('removed');
|
|
633
|
+
expect(list.data[1].metadata).toEqual({});
|
|
634
|
+
expect(list.data[2].metadata).toEqual({ untouched: true });
|
|
635
|
+
// The archive file does not mention ses_2, so the stamp OpenCode carries
|
|
636
|
+
// (a session migrated from v1) stays as it is.
|
|
637
|
+
expect(list.data[1].time).toEqual({ created: 1, updated: 3, archived: 999 });
|
|
638
|
+
|
|
639
|
+
const detail = await (await fetch(`http://127.0.0.1:${proxyPort}/api/session/ses_1`)).json();
|
|
640
|
+
expect(detail).toMatchObject({
|
|
641
|
+
id: 'ses_1',
|
|
642
|
+
time: { archived: 4242 },
|
|
643
|
+
metadata: { fromOpenCode: true, shared: 'ours', openchamber: { goal: { status: 'active' } } },
|
|
644
|
+
});
|
|
645
|
+
expect(detail.metadata).not.toHaveProperty('removed');
|
|
646
|
+
const cleared = await (await fetch(`http://127.0.0.1:${proxyPort}/api/session/ses_2`)).json();
|
|
647
|
+
expect(cleared.metadata).toEqual({});
|
|
625
648
|
});
|
|
626
649
|
|
|
627
|
-
it('
|
|
650
|
+
it('forwards unparsed SDK JSON bodies to generic API proxy requests', async () => {
|
|
628
651
|
const upstream = express();
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
652
|
+
upstream.post('/api/session/abc/revert', express.json(), (req, res) => {
|
|
653
|
+
res.json({
|
|
654
|
+
body: req.body,
|
|
655
|
+
contentLength: req.headers['content-length'],
|
|
656
|
+
});
|
|
633
657
|
});
|
|
634
658
|
upstreamServer = await listen(upstream);
|
|
635
659
|
const upstreamPort = upstreamServer.address().port;
|
|
@@ -641,7 +665,6 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
641
665
|
os: {},
|
|
642
666
|
path,
|
|
643
667
|
OPEN_CODE_READY_GRACE_MS: 0,
|
|
644
|
-
LONG_REQUEST_TIMEOUT_MS: 50,
|
|
645
668
|
getRuntime: () => ({
|
|
646
669
|
openCodePort: upstreamPort,
|
|
647
670
|
openCodeBaseUrl: externalBaseUrl,
|
|
@@ -656,20 +679,22 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
656
679
|
proxyServer = await listen(app);
|
|
657
680
|
const proxyPort = proxyServer.address().port;
|
|
658
681
|
|
|
659
|
-
const
|
|
682
|
+
const payload = { messageID: 'msg_1' };
|
|
683
|
+
const response = await fetch(`http://127.0.0.1:${proxyPort}/api/session/abc/revert`, {
|
|
660
684
|
method: 'POST',
|
|
661
685
|
headers: { 'content-type': 'application/json' },
|
|
662
|
-
body: JSON.stringify(
|
|
663
|
-
signal: AbortSignal.timeout(5000),
|
|
686
|
+
body: JSON.stringify(payload),
|
|
664
687
|
});
|
|
665
688
|
|
|
666
689
|
expect(response.status).toBe(200);
|
|
667
|
-
await
|
|
690
|
+
const data = await response.json();
|
|
691
|
+
expect(data.body).toEqual(payload);
|
|
692
|
+
expect(Number(data.contentLength)).toBeGreaterThan(0);
|
|
668
693
|
});
|
|
669
694
|
|
|
670
|
-
it('
|
|
695
|
+
it('uses the long proxy timeout budget for slow upstream responses', async () => {
|
|
671
696
|
const upstream = express();
|
|
672
|
-
upstream.
|
|
697
|
+
upstream.get('/api/slow', (_req, _res) => {
|
|
673
698
|
// Leave the response open so the proxy timeout path is exercised.
|
|
674
699
|
});
|
|
675
700
|
upstreamServer = await listen(upstream);
|
|
@@ -697,13 +722,12 @@ describe('OpenCode proxy SSE forwarding', () => {
|
|
|
697
722
|
proxyServer = await listen(app);
|
|
698
723
|
const proxyPort = proxyServer.address().port;
|
|
699
724
|
|
|
700
|
-
const response = await fetch(`http://127.0.0.1:${proxyPort}/api/
|
|
701
|
-
method: 'POST',
|
|
702
|
-
headers: { 'content-type': 'application/json' },
|
|
703
|
-
body: JSON.stringify({ method: 0 }),
|
|
725
|
+
const response = await fetch(`http://127.0.0.1:${proxyPort}/api/slow`, {
|
|
704
726
|
signal: AbortSignal.timeout(2000),
|
|
705
727
|
});
|
|
706
728
|
|
|
707
729
|
expect(response.status).toBe(504);
|
|
730
|
+
await expect(response.json()).resolves.toMatchObject({ error: 'OpenCode upstream timed out' });
|
|
708
731
|
});
|
|
732
|
+
|
|
709
733
|
});
|
|
@@ -36,11 +36,12 @@ async function createFixture({ timeoutMs = 1000 } = {}) {
|
|
|
36
36
|
instance ??= bootstrap.phase === 'directory-created'
|
|
37
37
|
? { projectID: 'global', config: {} }
|
|
38
38
|
: { projectID: 'project-3464', config: projectConfig };
|
|
39
|
-
if (req.path === '/config') return res.json(instance.config);
|
|
40
|
-
if (req.path === '/session' && req.method === 'POST') {
|
|
39
|
+
if (req.path === '/api/config') return res.json(instance.config);
|
|
40
|
+
if (req.path === '/api/session' && req.method === 'POST') {
|
|
41
41
|
return res.json({ projectID: instance.projectID, directory: req.query.directory, title: req.body.title });
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
// v2 pages the session list as `{ data, cursor }`.
|
|
44
|
+
res.json({ data: [], cursor: {} });
|
|
44
45
|
});
|
|
45
46
|
const upstreamUrl = await listen(upstream);
|
|
46
47
|
const app = express();
|
|
@@ -91,7 +92,7 @@ describe('issue #3464 worktree OpenCode initialization', () => {
|
|
|
91
92
|
expect(fixture.forwarded).toEqual([]);
|
|
92
93
|
fixture.setBootstrap({ status: 'ready', phase: 'setup-ready', error: null });
|
|
93
94
|
expect((await response).status).toBe(200);
|
|
94
|
-
expect(fixture.forwarded).toEqual(['/session']);
|
|
95
|
+
expect(fixture.forwarded).toEqual(['/api/session']);
|
|
95
96
|
});
|
|
96
97
|
|
|
97
98
|
it('does not block unrelated directories while a worktree is pending', async () => {
|