@vantran-se/openchamber-web 1.24.4 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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-B82Oye3V.js} +1 -1
- package/dist/assets/DiffView-DJLmWn6Z.js +4 -0
- package/dist/assets/FilesView-DjksmZRo.js +17 -0
- package/dist/assets/{GitView-Byu2DY7s.js → GitView-DiUsUIgr.js} +4 -4
- package/dist/assets/{GuestAttachDialog-B808E0-d.js → GuestAttachDialog-CYwWYLr3.js} +1 -1
- package/dist/assets/GuestSurfacePane-CmctyRI4.js +1 -0
- package/dist/assets/{JsonTreeView-VW_7czo3.js → JsonTreeView-DOHHcbgJ.js} +1 -1
- package/dist/assets/LinearIssuesView-DaqnylcV.js +1 -0
- package/dist/assets/MarkdownImageGallery-HJNvWt7L.js +1 -0
- package/dist/assets/MarkdownRendererImpl-nDZRGg2I.js +12 -0
- package/dist/assets/OnboardingScreen-C2B5Bsof.js +1 -0
- package/dist/assets/{PatchDiff-DCjGhlYV.js → PatchDiff-C4FLBjpt.js} +1 -1
- package/dist/assets/{PierreDiffViewer-CEDZNkU2.js → PierreDiffViewer-C_1S9c9n.js} +1 -1
- package/dist/assets/PlanView-_eZvb-G5.js +5 -0
- package/dist/assets/PluginPane-sM8fcZIV.js +3 -0
- package/dist/assets/SettingsView-BRfr46hb.js +29 -0
- package/dist/assets/SettingsWindow-CcUDwQHg.js +1 -0
- package/dist/assets/SubmoduleDiffSummary-CrN1ZGwl.js +1 -0
- package/dist/assets/ToolOutputDialog-Cij4jI09.js +15 -0
- package/dist/assets/ToolPartDiffPreview-BXzwQ-JY.js +8 -0
- package/dist/assets/{VirtualizedFileDiff-NU0FHFhT.js → VirtualizedFileDiff-DSWTLJNH.js} +4 -4
- package/dist/assets/{WalkthroughView-BZyjhqHv.js → WalkthroughView-CpUUgY8H.js} +2 -2
- package/dist/assets/appThemeRegistry-B5tHTkR8.js +1 -0
- package/dist/assets/{commitAndPush-BDftrjr6.js → commitAndPush-D7D8qV8p.js} +1 -1
- package/dist/assets/{computeVirtualFileMetrics-DlWlEM3x.js → computeVirtualFileMetrics-cq9uQ30i.js} +1 -1
- package/dist/assets/de-CUO1-KqF.js +10 -0
- package/dist/assets/es-BlbC6sGJ.js +16 -0
- package/dist/assets/fr-D2nwe_0W.js +14 -0
- package/dist/assets/index-BQOoYIOu.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-D0obJ2p8.js} +1 -1
- package/dist/assets/{isFilePlainText-ue6kCou7.js → isFilePlainText-DB3_rjyW.js} +1 -1
- package/dist/assets/ja-CA7vnDsZ.js +16 -0
- package/dist/assets/ko-Chy6a9l-.js +16 -0
- package/dist/assets/main-B9JFK3vF.js +896 -0
- package/dist/assets/main-Bhiqnrhd.js +2 -0
- package/dist/assets/{markdownCore-CK48LG0z.js → markdownCore-tfqOFaBd.js} +4 -4
- package/dist/assets/miniChat-B0UOL5zA.js +2 -0
- package/dist/assets/mobile-BJppFIEo.js +2 -0
- package/dist/assets/{patchFileDiff-D7QVlovD.js → patchFileDiff-Db6KuwCP.js} +3 -3
- package/dist/assets/pl-CTR5A_1P.js +16 -0
- package/dist/assets/pt-BR-BE1O1KEx.js +16 -0
- package/dist/assets/renderElectronMiniChatApp-Yz5sfoFh.js +2 -0
- package/dist/assets/renderMobileApp-QQ-yB8aY.js +25 -0
- package/dist/assets/runtimeEndpointReset-DKDdzRzm.js +27 -0
- package/dist/assets/scheduledTasksApi-C5sCuNqf.js +1 -0
- package/dist/assets/{shikiHighlight-BPu3JiQs.js → shikiHighlight-xURoo5t_.js} +1 -1
- package/dist/assets/{textMateThemeFromAppTheme-DWqRPo9A.js → textMateThemeFromAppTheme-BZLGuYTU.js} +1 -1
- package/dist/assets/tr-Bh5vK6cW.js +7 -0
- package/dist/assets/uk-CLDkZFy_.js +16 -0
- package/dist/assets/useAppFontEffects-BxrtCnfR.js +7337 -0
- package/dist/assets/{useInlineCommentController-CgS0fnw_.js → useInlineCommentController-CeXuR-SR.js} +2 -2
- package/dist/assets/useRootScrollLock-DgWxezc1.js +2 -0
- package/dist/assets/{vendor-codemirror-language-data-Bx2EHc1O.js → vendor-codemirror-language-data-DOuaQUZ0.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-63H1h21j.js} +2 -2
- package/dist/assets/zh-CN-DODgcmYj.js +16 -0
- package/dist/assets/zh-TW-ByNfIwLA.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
|
@@ -1,40 +1,57 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { excerpt, loadAssistContext } from './context.js';
|
|
2
|
+
import { excerpt, loadAssistContext, newestContentId } from './context.js';
|
|
3
3
|
import { buildAssistPrompt } from './prompt.js';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
// v2 message records are flat and a page lists them newest first.
|
|
6
|
+
const user = (id, text, extra = {}) => ({ id, type: 'user', text, ...extra });
|
|
7
|
+
const assistant = (id, text, extra = {}) => ({
|
|
8
|
+
id,
|
|
9
|
+
type: 'assistant',
|
|
10
|
+
content: text ? [{ type: 'text', text }] : [],
|
|
11
|
+
finish: 'stop',
|
|
12
|
+
time: { completed: 1 },
|
|
13
|
+
model: { providerID: 'provider', id: 'model' },
|
|
14
|
+
...extra,
|
|
8
15
|
});
|
|
9
|
-
const
|
|
10
|
-
|
|
16
|
+
const synthetic = (id, text, extra = {}) => ({ id, type: 'synthetic', text, ...extra });
|
|
17
|
+
// OpenCode closes every turn with an idle marker; a switch is appended when
|
|
18
|
+
// the user changes model or agent between turns.
|
|
19
|
+
const idle = (id, outcome = 'succeeded') => ({ id, type: 'idle', outcome, time: { created: 2 } });
|
|
20
|
+
const modelSwitch = (id) => ({ id, type: 'model-switched', model: { providerID: 'p', id: 'm' } });
|
|
21
|
+
|
|
22
|
+
const pair = (id) => [user(`u${id}`, `request ${id}`), assistant(`a${id}`, `answer ${id}`)];
|
|
23
|
+
|
|
24
|
+
/** `data` is given oldest-first here and reversed, the way OpenCode serves it. */
|
|
25
|
+
const page = (data, next = null) => ({ data: [...data].reverse(), cursor: next ? { next } : {} });
|
|
11
26
|
const load = (readPage) => loadAssistContext({ readPage, signal: new AbortController().signal });
|
|
12
27
|
|
|
13
28
|
describe('session assist context', () => {
|
|
14
29
|
it('stops paging at three human turns and excludes tools and injected instructions', async () => {
|
|
15
30
|
let calls = 0;
|
|
16
31
|
const records = [...pair(1), ...pair(2), ...pair(3), ...pair(4)];
|
|
17
|
-
records.at(-1).
|
|
18
|
-
|
|
32
|
+
records.at(-1).content.push(
|
|
33
|
+
{ type: 'tool', tool: 'bash', state: { output: 'TOOL_PAYLOAD' } },
|
|
34
|
+
);
|
|
35
|
+
const context = await load(async ({ limit, cursor }) => {
|
|
19
36
|
calls++;
|
|
20
37
|
expect(limit).toBe(50);
|
|
21
|
-
expect(
|
|
38
|
+
expect(cursor).toBeUndefined();
|
|
22
39
|
return page(records, 'more');
|
|
23
40
|
});
|
|
24
41
|
expect(calls).toBe(1);
|
|
25
42
|
expect(context.turns.map((t) => t.user.id)).toEqual(['u2', 'u3', 'u4']);
|
|
26
43
|
expect(context.last.text).toBe('answer 4');
|
|
27
44
|
expect(JSON.stringify(context)).not.toContain('TOOL_PAYLOAD');
|
|
28
|
-
expect(JSON.stringify(context)).not.toContain('INJECTED_PROMPT');
|
|
29
45
|
});
|
|
30
46
|
|
|
31
|
-
it('finds the real user across a page boundary and compaction
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
47
|
+
it('finds the real user across a page boundary and past a compaction', async () => {
|
|
48
|
+
// v2 gives compaction its own message role instead of an assistant message
|
|
49
|
+
// flagged `summary`.
|
|
50
|
+
const compaction = { id: 'summary', type: 'compaction', status: 'completed', summary: 'INTERNAL SUMMARY' };
|
|
51
|
+
const final = assistant('final', 'All requested work done');
|
|
52
|
+
const context = await load(async ({ cursor }) => (cursor
|
|
53
|
+
? page([...pair(1), ...pair(2), user('human', 'Finish the requested work')])
|
|
54
|
+
: page([compaction, final], 'older')));
|
|
38
55
|
expect(context.last.id).toBe('final');
|
|
39
56
|
expect(context.turns.at(-1).user.id).toBe('human');
|
|
40
57
|
expect(context.turns.at(-1).assistant.id).toBe('final');
|
|
@@ -43,8 +60,8 @@ describe('session assist context', () => {
|
|
|
43
60
|
|
|
44
61
|
it('retains interrupted requests as progress, not as completed turns', async () => {
|
|
45
62
|
const context = await load(async () => page([
|
|
46
|
-
|
|
47
|
-
|
|
63
|
+
user('u1', 'Implement both fixes'),
|
|
64
|
+
assistant('a1', 'First fix done', { finish: 'tool-calls' }),
|
|
48
65
|
...pair(2),
|
|
49
66
|
]));
|
|
50
67
|
expect(context.turns[0].complete).toBe(false);
|
|
@@ -52,22 +69,31 @@ describe('session assist context', () => {
|
|
|
52
69
|
expect(context.turns[1].complete).toBe(true);
|
|
53
70
|
});
|
|
54
71
|
|
|
55
|
-
it('
|
|
56
|
-
|
|
57
|
-
|
|
72
|
+
it('folds an attached synthetic into the user message it belongs to', async () => {
|
|
73
|
+
// v1 carried an attachment as a synthetic part of the user message; v2
|
|
74
|
+
// sends it as its own turn just before the prompt.
|
|
75
|
+
const attachment = synthetic('s', 'Serialized attachment', {
|
|
58
76
|
metadata: { openchamberContext: { kind: 'chat-quote', quote: 'English quoted source', text: 'Виправ саме це' } },
|
|
59
|
-
}
|
|
60
|
-
const context = await load(async () => page([
|
|
77
|
+
});
|
|
78
|
+
const context = await load(async () => page([attachment, user('u', 'Fix it'), assistant('a', 'Done')]));
|
|
79
|
+
expect(context.turns).toHaveLength(1);
|
|
61
80
|
expect(context.turns[0].user.text).toContain('> English quoted source');
|
|
62
81
|
expect(context.turns[0].user.text).toContain('User comment:\nВиправ саме це');
|
|
63
|
-
expect(context.turns[0].user.
|
|
82
|
+
expect(context.turns[0].user.text).toContain('Fix it');
|
|
83
|
+
expect(context.turns[0].user.authored).toContain('Виправ саме це');
|
|
64
84
|
});
|
|
65
85
|
|
|
66
86
|
it('retains the comment after a large quote and the conclusion after a long answer', async () => {
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
87
|
+
const attachment = synthetic('s', 'attachment', {
|
|
88
|
+
metadata: {
|
|
89
|
+
openchamberContext: { kind: 'browser-annotation', prompt: 'x'.repeat(30_000), text: 'USER_REQUEST_END' },
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
const context = await load(async () => page([
|
|
93
|
+
attachment,
|
|
94
|
+
user('u', 'Look at this'),
|
|
95
|
+
assistant('a', `START${'x'.repeat(30_000)}CONCLUSION`),
|
|
96
|
+
]));
|
|
71
97
|
expect(context.turns[0].user.text).toContain('USER_REQUEST_END');
|
|
72
98
|
expect(context.last.text).toMatch(/^START/);
|
|
73
99
|
expect(context.last.text).toMatch(/CONCLUSION$/);
|
|
@@ -75,10 +101,10 @@ describe('session assist context', () => {
|
|
|
75
101
|
});
|
|
76
102
|
|
|
77
103
|
it('fails explicitly on malformed annotation text instead of losing the comment', async () => {
|
|
78
|
-
const
|
|
79
|
-
openchamberContext: { kind: 'chat-quote', quote: 'source', text: 42 },
|
|
80
|
-
}
|
|
81
|
-
await expect(load(async () => page([
|
|
104
|
+
const attachment = synthetic('s', 'attachment', {
|
|
105
|
+
metadata: { openchamberContext: { kind: 'chat-quote', quote: 'source', text: 42 } },
|
|
106
|
+
});
|
|
107
|
+
await expect(load(async () => page([attachment, user('u', 'Fix'), assistant('a', 'done')]))).rejects.toThrow();
|
|
82
108
|
});
|
|
83
109
|
|
|
84
110
|
it('does not treat a failed or repeated page as complete history', async () => {
|
|
@@ -93,24 +119,68 @@ describe('session assist context', () => {
|
|
|
93
119
|
|
|
94
120
|
it('bounds retrieval and refuses to invent a user for an orphaned answer', async () => {
|
|
95
121
|
let calls = 0;
|
|
96
|
-
const context = await load(async () => page([
|
|
122
|
+
const context = await load(async () => page([assistant(`a${++calls}`, 'answer')], `cursor${calls}`));
|
|
97
123
|
expect(calls).toBe(8);
|
|
98
124
|
expect(context).toBeNull();
|
|
99
125
|
});
|
|
100
126
|
|
|
101
|
-
it('
|
|
127
|
+
it('looks past the idle marker that closes a finished turn', async () => {
|
|
128
|
+
// The ordinary v2 transcript: answer, then `idle`, possibly followed by a
|
|
129
|
+
// switch the user made afterwards. The answer is still the last message.
|
|
130
|
+
for (const tail of [[idle('i')], [idle('i'), modelSwitch('m')], [modelSwitch('m'), idle('i')]]) {
|
|
131
|
+
const context = await load(async () => page([...pair(1), ...tail]));
|
|
132
|
+
expect(context?.last.id).toBe('a1');
|
|
133
|
+
expect(context.turns).toHaveLength(1);
|
|
134
|
+
expect(context.turns[0].assistant.id).toBe('a1');
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('keeps an attachment glued to its prompt across a switch, and a turn across an idle', async () => {
|
|
139
|
+
const attachment = synthetic('s', 'Attached note');
|
|
140
|
+
const context = await load(async () => page([
|
|
141
|
+
...pair(1), idle('i1'),
|
|
142
|
+
attachment, modelSwitch('m'), user('u2', 'Use the note'), assistant('a2', 'Used'), idle('i2'),
|
|
143
|
+
]));
|
|
144
|
+
expect(context.turns.map((turn) => turn.user.id)).toEqual(['u1', 'u2']);
|
|
145
|
+
expect(context.turns[1].user.text).toBe('Attached note\n\nUse the note');
|
|
146
|
+
expect(context.turns[0].complete).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('treats a failed or interrupted idle as evidence the turn did not finish', async () => {
|
|
150
|
+
for (const outcome of ['failed', 'interrupted']) {
|
|
151
|
+
expect(await load(async () => page([...pair(1), idle('i', outcome)]))).toBeNull();
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('keeps paging when a page holds only service records', async () => {
|
|
156
|
+
const context = await load(async ({ cursor }) => (cursor
|
|
157
|
+
? page([...pair(1)])
|
|
158
|
+
: page([idle('i1'), modelSwitch('m'), idle('i2')], 'older')));
|
|
159
|
+
expect(context?.last.id).toBe('a1');
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('names the newest content record of a newest-first page', () => {
|
|
163
|
+
expect(newestContentId([idle('i'), modelSwitch('m'), assistant('a', 'x'), user('u', 'y')])).toBe('a');
|
|
164
|
+
expect(newestContentId([idle('i', 'failed'), assistant('a', 'x')])).toBe('i');
|
|
165
|
+
expect(newestContentId([idle('i')])).toBeNull();
|
|
166
|
+
expect(newestContentId(undefined)).toBeNull();
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('skips unfinished, failed, compaction, and user tails', async () => {
|
|
102
170
|
for (const tail of [
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
171
|
+
user('tail', 'New request'),
|
|
172
|
+
assistant('tail', 'Working', { finish: 'tool-calls' }),
|
|
173
|
+
assistant('tail', 'Failed', { error: { type: 'APIError', message: 'boom' } }),
|
|
174
|
+
{ id: 'tail', type: 'compaction', status: 'completed', summary: 'Summary' },
|
|
107
175
|
]) expect(await load(async () => page([...pair(1), tail]))).toBeNull();
|
|
108
176
|
});
|
|
109
177
|
|
|
110
178
|
it('keeps both sides of the newest exchange within a small model budget', async () => {
|
|
111
179
|
const context = await load(async () => page([
|
|
112
|
-
...pair(1),
|
|
113
|
-
|
|
180
|
+
...pair(1),
|
|
181
|
+
...pair(2),
|
|
182
|
+
user('latest', `REQUEST_START${'u'.repeat(8000)}REQUEST_END`),
|
|
183
|
+
assistant('answer', `ANSWER_START${'a'.repeat(16000)}ANSWER_END`),
|
|
114
184
|
]));
|
|
115
185
|
for (const budget of [1_000, 4_000, 14_000, 32_000, 1_000_000]) {
|
|
116
186
|
const prompt = buildAssistPrompt(context.turns, { recap: true, suggestion: true }, budget);
|
|
@@ -118,15 +188,13 @@ describe('session assist context', () => {
|
|
|
118
188
|
for (const marker of ['REQUEST_START', 'REQUEST_END', 'ANSWER_START', 'ANSWER_END']) expect(prompt.text).toContain(marker);
|
|
119
189
|
}
|
|
120
190
|
expect(buildAssistPrompt(context.turns, { recap: true }, 500)).toBeNull();
|
|
121
|
-
expect(excerpt('long text', 0)).toBe('');
|
|
122
|
-
expect(excerpt('long text', 2)).toBe('lo');
|
|
123
|
-
for (let limit = 0; limit < 60; limit++) expect(excerpt('x'.repeat(100), limit).length).toBeLessThanOrEqual(limit);
|
|
124
191
|
});
|
|
125
192
|
|
|
126
|
-
it('
|
|
127
|
-
expect(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
193
|
+
it('excerpts from both ends so the start and the end both survive', () => {
|
|
194
|
+
expect(excerpt('abcdef', 10)).toBe('abcdef');
|
|
195
|
+
const trimmed = excerpt(`START${'x'.repeat(500)}END`, 100);
|
|
196
|
+
expect(trimmed.length).toBeLessThanOrEqual(100);
|
|
197
|
+
expect(trimmed).toMatch(/^START/);
|
|
198
|
+
expect(trimmed).toMatch(/END$/);
|
|
131
199
|
});
|
|
132
200
|
});
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import os from 'os';
|
|
5
5
|
import path from 'path';
|
|
6
|
-
import {
|
|
6
|
+
import { OpenCode } from '@opencode/client';
|
|
7
7
|
import { readMergedSettingsSync } from '../opencode/settings-files.js';
|
|
8
|
-
import { loadAssistContext } from './context.js';
|
|
8
|
+
import { loadAssistContext, newestContentId } from './context.js';
|
|
9
9
|
import { buildAssistPrompt, buildAssistSystemPrompt } from './prompt.js';
|
|
10
10
|
|
|
11
11
|
const OPENCHAMBER_SETTINGS_FILE = path.join(
|
|
@@ -28,6 +28,8 @@ const RECAP_CHAR_LIMIT = 320;
|
|
|
28
28
|
const SUGGESTION_CHAR_LIMIT = 500;
|
|
29
29
|
const FETCH_TIMEOUT_MS = 5_000;
|
|
30
30
|
const GENERATION_TIMEOUT_MS = 120_000;
|
|
31
|
+
// Enough records to look past the idle marker and a couple of switches.
|
|
32
|
+
const TAIL_RECHECK_LIMIT = 8;
|
|
31
33
|
const QUIET_FAILURE_CODES = new Set(['context-too-small', 'output-exhausted']);
|
|
32
34
|
|
|
33
35
|
const extractJsonObject = (value) => {
|
|
@@ -77,12 +79,22 @@ const extractUserMessage = (payload) => {
|
|
|
77
79
|
};
|
|
78
80
|
};
|
|
79
81
|
|
|
82
|
+
/**
|
|
83
|
+
* The recap and the suggestion live in OpenChamber's own session metadata
|
|
84
|
+
* store: OpenCode 2.x accepts session metadata only when a session is created.
|
|
85
|
+
* `persistSessionAssist(sessionID, directory, assist)` writes it; without that
|
|
86
|
+
* seam the runtime stays inert rather than generating text it cannot save.
|
|
87
|
+
*/
|
|
80
88
|
export const createSessionAssistRuntime = ({
|
|
81
89
|
buildOpenCodeUrl,
|
|
82
90
|
getOpenCodeAuthHeaders,
|
|
83
91
|
getSmallModelService,
|
|
84
92
|
getTargets = getSessionAssistTargets,
|
|
85
93
|
quietMs = IDLE_QUIET_MS,
|
|
94
|
+
persistSessionAssist = null,
|
|
95
|
+
// Archive state is OpenChamber's own in v2 (no OpenCode route sets it), so
|
|
96
|
+
// the runtime asks rather than reading `time.archived` off the record.
|
|
97
|
+
isSessionArchived = async () => false,
|
|
86
98
|
}) => {
|
|
87
99
|
const timers = new Map();
|
|
88
100
|
const inflight = new Map();
|
|
@@ -107,20 +119,32 @@ export const createSessionAssistRuntime = ({
|
|
|
107
119
|
const targets = getTargets();
|
|
108
120
|
if (!targets.recap && !targets.suggestion) return;
|
|
109
121
|
const baseUrl = buildOpenCodeUrl('/', '').replace(/\/$/, '');
|
|
110
|
-
const client =
|
|
122
|
+
const client = OpenCode.make({
|
|
123
|
+
baseUrl,
|
|
124
|
+
headers: {
|
|
125
|
+
...getOpenCodeAuthHeaders(),
|
|
126
|
+
// v2 scopes by header and rejects non-ASCII header values.
|
|
127
|
+
...(directory ? { 'x-opencode-directory': encodeURIComponent(directory) } : {}),
|
|
128
|
+
},
|
|
129
|
+
});
|
|
111
130
|
const requestOptions = () => ({ signal: AbortSignal.any([signal, AbortSignal.timeout(FETCH_TIMEOUT_MS)]) });
|
|
112
131
|
const checkCurrent = () => {
|
|
113
132
|
signal.throwIfAborted();
|
|
114
133
|
if (buildOpenCodeUrl('/', '').replace(/\/$/, '') !== baseUrl) throw new Error('Session assist runtime changed');
|
|
115
134
|
};
|
|
116
|
-
const
|
|
135
|
+
const session = await client.session.get({ sessionID: sessionId }, requestOptions());
|
|
117
136
|
checkCurrent();
|
|
118
137
|
// Reverted history is not the active conversation. A new prompt clears
|
|
119
138
|
// the revert boundary before its next idle event.
|
|
120
|
-
if (session?.id !== sessionId || session.parentID || session.revert?.messageID
|
|
139
|
+
if (session?.id !== sessionId || session.parentID || session.revert?.messageID) return;
|
|
140
|
+
// An archived session is put away: no recap or suggestion is generated for it.
|
|
141
|
+
if (await isSessionArchived(sessionId)) return;
|
|
121
142
|
const context = await loadAssistContext({
|
|
122
143
|
signal,
|
|
123
|
-
readPage: (
|
|
144
|
+
readPage: ({ limit, cursor }) => client.message.list(
|
|
145
|
+
{ sessionID: sessionId, limit, ...(cursor ? { cursor } : { order: 'desc' }) },
|
|
146
|
+
requestOptions(),
|
|
147
|
+
),
|
|
124
148
|
});
|
|
125
149
|
checkCurrent();
|
|
126
150
|
if (!context) return;
|
|
@@ -160,30 +184,28 @@ export const createSessionAssistRuntime = ({
|
|
|
160
184
|
if (recap && scriptMismatch(recap)) recap = '';
|
|
161
185
|
if (suggestion && scriptMismatch(suggestion)) suggestion = '';
|
|
162
186
|
if (!recap && !suggestion) return;
|
|
163
|
-
|
|
187
|
+
// v2 lists newest first. The answer is followed by its `idle` marker and
|
|
188
|
+
// possibly a model or agent switch, so read a short tail and compare the
|
|
189
|
+
// newest content record rather than the newest record.
|
|
190
|
+
const latestPage = await client.message.list({ sessionID: sessionId, limit: TAIL_RECHECK_LIMIT, order: 'desc' }, requestOptions());
|
|
164
191
|
checkCurrent();
|
|
165
|
-
if (
|
|
192
|
+
if (newestContentId(latestPage?.data) !== last.id) return;
|
|
166
193
|
// Never fall back to the pre-generation metadata snapshot after a failed
|
|
167
194
|
// fresh read: doing so overwrites dismissals and unrelated metadata.
|
|
168
|
-
const
|
|
195
|
+
const freshSession = await client.session.get({ sessionID: sessionId }, requestOptions());
|
|
169
196
|
checkCurrent();
|
|
170
|
-
if (freshSession?.id !== sessionId || freshSession.revert?.messageID || freshSession.
|
|
197
|
+
if (freshSession?.id !== sessionId || freshSession.revert?.messageID || freshSession.location?.directory !== session.location?.directory) return;
|
|
198
|
+
if (await isSessionArchived(sessionId)) return;
|
|
171
199
|
const enabled = getTargets();
|
|
172
200
|
if (!enabled.recap) recap = '';
|
|
173
201
|
if (!enabled.suggestion) suggestion = '';
|
|
174
202
|
if (!recap && !suggestion) return;
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
openchamber: {
|
|
182
|
-
...currentNamespace,
|
|
183
|
-
assist: { recap, suggestion, forMessageID: last.id, generatedAt: Date.now() },
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
}, requestOptions());
|
|
203
|
+
await persistSessionAssist(sessionId, directory, {
|
|
204
|
+
recap,
|
|
205
|
+
suggestion,
|
|
206
|
+
forMessageID: last.id,
|
|
207
|
+
generatedAt: Date.now(),
|
|
208
|
+
});
|
|
187
209
|
};
|
|
188
210
|
|
|
189
211
|
const startGeneration = (sessionId, directory, armedAt) => {
|
|
@@ -219,8 +241,16 @@ export const createSessionAssistRuntime = ({
|
|
|
219
241
|
timers.set(sessionId, { timer, armedAt });
|
|
220
242
|
};
|
|
221
243
|
|
|
244
|
+
let parkedNoticeLogged = false;
|
|
222
245
|
const processPayload = (payload, directoryHint = '') => {
|
|
223
246
|
if (stopped) return;
|
|
247
|
+
if (typeof persistSessionAssist !== 'function') {
|
|
248
|
+
if (!parkedNoticeLogged) {
|
|
249
|
+
parkedNoticeLogged = true;
|
|
250
|
+
console.log('[session-assist] parked: no session metadata store is wired, so a recap could not be saved');
|
|
251
|
+
}
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
224
254
|
const status = extractSessionStatus(payload);
|
|
225
255
|
if (status) {
|
|
226
256
|
if (status.type === 'idle') armTimer(status.sessionId, status.directory || directoryHint);
|