@openchambery/web 1.19.22-beta.1 → 2.0.0-beta.3
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 +13 -7
- package/bin/cli-opencode.test.js +208 -0
- package/bin/cli.js +62 -9
- package/bin/lib/cli-startup.js +105 -2
- package/bin/lib/cli-startup.test.js +179 -0
- package/dist/assets/{AgentAvatar-CRaBJXKs.js → AgentAvatar-B_JQoreg.js} +1 -1
- package/dist/assets/AssistantView-ClQAfGOT.js +3 -0
- package/dist/assets/{DiagramView-D1LGK_s2.js → DiagramView-BNnda8qO.js} +1 -1
- package/dist/assets/{FadeInOnReveal-B0kJo9Ii.js → FadeInOnReveal-VYQTSAkr.js} +1 -1
- package/dist/assets/{Icon-BgdfPhNs.js → Icon-BiEQEcih.js} +1 -1
- package/dist/assets/MarkdownRenderer-CJHSsWin.js +2 -0
- package/dist/assets/{MarkdownRendererImpl-DfoCJ1Mq.js → MarkdownRendererImpl-DwrHFGUp.js} +3 -3
- package/dist/assets/{MarkstreamRendererImpl-D2dsW5Lg.js → MarkstreamRendererImpl-CSnbQMu3.js} +1 -1
- package/dist/assets/MobileDetailNavigation-BXr6AGLT.js +1 -0
- package/dist/assets/{MobileShareBridge-2Yjn6wXg.js → MobileShareBridge-D7OE9OP_.js} +2 -2
- package/dist/assets/MobileSurface-D2jUkX9l.js +2 -0
- package/dist/assets/{MultiRunWindow-tTbMFowS.js → MultiRunWindow-DF3iIFCd.js} +1 -1
- package/dist/assets/{OnboardingScreen-CD2KtlF3.js → OnboardingScreen-BjHmlwlw.js} +1 -1
- package/dist/assets/OverlayScrollbar-DLtWO_Gp.js +2 -0
- package/dist/assets/SettingsView-BRxELjow.js +25 -0
- package/dist/assets/{SettingsWindow-zIa76s4t.js → SettingsWindow-BI5swspb.js} +1 -1
- package/dist/assets/{TerminalView-CDdzF4yi.js → TerminalView-BU3x8-fr.js} +1 -1
- package/dist/assets/{ToolOutputDialog-DNqA4uBl.js → ToolOutputDialog-BEWhBcRd.js} +2 -2
- package/dist/assets/appThemeRegistry-4MR0F7Jz.js +1 -0
- package/dist/assets/{button-CI7Q-Zw_.js → button-DKuz3L8l.js} +1 -1
- package/dist/assets/collapsible-DXbDynN4.js +3 -0
- package/dist/assets/context-menu-CqolsLCm.js +1 -0
- package/dist/assets/{desktopHosts-B1ixEylr.js → desktopHosts-CoDkOnyS.js} +1 -1
- package/dist/assets/{desktopRelayRestore-4JmFUw8r.js → desktopRelayRestore-DDlVKyOE.js} +1 -1
- package/dist/assets/{diagram-DdLO8HZ9.js → diagram-D7T8HQgj.js} +1 -1
- package/dist/assets/{dialog-B6pnIYmp.js → dialog-DQYl3W_o.js} +1 -1
- package/dist/assets/es-CN3E_zXj.js +15 -0
- package/dist/assets/{fileMentionTouchSelection-DNeiqns-.js → fileMentionTouchSelection-BZ6ovBYH.js} +1 -1
- package/dist/assets/{fileQueries-DQc8EJUf.js → fileQueries-JrpcsOCs.js} +1 -1
- package/dist/assets/fr-9zZvQZD2.js +13 -0
- package/dist/assets/gitApi-CM42qUed.js +10 -0
- package/dist/assets/{imageSource-BlAJJUEI.js → imageSource-CIl0FL10.js} +1 -1
- package/dist/assets/{input-D-__fwRi.js → input-CzQy8UhV.js} +1 -1
- package/dist/assets/insertionBoundaries-CtkZ9720.js +1 -0
- package/dist/assets/ja-Dnjk_82N.js +15 -0
- package/dist/assets/ko-BxCEE99C.js +15 -0
- package/dist/assets/main-BILgBI3B.js +169 -0
- package/dist/assets/main-BeveiW6F.js +2 -0
- package/dist/assets/markdown-worker-bS5OgGO3.js +2 -0
- package/dist/assets/{markdownHeightCache-BhxqJOvf.js → markdownHeightCache-Cj1I5NDw.js} +1 -1
- package/dist/assets/{markdownTheme-DOfGg-A7.js → markdownTheme-CKac3wKC.js} +1 -1
- package/dist/assets/mcpQueries-D5mQymgM.js +1 -0
- package/dist/assets/miniChat-BgrzM3u7.js +2 -0
- package/dist/assets/mobile-DtYoQE8C.js +2 -0
- package/dist/assets/multirun-jy8dEI96.js +4 -0
- package/dist/assets/{persistence-Ce3AnpEr.js → persistence-C9LQpiOS.js} +2 -2
- package/dist/assets/pl-CNNsWnPM.js +15 -0
- package/dist/assets/platform-BQghHRfp.js +6 -0
- package/dist/assets/pt-BR-BZB2DJMp.js +15 -0
- package/dist/assets/renderElectronMiniChatApp-BGrrmeME.js +2 -0
- package/dist/assets/renderMobileApp-u3c4GtFC.js +28 -0
- package/dist/assets/{runtimeConfig-CMkwoQ_X.js → runtimeConfig-BIGBRGQI.js} +1 -1
- package/dist/assets/{runtimeEndpointReset-ChOxt-J7.js → runtimeEndpointReset-D2savkuw.js} +12 -12
- package/dist/assets/{sessionChangeSummary-NnxcqCTI.js → sessionChangeSummary-eIbpSfrO.js} +1 -1
- package/dist/assets/{sessionLookup-BrU3rFHJ.js → sessionLookup-myHe5ltu.js} +1 -1
- package/dist/assets/{sortable-tabs-strip-Fnfhf3K9.js → sortable-tabs-strip-BQtmHx9r.js} +1 -1
- package/dist/assets/src-CLN7Z-zx.css +2 -0
- package/dist/assets/store-DLCiZaA6.js +15 -0
- package/dist/assets/{terminalApi-xjqssKke.js → terminalApi-BxcdiduX.js} +1 -1
- package/dist/assets/{textarea-bHYxZtfH.js → textarea-CakKvqFw.js} +1 -1
- package/dist/assets/{tooltip-0T5jv0cu.js → tooltip-Cx5gTbdY.js} +1 -1
- package/dist/assets/uk-rwQrxeYM.js +15 -0
- package/dist/assets/{url-_z7evzdK.js → url-CDHnjlsm.js} +1 -1
- package/dist/assets/{useAppFontEffects-C02YFyAv.js → useAppFontEffects-CNeo0aZs.js} +59 -45
- package/dist/assets/{useAssistantUIStore-CMutVh9B.js → useAssistantUIStore-asNG6K7n.js} +1 -1
- package/dist/assets/useDesktopWindowControlsLayout-DBJ56qIo.js +1 -0
- package/dist/assets/useEffectiveDirectory-B4LvR8Gt.js +1 -0
- package/dist/assets/{useFontPreferences-B1JYyzpK.js → useFontPreferences-CUnQ4TVm.js} +1 -1
- package/dist/assets/useMobileNavigationStore-ZHJPxlHt.js +414 -0
- package/dist/assets/{useRuntimeAPIs-DSLXJybW.js → useRuntimeAPIs-DwLtO0c_.js} +1 -1
- package/dist/assets/useSessionAutoCleanup-BIVmrnYU.js +2 -0
- package/dist/assets/{useThemeSystem-DMzWVJaW.js → useThemeSystem-BlNUWH47.js} +1 -1
- package/dist/assets/useUIStore-CQYKJnrg.js +1 -0
- package/dist/assets/{useWorkerHighlightedLines-C9z0ML1z.js → useWorkerHighlightedLines-CJZbJDW3.js} +2 -2
- package/dist/assets/{vendor-base-ui-CnHfUmDN.js → vendor-base-ui-CDjyofeD.js} +1 -1
- package/dist/assets/{vendor-cmdk-CeAGfrLo.js → vendor-cmdk-BFH0UpXX.js} +1 -1
- package/dist/assets/{vendor-dnd-kit-accessibility-BY5LhhUB.js → vendor-dnd-kit-accessibility-BrR3AKvM.js} +1 -1
- package/dist/assets/{vendor-dnd-kit-core-CvWxUPdb.js → vendor-dnd-kit-core-CNfdvk6H.js} +1 -1
- package/dist/assets/{vendor-dnd-kit-sortable-hHdP9lLb.js → vendor-dnd-kit-sortable-DQUaTeGj.js} +1 -1
- package/dist/assets/{vendor-framer-motion-DFy_BSVd.js → vendor-framer-motion-4dogsUk3.js} +1 -1
- package/dist/assets/{vendor-legendapp-list-WE32lwNk.js → vendor-legendapp-list-BU7MdPZR.js} +1 -1
- package/dist/assets/{vendor-markstream-react-DX55XLGO.js → vendor-markstream-react-qHC2FykU.js} +3 -3
- package/dist/assets/vendor-opencode-client-BOe2qpQb.js +12 -0
- package/dist/assets/{vendor-pierre-diffs-DX7XTPG3.js → vendor-pierre-diffs-CUfqC003.js} +1 -1
- package/dist/assets/{vendor-react-DLPElpoQ.js → vendor-react-C94A0AHl.js} +1 -1
- package/dist/assets/{vendor-react-drawio-ECtEwvbc.js → vendor-react-drawio-FVlWqKVE.js} +1 -1
- package/dist/assets/{vendor-reactuses-core-BnW6GxJt.js → vendor-reactuses-core-C2A3EjUi.js} +1 -1
- package/dist/assets/{vendor-sonner-DVzioF3d.js → vendor-sonner-DNqHmUQs.js} +1 -1
- package/dist/assets/{vendor-stream-diffs-DWy3xSmp.js → vendor-stream-diffs-CwbKsmlv.js} +2 -2
- package/dist/assets/{vendor-tanstack-react-query-D7pys_c9.js → vendor-tanstack-react-query-D0iFK57C.js} +1 -1
- package/dist/assets/{vendor-tanstack-react-virtual-tlDgH6PG.js → vendor-tanstack-react-virtual-B2kV6cnT.js} +1 -1
- package/dist/assets/{vendor-yaml-DIcAK3EC.js → vendor-yaml-C9KlJAlj.js} +37 -37
- package/dist/assets/{vendor-zustand-B4dlGEM2.js → vendor-zustand-BqLKf6ZY.js} +1 -1
- package/dist/assets/zh-CN-BvmBDnkD.js +15 -0
- package/dist/assets/zh-TW-9wcHTX0y.js +15 -0
- package/dist/index.html +13 -13
- package/dist/mini-chat.html +13 -13
- package/dist/mobile.html +13 -13
- package/package.json +2 -2
- package/server/index.js +392 -20
- package/server/lib/assistants/DOCUMENTATION.md +26 -21
- package/server/lib/assistants/assign.js +2 -1
- package/server/lib/assistants/contact-store.js +37 -19
- package/server/lib/assistants/contracts.js +11 -1
- package/server/lib/assistants/projection-history.test.js +454 -0
- package/server/lib/assistants/routes.js +11 -5
- package/server/lib/assistants/service.js +850 -294
- package/server/lib/assistants/service.test.js +588 -274
- package/server/lib/conversations/DOCUMENTATION.md +5 -5
- package/server/lib/conversations/service.js +87 -57
- package/server/lib/conversations/service.test.js +132 -100
- package/server/lib/conversations/validation.js +11 -1
- package/server/lib/event-stream/directory-ws-bridge.js +13 -2
- package/server/lib/event-stream/global-hub.js +51 -5
- package/server/lib/event-stream/runtime.js +57 -20
- package/server/lib/event-stream/runtime.test.js +112 -0
- package/server/lib/llm/DOCUMENTATION.md +95 -84
- package/server/lib/llm/catalog.js +111 -45
- package/server/lib/llm/catalog.test.js +121 -59
- package/server/lib/llm/completions.js +41 -12
- package/server/lib/llm/completions.test.js +45 -4
- package/server/lib/llm/generate.js +516 -453
- package/server/lib/llm/generate.test.js +705 -484
- package/server/lib/llm/routes.js +8 -4
- package/server/lib/message-queue/DOCUMENTATION.md +5 -5
- package/server/lib/message-queue/opencode-adapter.js +191 -104
- package/server/lib/message-queue/opencode-adapter.test.js +328 -58
- package/server/lib/message-queue/runtime.js +15 -2
- package/server/lib/message-queue/runtime.test.js +6 -6
- package/server/lib/message-queue/worker.js +7 -1
- package/server/lib/notifications/runtime.js +5 -0
- package/server/lib/opencode/DOCUMENTATION.md +103 -16
- package/server/lib/opencode/agent-document.d.ts +28 -0
- package/server/lib/opencode/agent-document.js +280 -0
- package/server/lib/opencode/agent-document.test.js +137 -0
- package/server/lib/opencode/agents.js +96 -0
- package/server/lib/opencode/auth-state-runtime.js +5 -0
- package/server/lib/opencode/bootstrap-runtime.js +2 -0
- package/server/lib/opencode/config-entity-routes.js +111 -102
- package/server/lib/opencode/config-entity-routes.test.js +123 -10
- package/server/lib/opencode/config-hot-reload.integration.test.js +105 -0
- package/server/lib/opencode/ensure-cli.js +238 -0
- package/server/lib/opencode/ensure-cli.test.js +119 -0
- package/server/lib/opencode/env-runtime.js +208 -111
- package/server/lib/opencode/env-runtime.test.js +211 -14
- package/server/lib/opencode/feature-routes-runtime.js +80 -5
- package/server/lib/opencode/feature-routes-runtime.test.js +18 -0
- package/server/lib/opencode/http-server-connections.js +98 -0
- package/server/lib/opencode/http-server-connections.test.js +321 -0
- package/server/lib/opencode/lifecycle.js +539 -95
- package/server/lib/opencode/lifecycle.test.js +698 -6
- package/server/lib/opencode/managed-capabilities-runtime.js +15 -2
- package/server/lib/opencode/managed-capabilities-runtime.test.js +1 -0
- package/server/lib/opencode/network-runtime.js +28 -16
- package/server/lib/opencode/network-runtime.test.js +68 -4
- package/server/lib/opencode/openchamber-routes.js +7 -1
- package/server/lib/opencode/opencode2-pin.js +139 -0
- package/server/lib/opencode/opencode2-pin.test.js +88 -0
- package/server/lib/opencode/opencode2-sidecar.e2e.test.js +326 -0
- package/server/lib/opencode/owned-runtime-upgrade.js +431 -0
- package/server/lib/opencode/owned-runtime-upgrade.test.js +160 -0
- package/server/lib/opencode/plugin-compatibility.js +15 -0
- package/server/lib/opencode/plugin-compatibility.test.js +21 -0
- package/server/lib/opencode/plugin-routes.js +3 -18
- package/server/lib/opencode/plugin-routes.test.js +9 -9
- package/server/lib/opencode/plugins.js +4 -3
- package/server/lib/opencode/plugins.test.js +12 -0
- package/server/lib/opencode/provider-catalog.js +58 -12
- package/server/lib/opencode/provider-catalog.test.js +48 -0
- package/server/lib/opencode/proxy.js +368 -28
- package/server/lib/opencode/proxy.test.js +338 -0
- package/server/lib/opencode/routes.js +303 -76
- package/server/lib/opencode/routes.test.js +315 -50
- package/server/lib/opencode/runtime-contract.js +401 -0
- package/server/lib/opencode/runtime-contract.test.js +214 -0
- package/server/lib/opencode/server-opencode-fetch.js +242 -0
- package/server/lib/opencode/server-opencode-fetch.test.js +130 -0
- package/server/lib/opencode/server-utils-runtime.js +35 -0
- package/server/lib/opencode/shared-service.integration.test.js +66 -0
- package/server/lib/opencode/shared-service.js +147 -0
- package/server/lib/opencode/shared-service.test.js +93 -0
- package/server/lib/opencode/shared.js +3 -3
- package/server/lib/opencode/shutdown-runtime.js +15 -6
- package/server/lib/opencode/shutdown-runtime.test.js +49 -1
- package/server/lib/opencode/skill-routes.js +26 -40
- package/server/lib/opencode/skill-routes.test.js +71 -7
- package/server/lib/opencode/skills.test.js +15 -0
- package/server/lib/opencode/startup-pipeline-runtime.js +4 -0
- package/server/lib/opencode/static-routes-runtime.js +3 -1
- package/server/lib/opencode/static-routes-runtime.test.js +33 -0
- package/server/lib/opencode/v1-migration-gate.js +157 -0
- package/server/lib/opencode/v1-migration-gate.test.js +111 -0
- package/server/lib/opencode/v2-client.js +60 -0
- package/server/lib/opencode/v2-plugin-host-shim/index.mjs +155 -0
- package/server/lib/opencode/v2-plugin-host-shim/package.json +4 -0
- package/server/lib/opencode/watcher.js +2 -1
- package/server/lib/opencode/watcher.test.js +1 -1
- package/server/lib/permission-auto-accept/DOCUMENTATION.md +5 -5
- package/server/lib/permission-auto-accept/runtime.js +14 -7
- package/server/lib/permission-auto-accept/runtime.test.js +27 -12
- package/server/lib/relay/reasoning-projection.e2e.test.ts +22 -7
- package/server/lib/scheduled-tasks/DOCUMENTATION.md +79 -39
- package/server/lib/scheduled-tasks/managed-tool-route.js +31 -1
- package/server/lib/scheduled-tasks/managed-tool-route.test.js +23 -0
- package/server/lib/scheduled-tasks/routes.js +27 -0
- package/server/lib/scheduled-tasks/routes.test.js +94 -0
- package/server/lib/scheduled-tasks/runtime.js +381 -310
- package/server/lib/scheduled-tasks/runtime.test.js +600 -309
- package/server/lib/session-goal/DOCUMENTATION.md +173 -22
- package/server/lib/session-goal/capability.js +57 -0
- package/server/lib/session-goal/capability.test.js +33 -0
- package/server/lib/session-goal/routes.js +240 -2
- package/server/lib/session-goal/routes.test.js +211 -0
- package/server/lib/session-goal/runtime.js +1617 -113
- package/server/lib/session-goal/runtime.test.js +1500 -70
- package/server/lib/session-index/DOCUMENTATION.md +18 -15
- package/server/lib/session-index/event-ingest.js +89 -16
- package/server/lib/session-index/event-ingest.test.js +73 -0
- package/server/lib/session-index/host-authority-snapshot.js +92 -0
- package/server/lib/session-index/routes.host-archive.test.js +201 -0
- package/server/lib/session-index/routes.js +63 -10
- package/server/lib/session-index/routes.test.js +8 -8
- package/server/lib/session-index/service.js +7 -1
- package/server/lib/session-index/sync-runtime.js +171 -41
- package/server/lib/session-index/sync-runtime.test.js +164 -9
- package/server/lib/session-metadata/DOCUMENTATION.md +86 -0
- package/server/lib/session-metadata/routes.js +193 -0
- package/server/lib/session-metadata/routes.test.js +156 -0
- package/server/lib/session-metadata/session-archive.d.ts +73 -0
- package/server/lib/session-metadata/session-archive.js +654 -0
- package/server/lib/session-metadata/session-archive.test.js +359 -0
- package/server/lib/session-metadata/session-metadata-store.d.ts +36 -0
- package/server/lib/session-metadata/session-metadata-store.js +375 -0
- package/server/lib/session-metadata/session-metadata-store.test.js +379 -0
- package/server/lib/session-metadata/session-projection.d.ts +41 -0
- package/server/lib/session-metadata/session-projection.js +255 -0
- package/server/lib/session-metadata/session-projection.test.js +64 -0
- package/server/lib/session-metadata/system-session.js +55 -0
- package/server/lib/session-metadata/system-session.test.js +55 -0
- package/server/lib/session-title/DOCUMENTATION.md +40 -7
- package/server/lib/session-title/native-runtime.test.js +167 -0
- package/server/lib/session-title/runtime.js +67 -42
- package/server/lib/session-title/session-access.js +46 -0
- package/server/lib/session-title/session-access.test.js +91 -0
- package/server/lib/session-turn-pages/DOCUMENTATION.md +12 -11
- package/server/lib/session-turn-pages/reconcile.service.js +1 -1
- package/server/lib/session-turn-pages/reconcile.service.test.js +16 -0
- package/server/lib/session-turn-pages/routes.js +123 -75
- package/server/lib/session-turn-pages/routes.test.js +566 -0
- package/server/lib/session-turn-pages/service.js +6 -2
- package/server/lib/session-turn-pages/service.test.js +34 -0
- package/server/lib/session-turn-pages/session-message-projection.d.ts +13 -0
- package/server/lib/session-turn-pages/session-message-projection.js +281 -0
- package/server/lib/small-model/DOCUMENTATION.md +101 -146
- package/server/lib/small-model/catalog.js +84 -54
- package/server/lib/small-model/catalog.test.js +111 -9
- package/server/lib/small-model/custom-api.js +68 -0
- package/server/lib/small-model/custom-api.test.js +64 -0
- package/server/lib/small-model/index.js +125 -241
- package/server/lib/small-model/resolve.js +35 -120
- package/server/lib/small-model/resolve.test.js +20 -110
- package/server/lib/small-model/routes.js +1 -3
- package/server/lib/small-model/summary-settings.test.js +157 -253
- package/server/opencode-proxy.test.js +63 -12
- package/dist/assets/AssistantView-BUveAgc4.js +0 -3
- package/dist/assets/MarkdownRenderer-BbrbDH6-.js +0 -2
- package/dist/assets/MobileDetailNavigation-B0aqKXd7.js +0 -1
- package/dist/assets/MobileSurface-DW7WfPsy.js +0 -2
- package/dist/assets/OverlayScrollbar-DrA0Vsg5.js +0 -2
- package/dist/assets/SettingsView-PkXIavr7.js +0 -25
- package/dist/assets/appThemeRegistry-D5Yxg4YF.js +0 -1
- package/dist/assets/collapsible-D5Phaykh.js +0 -1
- package/dist/assets/context-menu-CubSDW2g.js +0 -1
- package/dist/assets/es-DA3MqOo0.js +0 -15
- package/dist/assets/fr-Dbz0CdIA.js +0 -13
- package/dist/assets/gitApi-DXyC4MiV.js +0 -7
- package/dist/assets/insertionBoundaries-KlOVrHHt.js +0 -1
- package/dist/assets/ja-DumanVQA.js +0 -15
- package/dist/assets/ko-C0IkiUjQ.js +0 -15
- package/dist/assets/main-BPS5ylib.js +0 -2
- package/dist/assets/main-Cpd9VWYs.js +0 -169
- package/dist/assets/markdown-worker-CptoICmq.js +0 -2
- package/dist/assets/miniChat-B8_KLWiY.js +0 -2
- package/dist/assets/mobile-CtktKrXn.js +0 -2
- package/dist/assets/multirun-CYfP9Cfm.js +0 -4
- package/dist/assets/pl-B9No6MQp.js +0 -15
- package/dist/assets/platform-0w_Q9_ji.js +0 -2
- package/dist/assets/projectMeta-S1hJ7oBp.js +0 -3
- package/dist/assets/pt-BR-DyQ0WTDh.js +0 -15
- package/dist/assets/renderElectronMiniChatApp-iK14LWm8.js +0 -2
- package/dist/assets/renderMobileApp-DORLPWnb.js +0 -28
- package/dist/assets/src-rS3zCcsC.css +0 -2
- package/dist/assets/store-5B_LDnLM.js +0 -15
- package/dist/assets/uk-C_1KkqyP.js +0 -15
- package/dist/assets/useDesktopWindowControlsLayout-Dnr-jX0C.js +0 -1
- package/dist/assets/useEffectiveDirectory-CZLLyarc.js +0 -1
- package/dist/assets/useMobileNavigationStore-CoCiqNgm.js +0 -413
- package/dist/assets/useSessionAutoCleanup-xQyETQkG.js +0 -2
- package/dist/assets/useUIStore-Bxv3f23A.js +0 -1
- package/dist/assets/vendor-opencode-sdk-C07HQypa.js +0 -7
- package/dist/assets/zh-CN-uWILgBdt.js +0 -15
- package/dist/assets/zh-TW-MYfdvhbD.js +0 -15
- package/server/lib/small-model/call.js +0 -427
- package/server/lib/small-model/call.test.js +0 -382
- package/server/lib/small-model/opencode-session.js +0 -339
- package/server/lib/small-model/opencode-session.test.js +0 -177
package/server/index.js
CHANGED
|
@@ -39,6 +39,7 @@ import { resolveOpenCodeEnvConfig } from './lib/opencode/env-config.js';
|
|
|
39
39
|
import { createHmrStateRuntime } from './lib/opencode/hmr-state-runtime.js';
|
|
40
40
|
import { createOpenCodeNetworkRuntime } from './lib/opencode/network-runtime.js';
|
|
41
41
|
import { createOpenCodeAuthStateRuntime } from './lib/opencode/auth-state-runtime.js';
|
|
42
|
+
import { createSharedOpenCodeService, isSharedServiceEnabled } from './lib/opencode/shared-service.js';
|
|
42
43
|
import { createProjectDirectoryRuntime } from './lib/opencode/project-directory-runtime.js';
|
|
43
44
|
import { createSettingsNormalizationRuntime } from './lib/opencode/settings-normalization-runtime.js';
|
|
44
45
|
import { createSettingsHelpers } from './lib/opencode/settings-helpers.js';
|
|
@@ -52,6 +53,10 @@ import {
|
|
|
52
53
|
} from './lib/opencode/core-routes.js';
|
|
53
54
|
import { registerOpenChamberRoutes } from './lib/opencode/openchamber-routes.js';
|
|
54
55
|
import { createServerUtilsRuntime } from './lib/opencode/server-utils-runtime.js';
|
|
56
|
+
import {
|
|
57
|
+
configureServerOpenCodeFetchGate,
|
|
58
|
+
createServerOpenCodeFetch,
|
|
59
|
+
} from './lib/opencode/server-opencode-fetch.js';
|
|
55
60
|
import { createStaticRoutesRuntime } from './lib/opencode/static-routes-runtime.js';
|
|
56
61
|
import { createSettingsRuntime } from './lib/opencode/settings-runtime.js';
|
|
57
62
|
import { createOpenCodeResolutionRuntime } from './lib/opencode/opencode-resolution-runtime.js';
|
|
@@ -59,6 +64,7 @@ import { createBootstrapRuntime } from './lib/opencode/bootstrap-runtime.js';
|
|
|
59
64
|
import { createSessionRuntime } from './lib/opencode/session-runtime.js';
|
|
60
65
|
import { createOpenCodeWatcherRuntime } from './lib/opencode/watcher.js';
|
|
61
66
|
import { createSessionTitleRuntime } from './lib/session-title/runtime.js';
|
|
67
|
+
import { createTitleSessionAccess } from './lib/session-title/session-access.js';
|
|
62
68
|
import { createSessionIndexService } from './lib/session-index/service.js';
|
|
63
69
|
import { createSessionIndexSyncRuntime } from './lib/session-index/sync-runtime.js';
|
|
64
70
|
import { resolveSessionIndexDbPath } from './lib/session-index/resolve-db-path.js';
|
|
@@ -68,7 +74,20 @@ import { resolveTranscriptCacheDbPath } from './lib/transcript-cache/resolve-db-
|
|
|
68
74
|
import { createMessageQueueRuntime } from './lib/message-queue/runtime.js';
|
|
69
75
|
import { resolveMessageQueueDbPath } from './lib/message-queue/resolve-db-path.js';
|
|
70
76
|
import { createOpenChamberEventBroadcaster } from './lib/opencode/feature-routes-runtime.js';
|
|
71
|
-
import {
|
|
77
|
+
import {
|
|
78
|
+
createSessionGoalRuntime,
|
|
79
|
+
withGoalExecutionGeneration,
|
|
80
|
+
} from './lib/session-goal/runtime.js';
|
|
81
|
+
import { createSessionMetadataStore } from './lib/session-metadata/session-metadata-store.js';
|
|
82
|
+
import {
|
|
83
|
+
createSessionArchiveService,
|
|
84
|
+
createUpstreamSessionFetcher,
|
|
85
|
+
} from './lib/session-metadata/session-archive.js';
|
|
86
|
+
import {
|
|
87
|
+
projectSessionLifecyclePayload,
|
|
88
|
+
projectSessionWithHostMetadata,
|
|
89
|
+
projectSessionWithStoredMap,
|
|
90
|
+
} from './lib/session-metadata/session-projection.js';
|
|
72
91
|
import { createScheduledTasksRuntime } from './lib/scheduled-tasks/runtime.js';
|
|
73
92
|
import { createScheduledTaskRunHistoryStore } from './lib/scheduled-tasks/run-history-store.js';
|
|
74
93
|
import { createServerStartupRuntime } from './lib/opencode/server-startup-runtime.js';
|
|
@@ -88,6 +107,7 @@ import { createNotificationTemplateRuntime } from './lib/notifications/template-
|
|
|
88
107
|
import { createPermissionAutoAcceptRuntime } from './lib/permission-auto-accept/runtime.js';
|
|
89
108
|
import { createQuestionAutoDelegateRuntime } from './lib/question-auto-delegate/runtime.js';
|
|
90
109
|
import { createGracefulShutdownRuntime } from './lib/opencode/shutdown-runtime.js';
|
|
110
|
+
import { attachHttpServerConnectionTracker } from './lib/opencode/http-server-connections.js';
|
|
91
111
|
import { createProjectConfigRuntime } from './lib/projects/project-config.js';
|
|
92
112
|
import { createRemoteClientAuthRuntime } from './lib/client-auth/remote-clients.js';
|
|
93
113
|
import { applyRuntimeCorsHeaders } from './lib/request-cors.js';
|
|
@@ -445,6 +465,12 @@ let openCodeApiDetectionTimer = null;
|
|
|
445
465
|
let lastOpenCodeError = null;
|
|
446
466
|
let lastOpenCodeLaunchDiagnostics = null;
|
|
447
467
|
let isOpenCodeReady = false;
|
|
468
|
+
let v1Migration = null;
|
|
469
|
+
let openCodeServeVersion = null;
|
|
470
|
+
let openCodeCliVersion = null;
|
|
471
|
+
let runtimeContract = null;
|
|
472
|
+
/** Bumps on start/restart so stale async health cannot re-permit an old instance. */
|
|
473
|
+
let runtimeContractGeneration = 0;
|
|
448
474
|
let openCodeNotReadySince = 0;
|
|
449
475
|
let isExternalOpenCode = false;
|
|
450
476
|
let exitOnShutdown = true;
|
|
@@ -549,6 +575,7 @@ const openCodeAuthStateRuntime = createOpenCodeAuthStateRuntime({
|
|
|
549
575
|
const getOpenCodeAuthHeaders = (...args) => openCodeAuthStateRuntime.getOpenCodeAuthHeaders(...args);
|
|
550
576
|
const isOpenCodeConnectionSecure = (...args) => openCodeAuthStateRuntime.isOpenCodeConnectionSecure(...args);
|
|
551
577
|
const ensureLocalOpenCodeServerPassword = (...args) => openCodeAuthStateRuntime.ensureLocalOpenCodeServerPassword(...args);
|
|
578
|
+
const adoptOpenCodeServerPassword = (...args) => openCodeAuthStateRuntime.adoptOpenCodeServerPassword(...args);
|
|
552
579
|
|
|
553
580
|
const openCodeNetworkState = {};
|
|
554
581
|
Object.defineProperties(openCodeNetworkState, {
|
|
@@ -572,6 +599,15 @@ const buildOpenCodeUrl = (...args) => openCodeNetworkRuntime.buildOpenCodeUrl(..
|
|
|
572
599
|
const ensureOpenCodeApiPrefix = (...args) => openCodeNetworkRuntime.ensureOpenCodeApiPrefix(...args);
|
|
573
600
|
const scheduleOpenCodeApiDetection = (...args) => openCodeNetworkRuntime.scheduleOpenCodeApiDetection(...args);
|
|
574
601
|
|
|
602
|
+
// Host OpenCode transport gate (queue/goal/scheduled/assistants + v2-client).
|
|
603
|
+
// Registered before background runtimes so direct OpenCode writes share proxy admission.
|
|
604
|
+
configureServerOpenCodeFetchGate(() => runtimeContract);
|
|
605
|
+
const serverOpenCodeFetch = createServerOpenCodeFetch({
|
|
606
|
+
buildOpenCodeUrl,
|
|
607
|
+
getOpenCodeAuthHeaders,
|
|
608
|
+
getRuntimeContract: () => runtimeContract,
|
|
609
|
+
});
|
|
610
|
+
|
|
575
611
|
const ENV_CONFIGURED_API_PREFIX = normalizeApiPrefix(
|
|
576
612
|
process.env.OPENCODE_API_PREFIX || process.env.OPENCHAMBER_API_PREFIX || ''
|
|
577
613
|
);
|
|
@@ -614,6 +650,7 @@ const openCodeEnvRuntime = createOpenCodeEnvRuntime({
|
|
|
614
650
|
const applyLoginShellEnvSnapshot = (...args) => openCodeEnvRuntime.applyLoginShellEnvSnapshot(...args);
|
|
615
651
|
const getLoginShellEnvSnapshot = (...args) => openCodeEnvRuntime.getLoginShellEnvSnapshot(...args);
|
|
616
652
|
const ensureOpencodeCliEnv = (...args) => openCodeEnvRuntime.ensureOpencodeCliEnv(...args);
|
|
653
|
+
const ensurePinnedOpenCode2CliEnv = (...args) => openCodeEnvRuntime.ensurePinnedOpenCode2CliEnv(...args);
|
|
617
654
|
const applyOpencodeBinaryFromSettings = (...args) => openCodeEnvRuntime.applyOpencodeBinaryFromSettings(...args);
|
|
618
655
|
const resolveOpencodeCliPath = (...args) => openCodeEnvRuntime.resolveOpencodeCliPath(...args);
|
|
619
656
|
const isExecutable = (...args) => openCodeEnvRuntime.isExecutable(...args);
|
|
@@ -621,6 +658,7 @@ const searchPathFor = (...args) => openCodeEnvRuntime.searchPathFor(...args);
|
|
|
621
658
|
const resolveGitBinaryForSpawn = (...args) => openCodeEnvRuntime.resolveGitBinaryForSpawn(...args);
|
|
622
659
|
const resolveManagedOpenCodeLaunchSpec = (...args) => openCodeEnvRuntime.resolveManagedOpenCodeLaunchSpec(...args);
|
|
623
660
|
const clearResolvedOpenCodeBinary = (...args) => openCodeEnvRuntime.clearResolvedOpenCodeBinary(...args);
|
|
661
|
+
const forceResolvedOpenCodeBinary = (...args) => openCodeEnvRuntime.forceResolvedOpenCodeBinary(...args);
|
|
624
662
|
const openCodeResolutionRuntime = createOpenCodeResolutionRuntime({
|
|
625
663
|
path,
|
|
626
664
|
resolveOpencodeCliPath,
|
|
@@ -696,6 +734,8 @@ const getSmallModelService = async () => {
|
|
|
696
734
|
smallModelServiceInstance = createSmallModelService({
|
|
697
735
|
buildOpenCodeUrl,
|
|
698
736
|
getOpenCodeAuthHeaders,
|
|
737
|
+
persistSessionMetadata: persistSessionMetadataToStore,
|
|
738
|
+
onSystemSessionPersisted: hideSystemSessionFromIndex,
|
|
699
739
|
});
|
|
700
740
|
}
|
|
701
741
|
return smallModelServiceInstance;
|
|
@@ -705,6 +745,19 @@ const sessionTitleRuntime = createSessionTitleRuntime({
|
|
|
705
745
|
buildOpenCodeUrl,
|
|
706
746
|
getOpenCodeAuthHeaders,
|
|
707
747
|
getSmallModelService,
|
|
748
|
+
serverOpenCodeFetch,
|
|
749
|
+
sessionAccess: createTitleSessionAccess({
|
|
750
|
+
buildOpenCodeUrl,
|
|
751
|
+
getOpenCodeAuthHeaders,
|
|
752
|
+
readSessionMetadata: (sessionID) => sessionMetadataStore.get(sessionID),
|
|
753
|
+
persistSessionMetadata: (sessionID, patch) => persistSessionMetadataToStore(sessionID, patch),
|
|
754
|
+
publishSession: (session, directory) => {
|
|
755
|
+
const payload = { type: 'session.updated', properties: { info: session, directory } };
|
|
756
|
+
broadcastGlobalUiEvent(payload);
|
|
757
|
+
const changed = sessionIndexServiceRef?.upsertAndReportChange(session);
|
|
758
|
+
if (changed) sessionIndexSyncRuntimeRef?.publishChange();
|
|
759
|
+
},
|
|
760
|
+
}),
|
|
708
761
|
});
|
|
709
762
|
|
|
710
763
|
// Forward declaration: question auto-delegate is created after the event hub;
|
|
@@ -713,9 +766,116 @@ let questionAutoDelegateRuntime = null;
|
|
|
713
766
|
/** Filled inside main() once the SQLite session index is constructed. */
|
|
714
767
|
let sessionIndexServiceRef = null;
|
|
715
768
|
|
|
769
|
+
const sessionMetadataStore = createSessionMetadataStore({ dataDir: OPENCHAMBER_DATA_DIR });
|
|
770
|
+
/**
|
|
771
|
+
* load() resolves `{ ok:false }` on read/corrupt failure (does not reject).
|
|
772
|
+
* Callers must check ok / isLoaded — never treat unresolved as empty success.
|
|
773
|
+
*/
|
|
774
|
+
const ensureSessionMetadataReady = async () => {
|
|
775
|
+
try {
|
|
776
|
+
const result = await sessionMetadataStore.load();
|
|
777
|
+
return result?.ok === true && sessionMetadataStore.isLoaded();
|
|
778
|
+
} catch (error) {
|
|
779
|
+
console.warn('[session-metadata] load threw:', error?.message ?? error);
|
|
780
|
+
return false;
|
|
781
|
+
}
|
|
782
|
+
};
|
|
783
|
+
// Prime without blocking module init; production gates (hub/SSE/routes) await ready.
|
|
784
|
+
void ensureSessionMetadataReady().then((ok) => {
|
|
785
|
+
if (!ok) {
|
|
786
|
+
console.warn(
|
|
787
|
+
'[session-metadata] initial load not ready:',
|
|
788
|
+
sessionMetadataStore.getLoadFailureReason?.() || 'unknown',
|
|
789
|
+
);
|
|
790
|
+
}
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
/**
|
|
794
|
+
* Goal write through the Host metadata store.
|
|
795
|
+
* Advances executionGeneration on pause/resume/condition changes so late audits
|
|
796
|
+
* cannot commit against a prior execution permit. Broadcasts only after commit.
|
|
797
|
+
*/
|
|
798
|
+
const persistSessionGoalToStore = async (sessionId, _directory, goal) => {
|
|
799
|
+
const result = await sessionMetadataStore.mutateSessionMetadata(sessionId, (current) => {
|
|
800
|
+
const previousGoal = current?.openchamber?.goal && typeof current.openchamber.goal === 'object'
|
|
801
|
+
? current.openchamber.goal
|
|
802
|
+
: null;
|
|
803
|
+
const nextGoal = withGoalExecutionGeneration(previousGoal, goal);
|
|
804
|
+
return { ok: true, patch: { openchamber: { goal: nextGoal } } };
|
|
805
|
+
});
|
|
806
|
+
if (!result?.committed) {
|
|
807
|
+
throw new Error(result?.reason || 'session goal persist was rejected');
|
|
808
|
+
}
|
|
809
|
+
const metadata = result.metadata;
|
|
810
|
+
try {
|
|
811
|
+
broadcastGlobalUiEvent({
|
|
812
|
+
type: 'openchamber:session-metadata',
|
|
813
|
+
properties: { sessionID: sessionId, metadata },
|
|
814
|
+
});
|
|
815
|
+
} catch (error) {
|
|
816
|
+
console.warn('[session-metadata] broadcast failed:', error?.message ?? error);
|
|
817
|
+
}
|
|
818
|
+
return metadata;
|
|
819
|
+
};
|
|
820
|
+
|
|
821
|
+
/**
|
|
822
|
+
* Isolation / Host metadata write. Same store + broadcast seam as goal persist.
|
|
823
|
+
* Callers pass an RFC 7386 merge patch; the store returns the committed object.
|
|
824
|
+
*/
|
|
825
|
+
const persistSessionMetadataToStore = async (sessionId, patch) => {
|
|
826
|
+
const metadata = await sessionMetadataStore.setSessionMetadata(sessionId, patch);
|
|
827
|
+
try {
|
|
828
|
+
broadcastGlobalUiEvent({
|
|
829
|
+
type: 'openchamber:session-metadata',
|
|
830
|
+
properties: { sessionID: sessionId, metadata },
|
|
831
|
+
});
|
|
832
|
+
} catch (error) {
|
|
833
|
+
console.warn('[session-metadata] broadcast failed:', error?.message ?? error);
|
|
834
|
+
}
|
|
835
|
+
return metadata;
|
|
836
|
+
};
|
|
837
|
+
|
|
838
|
+
/**
|
|
839
|
+
* After Host isolation metadata is committed, drop the session from the
|
|
840
|
+
* sidebar index immediately. Do not wait for the next directory list sync.
|
|
841
|
+
* Reads refs at call time — scheduled-task runtime is constructed before main().
|
|
842
|
+
*/
|
|
843
|
+
const hideSystemSessionFromIndex = ({ sessionID, directory, metadata } = {}) => {
|
|
844
|
+
if (!sessionIndexServiceRef || typeof sessionID !== 'string' || !sessionID) return;
|
|
845
|
+
const changed = sessionIndexServiceRef.upsertAndReportChange({
|
|
846
|
+
id: sessionID,
|
|
847
|
+
directory: directory || '',
|
|
848
|
+
metadata,
|
|
849
|
+
});
|
|
850
|
+
if (changed) {
|
|
851
|
+
sessionIndexSyncRuntimeRef?.publishChange();
|
|
852
|
+
}
|
|
853
|
+
};
|
|
854
|
+
|
|
855
|
+
/** Filled in main() once the session index + broadcast sinks exist. */
|
|
856
|
+
let sessionArchiveServiceRef = null;
|
|
857
|
+
let sessionIndexSyncRuntimeRef = null;
|
|
858
|
+
|
|
859
|
+
const readHostMetadataForSession = (sessionID) => {
|
|
860
|
+
const snap = sessionMetadataStore.getSnapshotSync();
|
|
861
|
+
if (!snap || typeof sessionID !== 'string') return null;
|
|
862
|
+
const host = snap[sessionID];
|
|
863
|
+
return host && typeof host === 'object' && !Array.isArray(host) ? host : null;
|
|
864
|
+
};
|
|
865
|
+
|
|
866
|
+
const projectHostSessionPayload = (payload) => {
|
|
867
|
+
const ready = sessionMetadataStore.isLoaded();
|
|
868
|
+
return projectSessionLifecyclePayload(
|
|
869
|
+
payload,
|
|
870
|
+
readHostMetadataForSession,
|
|
871
|
+
{ hostReady: ready },
|
|
872
|
+
);
|
|
873
|
+
};
|
|
874
|
+
|
|
716
875
|
const sessionGoalRuntime = createSessionGoalRuntime({
|
|
717
876
|
buildOpenCodeUrl,
|
|
718
877
|
getOpenCodeAuthHeaders,
|
|
878
|
+
serverOpenCodeFetch,
|
|
719
879
|
getSmallModelService,
|
|
720
880
|
shouldKeepGoalActiveForQuestion: (sessionId) => (
|
|
721
881
|
questionAutoDelegateRuntime?.isAutoHandling(sessionId) === true
|
|
@@ -726,6 +886,28 @@ const sessionGoalRuntime = createSessionGoalRuntime({
|
|
|
726
886
|
onGoalPaused: (sessionId, directory) => (
|
|
727
887
|
questionAutoDelegateRuntime?.pauseForSessionTree?.(sessionId, directory)
|
|
728
888
|
),
|
|
889
|
+
readSessionMetadata: (sessionId) => sessionMetadataStore.get(sessionId),
|
|
890
|
+
// Conditional commit on the store's exclusive serial boundary (generation +
|
|
891
|
+
// status preconditions share the lock with persist). Broadcast-only on
|
|
892
|
+
// success — do not feed progress writes back into processPayload.
|
|
893
|
+
mutateSessionMetadata: async (sessionId, decide) => {
|
|
894
|
+
const result = await sessionMetadataStore.mutateSessionMetadata(sessionId, decide);
|
|
895
|
+
if (result?.committed) {
|
|
896
|
+
try {
|
|
897
|
+
broadcastGlobalUiEvent({
|
|
898
|
+
type: 'openchamber:session-metadata',
|
|
899
|
+
properties: { sessionID: sessionId, metadata: result.metadata },
|
|
900
|
+
});
|
|
901
|
+
} catch (error) {
|
|
902
|
+
console.warn('[session-metadata] broadcast failed:', error?.message ?? error);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
return result;
|
|
906
|
+
},
|
|
907
|
+
persistSessionGoal: async (sessionId, directory, goal) => {
|
|
908
|
+
const metadata = await persistSessionGoalToStore(sessionId, directory, goal);
|
|
909
|
+
return metadata?.openchamber?.goal ?? goal;
|
|
910
|
+
},
|
|
729
911
|
emitGoalNotification: async ({ sessionId, directory, status, goal }) => {
|
|
730
912
|
// The goal settle notification replaces the per-turn ready notifications
|
|
731
913
|
// (suppressed while the goal is active) — so it obeys the same toggle.
|
|
@@ -766,6 +948,7 @@ const globalMessageStreamHub = createGlobalMessageStreamHub({
|
|
|
766
948
|
buildOpenCodeUrl,
|
|
767
949
|
getOpenCodeAuthHeaders,
|
|
768
950
|
upstreamStallTimeoutMs: getUpstreamStallTimeoutMs,
|
|
951
|
+
projectOutboundSessionPayload: projectHostSessionPayload,
|
|
769
952
|
});
|
|
770
953
|
|
|
771
954
|
const permissionAutoAcceptRuntime = createPermissionAutoAcceptRuntime({
|
|
@@ -908,6 +1091,9 @@ const serverUtilsRuntime = createServerUtilsRuntime({
|
|
|
908
1091
|
openCodeNotReadySince,
|
|
909
1092
|
isOpenCodeReady,
|
|
910
1093
|
isRestartingOpenCode,
|
|
1094
|
+
v1Migration,
|
|
1095
|
+
runtimeContract,
|
|
1096
|
+
openCodeServeVersion,
|
|
911
1097
|
}),
|
|
912
1098
|
getOpenCodeAuthHeaders,
|
|
913
1099
|
buildOpenCodeUrl,
|
|
@@ -934,6 +1120,13 @@ const serverUtilsRuntime = createServerUtilsRuntime({
|
|
|
934
1120
|
}
|
|
935
1121
|
return snapshot.PATH;
|
|
936
1122
|
},
|
|
1123
|
+
getStoredSessionMetadata: () => sessionMetadataStore.getAll(),
|
|
1124
|
+
getStoredSessionMetadataSync: () => sessionMetadataStore.getSnapshotSync(),
|
|
1125
|
+
ensureSessionMetadataReady,
|
|
1126
|
+
onSessionDeleted: (sessionID) => {
|
|
1127
|
+
if (!sessionArchiveServiceRef) return sessionMetadataStore.removeSession(sessionID);
|
|
1128
|
+
return sessionArchiveServiceRef.forgetSession(sessionID);
|
|
1129
|
+
},
|
|
937
1130
|
});
|
|
938
1131
|
|
|
939
1132
|
const setOpenCodePort = (...args) => serverUtilsRuntime.setOpenCodePort(...args);
|
|
@@ -1003,6 +1196,14 @@ Object.defineProperties(openCodeLifecycleState, {
|
|
|
1003
1196
|
lastOpenCodeError: { get: () => lastOpenCodeError, set: (value) => { lastOpenCodeError = value; } },
|
|
1004
1197
|
lastOpenCodeLaunchDiagnostics: { get: () => lastOpenCodeLaunchDiagnostics, set: (value) => { lastOpenCodeLaunchDiagnostics = value; } },
|
|
1005
1198
|
isOpenCodeReady: { get: () => isOpenCodeReady, set: (value) => { isOpenCodeReady = value; } },
|
|
1199
|
+
v1Migration: { get: () => v1Migration, set: (value) => { v1Migration = value; } },
|
|
1200
|
+
openCodeServeVersion: { get: () => openCodeServeVersion, set: (value) => { openCodeServeVersion = value; } },
|
|
1201
|
+
openCodeCliVersion: { get: () => openCodeCliVersion, set: (value) => { openCodeCliVersion = value; } },
|
|
1202
|
+
runtimeContract: { get: () => runtimeContract, set: (value) => { runtimeContract = value; } },
|
|
1203
|
+
runtimeContractGeneration: {
|
|
1204
|
+
get: () => runtimeContractGeneration,
|
|
1205
|
+
set: (value) => { runtimeContractGeneration = value; },
|
|
1206
|
+
},
|
|
1006
1207
|
openCodeNotReadySince: { get: () => openCodeNotReadySince, set: (value) => { openCodeNotReadySince = value; } },
|
|
1007
1208
|
isExternalOpenCode: { get: () => isExternalOpenCode, set: (value) => { isExternalOpenCode = value; } },
|
|
1008
1209
|
isShuttingDown: { get: () => isShuttingDown, set: (value) => { isShuttingDown = value; } },
|
|
@@ -1047,7 +1248,10 @@ const openCodeLifecycleRuntime = createOpenCodeLifecycleRuntime({
|
|
|
1047
1248
|
normalizeApiPrefix,
|
|
1048
1249
|
applyOpencodeBinaryFromSettings,
|
|
1049
1250
|
ensureOpencodeCliEnv,
|
|
1251
|
+
ensurePinnedOpenCode2CliEnv,
|
|
1050
1252
|
ensureLocalOpenCodeServerPassword,
|
|
1253
|
+
adoptOpenCodeServerPassword,
|
|
1254
|
+
sharedService: isSharedServiceEnabled() ? createSharedOpenCodeService() : null,
|
|
1051
1255
|
resolveManagedOpenCodeLaunchSpec,
|
|
1052
1256
|
setOpenCodePort,
|
|
1053
1257
|
setDetectedOpenCodeApiPrefix,
|
|
@@ -1059,6 +1263,26 @@ const openCodeLifecycleRuntime = createOpenCodeLifecycleRuntime({
|
|
|
1059
1263
|
getManagedOpenCodeShellEnvSnapshot: getLoginShellEnvSnapshot,
|
|
1060
1264
|
managedCapabilitiesRuntime,
|
|
1061
1265
|
getActiveSessionCount,
|
|
1266
|
+
// Most-recently-used directories first: OpenCode initializes each directory
|
|
1267
|
+
// lazily on first request (seconds on large session stores), so the
|
|
1268
|
+
// lifecycle warms these right after readiness — before the UI's first
|
|
1269
|
+
// interactive request would otherwise pay that cost.
|
|
1270
|
+
getWarmupDirectories: async () => {
|
|
1271
|
+
const settings = await readSettingsFromDiskMigrated().catch(() => null);
|
|
1272
|
+
if (!settings) return [];
|
|
1273
|
+
const directories = [];
|
|
1274
|
+
if (typeof settings.lastDirectory === 'string' && settings.lastDirectory) {
|
|
1275
|
+
directories.push(settings.lastDirectory);
|
|
1276
|
+
}
|
|
1277
|
+
const projects = Array.isArray(settings.projects) ? [...settings.projects] : [];
|
|
1278
|
+
projects.sort((a, b) => (b?.lastOpenedAt ?? 0) - (a?.lastOpenedAt ?? 0));
|
|
1279
|
+
for (const project of projects) {
|
|
1280
|
+
if (typeof project?.path === 'string' && project.path) {
|
|
1281
|
+
directories.push(project.path);
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
return [...new Set(directories)];
|
|
1285
|
+
},
|
|
1062
1286
|
});
|
|
1063
1287
|
|
|
1064
1288
|
const restartOpenCode = (...args) => openCodeLifecycleRuntime.restartOpenCode(...args);
|
|
@@ -1081,6 +1305,25 @@ const scheduledTasksRuntime = createScheduledTasksRuntime({
|
|
|
1081
1305
|
getSmallModelService,
|
|
1082
1306
|
waitForOpenCodeReady,
|
|
1083
1307
|
runHistoryStore: scheduledTaskRunHistoryStore,
|
|
1308
|
+
// Same Host store seam as session-goal / manual UI metadata writes.
|
|
1309
|
+
readSessionMetadata: (sessionId) => sessionMetadataStore.get(sessionId),
|
|
1310
|
+
persistSessionMetadata: persistSessionMetadataToStore,
|
|
1311
|
+
onSystemSessionPersisted: hideSystemSessionFromIndex,
|
|
1312
|
+
persistSessionGoal: persistSessionGoalToStore,
|
|
1313
|
+
// Arm the goal loop after first persist only — do not feed progress writes
|
|
1314
|
+
// back through processPayload (session-goal runtime already broadcasts those).
|
|
1315
|
+
onGoalPersisted: ({ sessionID, directory, metadata }) => {
|
|
1316
|
+
sessionGoalRuntime.processPayload({
|
|
1317
|
+
type: 'session.updated',
|
|
1318
|
+
properties: {
|
|
1319
|
+
info: {
|
|
1320
|
+
id: sessionID,
|
|
1321
|
+
directory: directory || '',
|
|
1322
|
+
metadata,
|
|
1323
|
+
},
|
|
1324
|
+
},
|
|
1325
|
+
}, directory || '');
|
|
1326
|
+
},
|
|
1084
1327
|
emitTaskRunEvent: (event) => {
|
|
1085
1328
|
for (const client of uiOpenChamberEventClients) {
|
|
1086
1329
|
try {
|
|
@@ -1108,7 +1351,19 @@ const ensureGlobalWatcherStarted = async () => {
|
|
|
1108
1351
|
return globalWatcherStartPromise;
|
|
1109
1352
|
}
|
|
1110
1353
|
|
|
1111
|
-
|
|
1354
|
+
// Await Host metadata ready before the internal hub attaches upstream SSE so
|
|
1355
|
+
// session lifecycle frames are projected (not dropped) from the first event.
|
|
1356
|
+
globalWatcherStartPromise = (async () => {
|
|
1357
|
+
const ready = await ensureSessionMetadataReady();
|
|
1358
|
+
if (!ready) {
|
|
1359
|
+
const reason = sessionMetadataStore.getLoadFailureReason?.() || 'not ready';
|
|
1360
|
+
const error = new Error(`session metadata unavailable before global watcher start: ${reason}`);
|
|
1361
|
+
error.code = 'session_metadata_unavailable';
|
|
1362
|
+
error.retryable = true;
|
|
1363
|
+
throw error;
|
|
1364
|
+
}
|
|
1365
|
+
return openCodeWatcherRuntime.start();
|
|
1366
|
+
})().catch((error) => {
|
|
1112
1367
|
globalWatcherStartPromise = null;
|
|
1113
1368
|
throw error;
|
|
1114
1369
|
});
|
|
@@ -1118,15 +1373,30 @@ const ensureGlobalWatcherStarted = async () => {
|
|
|
1118
1373
|
|
|
1119
1374
|
const completeOpenCodeStartup = () => {
|
|
1120
1375
|
scheduleOpenCodeApiDetection();
|
|
1121
|
-
if (
|
|
1376
|
+
if (
|
|
1377
|
+
(openCodeLifecycleState.openCodeProcess && !openCodeLifecycleState.isExternalOpenCode)
|
|
1378
|
+
|| openCodeLifecycleRuntime.isSharedOpenCodeService()
|
|
1379
|
+
) {
|
|
1122
1380
|
startHealthMonitoring();
|
|
1123
1381
|
}
|
|
1124
1382
|
// The global watcher used to start only for desktop notifications; session-title
|
|
1125
1383
|
// and session-goal also ride its event hub, so it now starts unconditionally
|
|
1126
|
-
// once OpenCode is up.
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1384
|
+
// once OpenCode is up. Controlled retry when metadata is not yet ready.
|
|
1385
|
+
const startWatcherWithRetry = (attempt = 0) => {
|
|
1386
|
+
void ensureGlobalWatcherStarted().catch((error) => {
|
|
1387
|
+
const retryable = error?.retryable === true || error?.code === 'session_metadata_unavailable';
|
|
1388
|
+
const delays = [500, 1_500, 3_000, 6_000, 12_000];
|
|
1389
|
+
if (retryable && attempt < delays.length) {
|
|
1390
|
+
console.warn(
|
|
1391
|
+
`Global event watcher deferred (metadata): ${error?.message || error}; retry ${attempt + 1}/${delays.length}`,
|
|
1392
|
+
);
|
|
1393
|
+
setTimeout(() => startWatcherWithRetry(attempt + 1), delays[attempt]);
|
|
1394
|
+
return;
|
|
1395
|
+
}
|
|
1396
|
+
console.warn(`Global event watcher startup failed: ${error?.message || error}`);
|
|
1397
|
+
});
|
|
1398
|
+
};
|
|
1399
|
+
startWatcherWithRetry();
|
|
1130
1400
|
};
|
|
1131
1401
|
|
|
1132
1402
|
const bootstrapOpenCodeAtStartup = async (...args) => {
|
|
@@ -1138,7 +1408,6 @@ const retryOpenCodeStartup = async (...args) => {
|
|
|
1138
1408
|
await openCodeLifecycleRuntime.retryOpenCodeStartup(...args);
|
|
1139
1409
|
completeOpenCodeStartup();
|
|
1140
1410
|
};
|
|
1141
|
-
const killProcessOnPort = (...args) => openCodeLifecycleRuntime.killProcessOnPort(...args);
|
|
1142
1411
|
const waitForPortRelease = (...args) => openCodeLifecycleRuntime.waitForPortRelease(...args);
|
|
1143
1412
|
|
|
1144
1413
|
const fetchAgentsSnapshot = (...args) => serverUtilsRuntime.fetchAgentsSnapshot(...args);
|
|
@@ -1175,7 +1444,6 @@ const gracefulShutdownRuntime = createGracefulShutdownRuntime({
|
|
|
1175
1444
|
setOpenCodeProcess: (value) => {
|
|
1176
1445
|
openCodeProcess = value;
|
|
1177
1446
|
},
|
|
1178
|
-
killProcessOnPort,
|
|
1179
1447
|
waitForPortRelease,
|
|
1180
1448
|
getServer: () => server,
|
|
1181
1449
|
getUiAuthController: () => uiAuthController,
|
|
@@ -1350,6 +1618,14 @@ async function main(options = {}) {
|
|
|
1350
1618
|
buildOpenCodeUrl,
|
|
1351
1619
|
getOpenCodeAuthHeaders,
|
|
1352
1620
|
waitForOpenCodeReady,
|
|
1621
|
+
projectSessions: (sessions) => {
|
|
1622
|
+
const snap = sessionMetadataStore.getSnapshotSync();
|
|
1623
|
+
// Not ready / unavailable — throw so sync keeps prior directory rows.
|
|
1624
|
+
if (!snap) {
|
|
1625
|
+
throw new Error('session metadata is unavailable: Host store not ready');
|
|
1626
|
+
}
|
|
1627
|
+
return sessions.map((session) => projectSessionWithStoredMap(session, snap));
|
|
1628
|
+
},
|
|
1353
1629
|
onRevisionTip: (tip) => {
|
|
1354
1630
|
broadcastOpenChamberEvent({
|
|
1355
1631
|
type: 'openchamber:session-index-changed',
|
|
@@ -1357,8 +1633,44 @@ async function main(options = {}) {
|
|
|
1357
1633
|
});
|
|
1358
1634
|
},
|
|
1359
1635
|
});
|
|
1636
|
+
sessionIndexSyncRuntimeRef = sessionIndexSyncRuntime;
|
|
1637
|
+
|
|
1638
|
+
sessionArchiveServiceRef = createSessionArchiveService({
|
|
1639
|
+
sessionMetadataStore,
|
|
1640
|
+
fetchUpstreamSession: createUpstreamSessionFetcher({
|
|
1641
|
+
buildOpenCodeUrl,
|
|
1642
|
+
getOpenCodeAuthHeaders,
|
|
1643
|
+
}),
|
|
1644
|
+
sessionIndexService,
|
|
1645
|
+
broadcastSessionEvent: (payload, options = {}) => {
|
|
1646
|
+
try {
|
|
1647
|
+
broadcastGlobalUiEvent(payload, options);
|
|
1648
|
+
} catch (error) {
|
|
1649
|
+
console.warn('[session-archive] global UI broadcast failed:', error?.message ?? error);
|
|
1650
|
+
}
|
|
1651
|
+
try {
|
|
1652
|
+
broadcastOpenChamberEvent(payload);
|
|
1653
|
+
} catch (error) {
|
|
1654
|
+
console.warn('[session-archive] openchamber event broadcast failed:', error?.message ?? error);
|
|
1655
|
+
}
|
|
1656
|
+
},
|
|
1657
|
+
onIndexChanged: () => {
|
|
1658
|
+
sessionIndexSyncRuntimeRef?.publishChange();
|
|
1659
|
+
},
|
|
1660
|
+
});
|
|
1661
|
+
|
|
1360
1662
|
const unsubscribeSessionIndexEvents = globalMessageStreamHub.subscribeEvent((event) => {
|
|
1361
|
-
if (applySessionIndexEvent(sessionIndexService, event)
|
|
1663
|
+
if (applySessionIndexEvent(sessionIndexService, event, Date.now(), {
|
|
1664
|
+
isHostReady: () => sessionMetadataStore.isLoaded(),
|
|
1665
|
+
projectSession: (session) => {
|
|
1666
|
+
if (!sessionMetadataStore.isLoaded()) return null;
|
|
1667
|
+
return projectSessionWithHostMetadata(
|
|
1668
|
+
session,
|
|
1669
|
+
readHostMetadataForSession(session?.id),
|
|
1670
|
+
);
|
|
1671
|
+
},
|
|
1672
|
+
onSessionDeleted: (sessionID) => sessionArchiveServiceRef?.forgetSession(sessionID),
|
|
1673
|
+
})) {
|
|
1362
1674
|
sessionIndexSyncRuntime?.publishChange();
|
|
1363
1675
|
}
|
|
1364
1676
|
});
|
|
@@ -1424,6 +1736,9 @@ async function main(options = {}) {
|
|
|
1424
1736
|
}));
|
|
1425
1737
|
expressApp = app;
|
|
1426
1738
|
server = http.createServer(app);
|
|
1739
|
+
// Track server-owned sockets so forceCloseConnections can destroy upgraded
|
|
1740
|
+
// WS/SSE leftovers that closeAllConnections does not release.
|
|
1741
|
+
attachHttpServerConnectionTracker(server);
|
|
1427
1742
|
let realtimeProxyRuntime = { stop: () => {} };
|
|
1428
1743
|
|
|
1429
1744
|
// The relay service is constructed further below (it depends on the active
|
|
@@ -1444,11 +1759,16 @@ async function main(options = {}) {
|
|
|
1444
1759
|
return {
|
|
1445
1760
|
openCodePort,
|
|
1446
1761
|
openCodeRunning: Boolean(openCodePort && isOpenCodeReady && !isRestartingOpenCode),
|
|
1762
|
+
openCodeStarting: Boolean(!isOpenCodeReady && !lastOpenCodeError),
|
|
1447
1763
|
openCodeSecureConnection: isOpenCodeConnectionSecure(),
|
|
1448
1764
|
openCodeAuthSource: openCodeAuthSource || null,
|
|
1449
1765
|
openCodeApiPrefix: '',
|
|
1450
1766
|
openCodeApiPrefixDetected: true,
|
|
1451
1767
|
isOpenCodeReady,
|
|
1768
|
+
v1Migration,
|
|
1769
|
+
openCodeServeVersion,
|
|
1770
|
+
openCodeCliVersion,
|
|
1771
|
+
runtimeContract,
|
|
1452
1772
|
lastOpenCodeError,
|
|
1453
1773
|
lastOpenCodeLaunchDiagnostics,
|
|
1454
1774
|
opencodeBinaryResolved: resolvedOpencodeBinary || null,
|
|
@@ -1559,6 +1879,8 @@ async function main(options = {}) {
|
|
|
1559
1879
|
setAutoAcceptSession,
|
|
1560
1880
|
sessionIndexService,
|
|
1561
1881
|
sessionIndexSyncRuntime,
|
|
1882
|
+
// Production snapshot/lookup filter: committed Host archive authority.
|
|
1883
|
+
getCommittedHostMetadata: async () => sessionMetadataStore.getAll(),
|
|
1562
1884
|
transcriptCacheService,
|
|
1563
1885
|
});
|
|
1564
1886
|
uiAuthController = bootstrapResult.uiAuthController;
|
|
@@ -1653,6 +1975,57 @@ async function main(options = {}) {
|
|
|
1653
1975
|
isUnsafeSkillRelativePath,
|
|
1654
1976
|
buildOpenCodeUrl,
|
|
1655
1977
|
getOpenCodeAuthHeaders,
|
|
1978
|
+
getIsExternalOpenCode: () => isExternalOpenCode,
|
|
1979
|
+
getIsSharedOpenCodeService: () => openCodeLifecycleRuntime.isSharedOpenCodeService(),
|
|
1980
|
+
forceResolvedOpenCodeBinary,
|
|
1981
|
+
restartOpenCode,
|
|
1982
|
+
waitForOpenCodeReady,
|
|
1983
|
+
getRuntimeContract: () => runtimeContract,
|
|
1984
|
+
getOpenCodeServeVersion: () => openCodeServeVersion,
|
|
1985
|
+
getOpenCodeCliVersion: () => openCodeCliVersion,
|
|
1986
|
+
getResolvedOpenCodeBinary: () => resolvedOpencodeBinary,
|
|
1987
|
+
getResolvedOpenCodeBinarySource: () => resolvedOpencodeBinarySource,
|
|
1988
|
+
getActiveSessionCount,
|
|
1989
|
+
sessionMetadataStore,
|
|
1990
|
+
sessionArchiveService: {
|
|
1991
|
+
setArchive: (...args) => {
|
|
1992
|
+
if (!sessionArchiveServiceRef) {
|
|
1993
|
+
const error = new Error('session archive is not configured');
|
|
1994
|
+
error.status = 503;
|
|
1995
|
+
throw error;
|
|
1996
|
+
}
|
|
1997
|
+
return sessionArchiveServiceRef.setArchive(...args);
|
|
1998
|
+
},
|
|
1999
|
+
archiveSession: (...args) => {
|
|
2000
|
+
if (!sessionArchiveServiceRef) {
|
|
2001
|
+
const error = new Error('session archive is not configured');
|
|
2002
|
+
error.status = 503;
|
|
2003
|
+
throw error;
|
|
2004
|
+
}
|
|
2005
|
+
return sessionArchiveServiceRef.archiveSession(...args);
|
|
2006
|
+
},
|
|
2007
|
+
},
|
|
2008
|
+
// Same store seam as sessionGoalRuntime / scheduledTasksRuntime.
|
|
2009
|
+
readSessionMetadata: (sessionId) => sessionMetadataStore.get(sessionId),
|
|
2010
|
+
persistSessionMetadata: persistSessionMetadataToStore,
|
|
2011
|
+
onSystemSessionPersisted: hideSystemSessionFromIndex,
|
|
2012
|
+
persistSessionGoal: persistSessionGoalToStore,
|
|
2013
|
+
onSessionMetadataWritten: ({ sessionID, directory, metadata }) => {
|
|
2014
|
+
sessionTitleRuntime.processPayload({
|
|
2015
|
+
type: 'openchamber:session-metadata',
|
|
2016
|
+
properties: { sessionID, directory, metadata },
|
|
2017
|
+
}, directory || '');
|
|
2018
|
+
sessionGoalRuntime.processPayload({
|
|
2019
|
+
type: 'session.updated',
|
|
2020
|
+
properties: {
|
|
2021
|
+
info: {
|
|
2022
|
+
id: sessionID,
|
|
2023
|
+
directory: directory || '',
|
|
2024
|
+
metadata,
|
|
2025
|
+
},
|
|
2026
|
+
},
|
|
2027
|
+
}, directory || '');
|
|
2028
|
+
},
|
|
1656
2029
|
getSmallModelService,
|
|
1657
2030
|
getOpenCodePort: () => openCodePort,
|
|
1658
2031
|
buildAugmentedPath,
|
|
@@ -1704,6 +2077,8 @@ async function main(options = {}) {
|
|
|
1704
2077
|
getOpenCodeAuthHeaders,
|
|
1705
2078
|
globalEventHub: globalMessageStreamHub,
|
|
1706
2079
|
processForwardedEventPayload,
|
|
2080
|
+
projectOutboundSessionPayload: projectHostSessionPayload,
|
|
2081
|
+
ensureSessionMetadataReady,
|
|
1707
2082
|
messageStreamWsClients: uiNotificationWsClients,
|
|
1708
2083
|
upstreamStallTimeoutMs: getUpstreamStallTimeoutMs,
|
|
1709
2084
|
terminalHeartbeatIntervalMs: TERMINAL_INPUT_WS_HEARTBEAT_INTERVAL_MS,
|
|
@@ -1773,12 +2148,9 @@ async function main(options = {}) {
|
|
|
1773
2148
|
restartOpenCode: () => restartOpenCode(),
|
|
1774
2149
|
getOpenCodeProcessInfo: () => {
|
|
1775
2150
|
const managed = Boolean((openCodeProcess || openCodePort) && !ENV_SKIP_OPENCODE_START && !isExternalOpenCode);
|
|
1776
|
-
// Only ever expose pid/port for a server WE manage.
|
|
1777
|
-
//
|
|
1778
|
-
//
|
|
1779
|
-
// let a single miscomputed `managed` flag take down the user's separate
|
|
1780
|
-
// server. Structurally withhold what isn't ours so the killer has no
|
|
1781
|
-
// target, instead of relying on the flag check alone.
|
|
2151
|
+
// Only ever expose pid/port for a server WE manage. Desktop no longer runs a
|
|
2152
|
+
// post-stop detached killer of a pre-captured pid; still withhold non-owned
|
|
2153
|
+
// process identity so diagnostics cannot imply we may kill an external serve.
|
|
1782
2154
|
return {
|
|
1783
2155
|
managed,
|
|
1784
2156
|
pid: managed && typeof openCodeProcess?.pid === 'number' ? openCodeProcess.pid : null,
|
|
@@ -1792,6 +2164,7 @@ async function main(options = {}) {
|
|
|
1792
2164
|
unsubscribeScheduledTaskEvents();
|
|
1793
2165
|
sessionIndexSyncRuntime?.stop();
|
|
1794
2166
|
sessionIndexService?.close();
|
|
2167
|
+
sessionArchiveServiceRef?.stop?.();
|
|
1795
2168
|
} catch {
|
|
1796
2169
|
// The index is a local cache; a failed close must not block shutdown.
|
|
1797
2170
|
}
|
|
@@ -1819,11 +2192,10 @@ async function main(options = {}) {
|
|
|
1819
2192
|
// best-effort shutdown of the dictation worker
|
|
1820
2193
|
}
|
|
1821
2194
|
try {
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
}
|
|
2195
|
+
const { stopLlmTempDirectory } = await import('./lib/llm/temp-directory.js');
|
|
2196
|
+
await stopLlmTempDirectory();
|
|
1825
2197
|
} catch {
|
|
1826
|
-
// best-effort cleanup of the
|
|
2198
|
+
// best-effort cleanup of the LLM generator temp OpenCode directory
|
|
1827
2199
|
}
|
|
1828
2200
|
return gracefulShutdown({
|
|
1829
2201
|
exitProcess: shutdownOptions.exitProcess ?? false,
|