@openchambery/web 2.0.0-beta.1 → 2.0.0-beta.10
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 +15 -11
- package/bin/cli-opencode.test.js +4 -4
- package/bin/cli.js +1 -1
- package/bin/lib/cli-startup.js +1 -1
- package/bin/lib/cli-startup.test.js +18 -4
- package/dist/assets/{AgentAvatar-CLWWNu_Q.js → AgentAvatar-CzTtVMnI.js} +1 -1
- package/dist/assets/AssistantView-Cg1qQvVe.js +3 -0
- package/dist/assets/{DiagramView-xuSJTnv7.js → DiagramView-hOi72Wdx.js} +1 -1
- package/dist/assets/{FadeInOnReveal-Ov0D96d0.js → FadeInOnReveal-DCqrQkkz.js} +1 -1
- package/dist/assets/Icon-B8fSTLdP.js +1 -0
- package/dist/assets/MarkdownRenderer-Cw74oVxV.js +2 -0
- package/dist/assets/{MarkdownRendererImpl-SKi4oG0c.js → MarkdownRendererImpl-YM7iRmzK.js} +3 -3
- package/dist/assets/MarkstreamRendererImpl-BDy_oGJQ.js +3 -0
- package/dist/assets/{MobileDetailNavigation-Bnx59U_J.js → MobileDetailNavigation-iX_hb_Xt.js} +1 -1
- package/dist/assets/{MobileShareBridge-BQlP4J-F.js → MobileShareBridge-CAMUupwR.js} +2 -2
- package/dist/assets/MobileSurface-CHbdPcLH.js +2 -0
- package/dist/assets/{MultiRunWindow-ChZGob0v.js → MultiRunWindow-Ci1ODFFX.js} +1 -1
- package/dist/assets/{OnboardingScreen-DtQJxZG-.js → OnboardingScreen-O4cGdz5p.js} +1 -1
- package/dist/assets/OverlayScrollbar-CRfGtcmG.js +2 -0
- package/dist/assets/SettingsView-Dg8BtTV1.js +25 -0
- package/dist/assets/{SettingsWindow-DfnsFa8y.js → SettingsWindow-B8d8qIQ7.js} +1 -1
- package/dist/assets/TerminalView-CMiw3s_c.js +8 -0
- package/dist/assets/{ToolOutputDialog-BejmjrRk.js → ToolOutputDialog-ByaQYRTp.js} +2 -2
- package/dist/assets/appThemeRegistry-BGGHio8T.js +1 -0
- package/dist/assets/{assistant-attachment-cache-C0aRnFkj.js → assistant-attachment-cache-DphJleHr.js} +1 -1
- package/dist/assets/{button-D-rATN7w.js → button-DIIrsMjW.js} +1 -1
- package/dist/assets/{collapsible-BXRd5_Hr.js → collapsible-CnvUeYst.js} +1 -1
- package/dist/assets/{context-menu-jGtH6fR9.js → context-menu-BGBUpZEQ.js} +1 -1
- package/dist/assets/{desktopHosts-B1ixEylr.js → desktopHosts-JGFqhlaM.js} +1 -1
- package/dist/assets/{desktopRelayRestore-4JmFUw8r.js → desktopRelayRestore-CHEwrI93.js} +1 -1
- package/dist/assets/{diagram-DQf7Y_uR.js → diagram-rvn7_qBM.js} +1 -1
- package/dist/assets/{dialog-bfbvR4VH.js → dialog-CQ63sc9E.js} +1 -1
- package/dist/assets/es-Dsmc0A_3.js +15 -0
- package/dist/assets/fileMentionTouchSelection-BzzcWJCi.js +3 -0
- package/dist/assets/{fileQueries-DQc8EJUf.js → fileQueries-DN6gbLhM.js} +1 -1
- package/dist/assets/fr-C_ZlZDI2.js +13 -0
- package/dist/assets/gitApi-BF8vuoZc.js +10 -0
- package/dist/assets/{imageSource-BlAJJUEI.js → imageSource-BMztRu0c.js} +1 -1
- package/dist/assets/{input-8r6F_Fza.js → input-BVu-iykl.js} +1 -1
- package/dist/assets/insertionBoundaries-EcAfGT2D.js +1 -0
- package/dist/assets/ja-BqqTaWTi.js +15 -0
- package/dist/assets/ko-DP2XPM37.js +15 -0
- package/dist/assets/{main-CCE_4y5F.js → main-B7t9lavz.js} +2 -2
- package/dist/assets/main-D2BzpnUt.css +1 -0
- package/dist/assets/main-DWP-prNB.js +169 -0
- package/dist/assets/markdown-worker-bS5OgGO3.js +2 -0
- package/dist/assets/{markdownHeightCache-1Qo6y6IJ.js → markdownHeightCache-D9-B1wdY.js} +1 -1
- package/dist/assets/markdownTheme-DM5h1i18.js +1 -0
- package/dist/assets/mcpQueries-CfXrAkuU.js +1 -0
- package/dist/assets/miniChat-DgOrEQbN.js +2 -0
- package/dist/assets/mobile-Co_ZOHkZ.js +2 -0
- package/dist/assets/multirun-DelyUO6k.js +4 -0
- package/dist/assets/persistence-D0y7226-.js +3 -0
- package/dist/assets/pl-BCf5uLlK.js +15 -0
- package/dist/assets/platform-CurqO28D.js +6 -0
- package/dist/assets/projectMeta-CPElzJ0n.js +3 -0
- package/dist/assets/pt-BR-W09Q2pvn.js +15 -0
- package/dist/assets/{relay-image-stream-DM7atqJs.js → relay-image-stream-DrdVj99c.js} +1 -1
- package/dist/assets/renderElectronMiniChatApp-pOE93w86.js +2 -0
- package/dist/assets/renderMobileApp-F7ZSLcw8.js +28 -0
- package/dist/assets/runtime-fetch-Fs9ZV2V8.js +1 -0
- package/dist/assets/{runtimeConfig-BMvqa5we.js → runtimeConfig-DSS0KxG3.js} +1 -1
- package/dist/assets/runtimeEndpointReset-x2Wgx57R.js +149 -0
- package/dist/assets/sessionChangeSummary-BUGSYcHp.js +2 -0
- package/dist/assets/{sessionLookup-gh-hVRIc.js → sessionLookup-Bss8M20i.js} +1 -1
- package/dist/assets/{sortable-tabs-strip-CudoSgV4.js → sortable-tabs-strip-CE7W7lJ9.js} +1 -1
- package/dist/assets/src-lS1keDVV.css +2 -0
- package/dist/assets/store-jaP79mqI.js +15 -0
- package/dist/assets/{terminalApi-DiF6JmBP.js → terminalApi-mDR2jXTo.js} +1 -1
- package/dist/assets/textarea-XD2oX_Ee.js +1 -0
- package/dist/assets/{tooltip-CQvpK-UV.js → tooltip-DYeQ_Hvy.js} +1 -1
- package/dist/assets/uk-BgFzz8m2.js +15 -0
- package/dist/assets/{url-_z7evzdK.js → url-CGbJbiJq.js} +1 -1
- package/dist/assets/{useAppFontEffects-Cpmpo7Wb.js → useAppFontEffects-BAWHZ-t0.js} +64 -45
- package/dist/assets/{useAssistantUIStore-CMutVh9B.js → useAssistantUIStore-Bz4tRflF.js} +1 -1
- package/dist/assets/useDesktopWindowControlsLayout-hN_nLb7T.js +1 -0
- package/dist/assets/useEffectiveDirectory-Do9DQ453.js +1 -0
- package/dist/assets/{useFontPreferences-DcbXQOkc.js → useFontPreferences-Bjx8zkGM.js} +1 -1
- package/dist/assets/useMobileNavigationStore-BsY_gi_K.js +414 -0
- package/dist/assets/useSessionAutoCleanup-C4g5KmDf.js +2 -0
- package/dist/assets/useUIStore-syVmbuDA.js +1 -0
- package/dist/assets/{useWorkerHighlightedLines-Bqn4AiBL.js → useWorkerHighlightedLines-B5QXxBok.js} +2 -2
- package/dist/assets/vendor-opencode-client-C12gfjag.js +12 -0
- package/dist/assets/{vendor-reactuses-core-BnW6GxJt.js → vendor-reactuses-core-Dq5ocTF8.js} +1 -1
- package/dist/assets/zh-CN-BhqSLgUY.js +15 -0
- package/dist/assets/zh-TW-BsaBgY-p.js +15 -0
- package/dist/index.html +12 -12
- package/dist/mini-chat.html +12 -12
- package/dist/mobile.html +12 -12
- package/package.json +3 -2
- package/server/index.js +359 -63
- package/server/lib/assistants/DOCUMENTATION.md +14 -9
- package/server/lib/assistants/contracts.js +11 -1
- package/server/lib/assistants/projection-history.test.js +265 -18
- package/server/lib/assistants/routes.js +6 -0
- package/server/lib/assistants/service.js +417 -231
- package/server/lib/assistants/service.test.js +392 -148
- package/server/lib/browser-provider/DOCUMENTATION.md +141 -0
- package/server/lib/browser-provider/contract.js +312 -0
- package/server/lib/browser-provider/host.js +421 -0
- package/server/lib/browser-provider/host.test.js +304 -0
- package/server/lib/browser-provider/routes.js +122 -0
- package/server/lib/browser-provider/routes.test.js +120 -0
- package/server/lib/browser-provider/selection-store.js +43 -0
- package/server/lib/browser-provider/selection-store.test.js +35 -0
- package/server/lib/conversations/DOCUMENTATION.md +1 -1
- package/server/lib/conversations/service.js +1 -0
- package/server/lib/conversations/service.test.js +16 -0
- package/server/lib/conversations/validation.js +11 -1
- package/server/lib/event-stream/DOCUMENTATION.md +3 -1
- package/server/lib/event-stream/directory-ws-bridge.js +13 -2
- package/server/lib/event-stream/global-hub.js +49 -4
- package/server/lib/event-stream/reasoning-projection.js +16 -1
- package/server/lib/event-stream/reasoning-projection.test.js +15 -0
- 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 +33 -9
- package/server/lib/llm/catalog.js +1 -1
- package/server/lib/llm/completions.js +5 -1
- package/server/lib/llm/completions.test.js +3 -3
- package/server/lib/llm/generate.js +237 -145
- package/server/lib/llm/generate.test.js +201 -46
- package/server/lib/llm/routes.js +2 -0
- package/server/lib/message-queue/runtime.js +15 -2
- package/server/lib/notifications/DOCUMENTATION.md +3 -1
- package/server/lib/notifications/runtime.js +133 -31
- package/server/lib/notifications/runtime.test.js +103 -0
- package/server/lib/notifications/template-runtime.js +130 -38
- package/server/lib/notifications/template-runtime.test.js +96 -0
- package/server/lib/opencode/DOCUMENTATION.md +89 -17
- 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 +42 -99
- package/server/lib/opencode/config-entity-routes.test.js +107 -0
- package/server/lib/opencode/config-hot-reload.integration.test.js +105 -0
- package/server/lib/opencode/ensure-cli.d.ts +8 -0
- package/server/lib/opencode/ensure-cli.js +1 -2
- package/server/lib/opencode/env-runtime.js +40 -26
- package/server/lib/opencode/env-runtime.test.js +10 -17
- package/server/lib/opencode/feature-routes-runtime.js +53 -4
- package/server/lib/opencode/feature-routes-runtime.test.js +25 -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 +349 -39
- package/server/lib/opencode/lifecycle.test.js +322 -0
- 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/openchamber-routes.js +7 -1
- package/server/lib/opencode/opencode2-pin.js +4 -4
- package/server/lib/opencode/opencode2-pin.test.js +1 -0
- package/server/lib/opencode/opencode2-sidecar.e2e.test.js +127 -4
- 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-routes.js +3 -18
- package/server/lib/opencode/plugin-routes.test.js +9 -9
- 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 +254 -46
- package/server/lib/opencode/proxy.test.js +238 -5
- package/server/lib/opencode/routes.js +326 -62
- package/server/lib/opencode/routes.test.js +278 -12
- 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 +33 -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 +20 -33
- package/server/lib/opencode/skill-routes.test.js +35 -2
- 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/upgrade-screen.d.ts +30 -0
- package/server/lib/opencode/upgrade-screen.js +299 -0
- package/server/lib/opencode/upgrade-screen.test.js +196 -0
- package/server/lib/opencode/v2-client.js +14 -3
- 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/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 +8 -0
- package/server/lib/scheduled-tasks/runtime.js +52 -4
- package/server/lib/scheduled-tasks/runtime.test.js +80 -1
- package/server/lib/session-goal/DOCUMENTATION.md +113 -13
- package/server/lib/session-goal/routes.js +9 -0
- package/server/lib/session-goal/runtime.js +1579 -117
- package/server/lib/session-goal/runtime.test.js +1453 -84
- 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 +161 -34
- package/server/lib/session-index/sync-runtime.test.js +155 -1
- package/server/lib/session-metadata/DOCUMENTATION.md +73 -18
- package/server/lib/session-metadata/opencode-session-record.d.ts +57 -0
- package/server/lib/session-metadata/opencode-session-record.js +316 -0
- package/server/lib/session-metadata/opencode-session-record.test.js +242 -0
- package/server/lib/session-metadata/routes.js +112 -9
- package/server/lib/session-metadata/routes.test.js +47 -2
- 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 +38 -0
- package/server/lib/session-metadata/session-metadata-store.js +270 -83
- package/server/lib/session-metadata/session-metadata-store.test.js +205 -10
- package/server/lib/session-metadata/session-projection.d.ts +41 -0
- package/server/lib/session-metadata/session-projection.js +279 -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 +69 -44
- 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 +9 -8
- package/server/lib/session-turn-pages/routes.js +17 -102
- package/server/lib/session-turn-pages/routes.test.js +281 -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 -147
- package/server/lib/small-model/catalog.js +31 -51
- package/server/lib/small-model/catalog.test.js +65 -10
- 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 +124 -240
- 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 +2 -0
- package/dist/assets/AssistantView-BTCkm8yk.js +0 -3
- package/dist/assets/Icon-DD-BuMfZ.js +0 -1
- package/dist/assets/MarkdownRenderer-bc_p1H7l.js +0 -2
- package/dist/assets/MarkstreamRendererImpl-CnkodGJW.js +0 -3
- package/dist/assets/MobileSurface-BXLeiZ4d.js +0 -2
- package/dist/assets/OverlayScrollbar-pMwxaCca.js +0 -2
- package/dist/assets/SettingsView-B5I0KDTZ.js +0 -25
- package/dist/assets/TerminalView-Dh9MWCpS.js +0 -8
- package/dist/assets/appThemeRegistry-COGfxTFV.js +0 -1
- package/dist/assets/es-c52LTHHe.js +0 -15
- package/dist/assets/fileMentionTouchSelection-BvrNCroG.js +0 -4
- package/dist/assets/fr-PisFbUE8.js +0 -13
- package/dist/assets/gitApi-ButwzQ0N.js +0 -9
- package/dist/assets/insertionBoundaries-DGs7S5zv.js +0 -1
- package/dist/assets/ja-C8Ikun3Z.js +0 -15
- package/dist/assets/ko-ClFys5o2.js +0 -15
- package/dist/assets/main-Dn9rpsgl.js +0 -169
- package/dist/assets/main-qSeeJRW1.css +0 -1
- package/dist/assets/markdown-worker-CptoICmq.js +0 -2
- package/dist/assets/markdownTheme-DOfGg-A7.js +0 -1
- package/dist/assets/miniChat-BpjxVqgg.js +0 -2
- package/dist/assets/mobile-nMJCaNq1.js +0 -2
- package/dist/assets/multirun-BvSG94mW.js +0 -4
- package/dist/assets/persistence-Ce3AnpEr.js +0 -3
- package/dist/assets/pl-CnaKWN5F.js +0 -15
- package/dist/assets/platform-CWTIp02q.js +0 -4
- package/dist/assets/projectMeta-DOe49dM_.js +0 -3
- package/dist/assets/pt-BR-s8OpfRI6.js +0 -15
- package/dist/assets/renderElectronMiniChatApp-R6dKh79f.js +0 -2
- package/dist/assets/renderMobileApp-y-S8y8v_.js +0 -28
- package/dist/assets/runtime-fetch-zIalUnbb.js +0 -1
- package/dist/assets/runtimeEndpointReset-B6BxhvR0.js +0 -147
- package/dist/assets/sessionChangeSummary-VVBlEXuh.js +0 -2
- package/dist/assets/src-BzX5UI-c.css +0 -2
- package/dist/assets/store-DJczmczv.js +0 -15
- package/dist/assets/textarea-3XR8sUfy.js +0 -1
- package/dist/assets/uk-CaX0iqkB.js +0 -15
- package/dist/assets/useDesktopWindowControlsLayout-B1GX59-L.js +0 -1
- package/dist/assets/useEffectiveDirectory-CN6JoCFw.js +0 -1
- package/dist/assets/useMobileNavigationStore-BVjFtXSy.js +0 -414
- package/dist/assets/useSessionAutoCleanup-BLjymaFt.js +0 -2
- package/dist/assets/useUIStore-Bxv3f23A.js +0 -1
- package/dist/assets/vendor-opencode-client-BOe2qpQb.js +0 -12
- package/dist/assets/zh-CN-20MYEjha.js +0 -15
- package/dist/assets/zh-TW-DiN04qTw.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 -183
- package/server/lib/small-model/opencode-session.test.js +0 -147
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
import { createProjectIdFromPath } from '../projects/project-id.js';
|
|
2
2
|
import { projectBootstrapSettingsResponse } from './settings-helpers.js';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
PINNED_OPENCODE2_VERSION,
|
|
5
|
+
evaluateOpenCodeHealthBody,
|
|
6
|
+
isOpenCode1xVersion,
|
|
7
|
+
resolveOpenCode2UpgradeTarget,
|
|
8
|
+
} from './opencode2-pin.js';
|
|
9
|
+
import {
|
|
10
|
+
installPinnedOpenCode2Cli,
|
|
11
|
+
readOpenCode2BinaryVersion,
|
|
12
|
+
resolveOpenChamberDataDir,
|
|
13
|
+
} from './ensure-cli.js';
|
|
14
|
+
import { registerUpgradeScreenRoutes } from './upgrade-screen.js';
|
|
15
|
+
import { evaluateRuntimeContract } from './runtime-contract.js';
|
|
16
|
+
import {
|
|
17
|
+
buildUpgradeStatusSnapshot,
|
|
18
|
+
classifyRuntimeOwnership,
|
|
19
|
+
createUpgradeOperationState,
|
|
20
|
+
evaluateOwnedUpgradeResult,
|
|
21
|
+
resolveOwnedCacheBinaryPath,
|
|
22
|
+
} from './owned-runtime-upgrade.js';
|
|
4
23
|
import fs from 'fs';
|
|
5
24
|
import os from 'os';
|
|
6
25
|
import path from 'path';
|
|
@@ -24,8 +43,22 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
24
43
|
getOpenCodeAuthHeaders,
|
|
25
44
|
onSettingsPersisted,
|
|
26
45
|
getIsExternalOpenCode = () => false,
|
|
46
|
+
getIsSharedOpenCodeService = () => false,
|
|
47
|
+
forceResolvedOpenCodeBinary = null,
|
|
48
|
+
restartOpenCode = null,
|
|
49
|
+
waitForOpenCodeReady = null,
|
|
50
|
+
getRuntimeContract = () => null,
|
|
51
|
+
getOpenCodeServeVersion = () => null,
|
|
52
|
+
getOpenCodeCliVersion = () => null,
|
|
53
|
+
getResolvedOpenCodeBinary = () => null,
|
|
54
|
+
getResolvedOpenCodeBinarySource = () => null,
|
|
55
|
+
getActiveSessionCount = () => 0,
|
|
56
|
+
openchamberDataDir = null,
|
|
27
57
|
} = dependencies;
|
|
28
58
|
|
|
59
|
+
const upgradeOperation = createUpgradeOperationState();
|
|
60
|
+
const resolveDataDir = () => openchamberDataDir || resolveOpenChamberDataDir();
|
|
61
|
+
|
|
29
62
|
let authLibrary = null;
|
|
30
63
|
const pendingMcpAuthContextByState = new Map();
|
|
31
64
|
const PENDING_MCP_AUTH_TTL_MS = 30 * 60 * 1000;
|
|
@@ -58,10 +91,81 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
58
91
|
});
|
|
59
92
|
const health = await healthResponse.json().catch(() => null);
|
|
60
93
|
if (!healthResponse.ok) {
|
|
61
|
-
return {
|
|
94
|
+
return {
|
|
95
|
+
ok: false,
|
|
96
|
+
status: healthResponse.status,
|
|
97
|
+
error: health?.error || healthResponse.statusText,
|
|
98
|
+
authenticated: healthResponse.status === 401 || healthResponse.status === 403 ? false : null,
|
|
99
|
+
};
|
|
62
100
|
}
|
|
63
|
-
const
|
|
64
|
-
|
|
101
|
+
const gate = evaluateOpenCodeHealthBody(health);
|
|
102
|
+
const currentVersion = gate.version
|
|
103
|
+
|| (typeof health?.version === 'string' ? health.version.replace(/^v/, '') : null);
|
|
104
|
+
return { ok: gate.ok, currentVersion, healthOk: gate.ok, authenticated: true };
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const resolveOwnershipContext = async () => {
|
|
108
|
+
const isExternal = getIsExternalOpenCode() === true;
|
|
109
|
+
let binarySource = typeof getResolvedOpenCodeBinarySource === 'function'
|
|
110
|
+
? getResolvedOpenCodeBinarySource()
|
|
111
|
+
: null;
|
|
112
|
+
let binaryPath = typeof getResolvedOpenCodeBinary === 'function'
|
|
113
|
+
? getResolvedOpenCodeBinary()
|
|
114
|
+
: null;
|
|
115
|
+
try {
|
|
116
|
+
const settings = await readSettingsFromDiskMigrated();
|
|
117
|
+
const resolution = await getOpenCodeResolutionSnapshot(settings);
|
|
118
|
+
binarySource = binarySource || resolution?.source || resolution?.detectedSourceNow || null;
|
|
119
|
+
binaryPath = binaryPath || resolution?.resolved || null;
|
|
120
|
+
if (resolution?.source === 'bundled' || resolution?.detectedSourceNow === 'bundled') {
|
|
121
|
+
binarySource = 'bundled';
|
|
122
|
+
}
|
|
123
|
+
} catch {
|
|
124
|
+
// Resolution failures still allow ownership classification from runtime flags.
|
|
125
|
+
}
|
|
126
|
+
return classifyRuntimeOwnership({
|
|
127
|
+
isExternal,
|
|
128
|
+
isSharedService: getIsSharedOpenCodeService() === true,
|
|
129
|
+
binarySource,
|
|
130
|
+
binaryPath,
|
|
131
|
+
dataDir: resolveDataDir(),
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const buildLiveContract = async ({ fresh = false } = {}) => {
|
|
136
|
+
const cached = typeof getRuntimeContract === 'function' ? getRuntimeContract() : null;
|
|
137
|
+
const serveProbe = await readOpenCodeCurrentVersion().catch(() => ({ ok: false, currentVersion: null }));
|
|
138
|
+
const serveVersion = serveProbe.currentVersion
|
|
139
|
+
|| (!fresh && typeof getOpenCodeServeVersion === 'function' ? getOpenCodeServeVersion() : null);
|
|
140
|
+
const binaryPath = typeof getResolvedOpenCodeBinary === 'function' ? getResolvedOpenCodeBinary() : null;
|
|
141
|
+
const cliVersion = (typeof getOpenCodeCliVersion === 'function' ? getOpenCodeCliVersion() : null)
|
|
142
|
+
|| (binaryPath ? readOpenCode2BinaryVersion(binaryPath) : null)
|
|
143
|
+
|| null;
|
|
144
|
+
return evaluateRuntimeContract({
|
|
145
|
+
serveVersion,
|
|
146
|
+
cliVersion,
|
|
147
|
+
reachable: fresh ? serveProbe.ok === true : serveProbe.ok === true || Boolean(serveVersion) || Boolean(cached?.reachable),
|
|
148
|
+
authenticated: serveProbe.authenticated ?? (fresh ? null : cached?.authenticated) ?? null,
|
|
149
|
+
healthOk: serveProbe.healthOk ?? serveProbe.ok ?? (fresh ? false : cached?.healthOk) ?? null,
|
|
150
|
+
migrationAdmitTranscript: cached?.migrationExecutable ?? null,
|
|
151
|
+
migrationPhase: cached?.migrationPhase ?? null,
|
|
152
|
+
migrationError: cached?.migrationError ?? null,
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const buildUpgradeStatus = async () => {
|
|
157
|
+
const ownership = await resolveOwnershipContext();
|
|
158
|
+
const contract = await buildLiveContract();
|
|
159
|
+
const activeCount = typeof getActiveSessionCount === 'function' ? Number(getActiveSessionCount()) || 0 : 0;
|
|
160
|
+
return buildUpgradeStatusSnapshot({
|
|
161
|
+
ownership,
|
|
162
|
+
serveVersion: contract.serveVersion,
|
|
163
|
+
cliVersion: contract.cliVersion,
|
|
164
|
+
targetVersion: PINNED_OPENCODE2_VERSION,
|
|
165
|
+
contract,
|
|
166
|
+
operation: upgradeOperation.getState(),
|
|
167
|
+
hasActiveTasks: activeCount > 0,
|
|
168
|
+
});
|
|
65
169
|
};
|
|
66
170
|
|
|
67
171
|
const parseVersionForComparison = (value) => {
|
|
@@ -150,6 +254,35 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
150
254
|
return fallback;
|
|
151
255
|
};
|
|
152
256
|
|
|
257
|
+
registerUpgradeScreenRoutes(app, {
|
|
258
|
+
resolveOwnership: resolveOwnershipContext,
|
|
259
|
+
readServeVersion: async () => {
|
|
260
|
+
const probe = await readOpenCodeCurrentVersion().catch(() => ({ currentVersion: null }));
|
|
261
|
+
return probe.currentVersion || null;
|
|
262
|
+
},
|
|
263
|
+
readCliVersion: () => {
|
|
264
|
+
const fromRuntime = typeof getOpenCodeCliVersion === 'function' ? getOpenCodeCliVersion() : null;
|
|
265
|
+
if (fromRuntime) return fromRuntime;
|
|
266
|
+
const binaryPath = typeof getResolvedOpenCodeBinary === 'function' ? getResolvedOpenCodeBinary() : null;
|
|
267
|
+
return binaryPath ? readOpenCode2BinaryVersion(binaryPath) : null;
|
|
268
|
+
},
|
|
269
|
+
readConfiguredBinary: async () => {
|
|
270
|
+
const settings = await readSettingsFromDiskMigrated();
|
|
271
|
+
return typeof settings?.opencodeBinary === 'string' ? settings.opencodeBinary : null;
|
|
272
|
+
},
|
|
273
|
+
persistBinary: async (binaryPath) => {
|
|
274
|
+
await persistSettings({ opencodeBinary: binaryPath });
|
|
275
|
+
},
|
|
276
|
+
getResolvedBinary: getResolvedOpenCodeBinary,
|
|
277
|
+
getResolvedBinarySource: getResolvedOpenCodeBinarySource,
|
|
278
|
+
forceBinary: typeof forceResolvedOpenCodeBinary === 'function' ? forceResolvedOpenCodeBinary : null,
|
|
279
|
+
restart: typeof restartOpenCode === 'function' ? restartOpenCode : null,
|
|
280
|
+
waitReady: typeof waitForOpenCodeReady === 'function' ? waitForOpenCodeReady : null,
|
|
281
|
+
isSharedService: () => getIsSharedOpenCodeService() === true,
|
|
282
|
+
install: (options) => installPinnedOpenCode2Cli({ ...options, dataDir: resolveDataDir() }),
|
|
283
|
+
readBinaryVersion: readOpenCode2BinaryVersion,
|
|
284
|
+
});
|
|
285
|
+
|
|
153
286
|
app.get('/api/config/settings', async (req, res) => {
|
|
154
287
|
try {
|
|
155
288
|
const settings = await readSettingsFromDiskMigrated();
|
|
@@ -185,17 +318,17 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
185
318
|
|
|
186
319
|
app.post('/api/opencode/upgrade', async (req, res) => {
|
|
187
320
|
try {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (await isBundledOpenCodeBinaryActive()) {
|
|
196
|
-
return res.status(409).json({
|
|
321
|
+
const ownership = await resolveOwnershipContext();
|
|
322
|
+
if (!ownership.canUpgradeInApp) {
|
|
323
|
+
const status = ownership.ownership === 'external-serve' || ownership.ownership === 'bundled' ? 409 : 409;
|
|
324
|
+
return res.status(status).json({
|
|
197
325
|
success: false,
|
|
198
|
-
error:
|
|
326
|
+
error: ownership.guidance
|
|
327
|
+
|| 'OpenChamber can only upgrade its owned OpenCode cache in-app.',
|
|
328
|
+
errorCode: ownership.reason || 'UPGRADE_NOT_MANAGED',
|
|
329
|
+
ownership: ownership.ownership,
|
|
330
|
+
management: ownership.management,
|
|
331
|
+
guidance: ownership.guidance,
|
|
199
332
|
});
|
|
200
333
|
}
|
|
201
334
|
|
|
@@ -206,23 +339,136 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
206
339
|
return res.status(400).json({
|
|
207
340
|
success: false,
|
|
208
341
|
error: 'OpenCode upgrade refuses 1.x targets. Only pinned opencode2 is allowed.',
|
|
342
|
+
errorCode: 'OPENCODE_UPGRADE_1X_REFUSED',
|
|
209
343
|
});
|
|
210
344
|
}
|
|
211
345
|
const target = resolveOpenCode2UpgradeTarget(rawTarget);
|
|
346
|
+
const confirmActive = req.body?.confirmActiveTasks === true || req.body?.force === true;
|
|
347
|
+
const activeCount = typeof getActiveSessionCount === 'function' ? Number(getActiveSessionCount()) || 0 : 0;
|
|
348
|
+
if (activeCount > 0 && !confirmActive) {
|
|
349
|
+
return res.status(409).json({
|
|
350
|
+
success: false,
|
|
351
|
+
error: 'OpenCode has active sessions. Confirm upgrade to interrupt them, or wait until idle.',
|
|
352
|
+
errorCode: 'UPGRADE_ACTIVE_TASKS',
|
|
353
|
+
hasActiveTasks: true,
|
|
354
|
+
activeSessionCount: activeCount,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const begin = upgradeOperation.begin(target);
|
|
359
|
+
if (!begin.ok) {
|
|
360
|
+
return res.status(begin.status).json(begin.body);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const expectedBinaryPath = resolveOwnedCacheBinaryPath(target, { dataDir: resolveDataDir() });
|
|
364
|
+
let installedPath = expectedBinaryPath;
|
|
365
|
+
const previousBinary = getResolvedOpenCodeBinary();
|
|
366
|
+
const previousSource = getResolvedOpenCodeBinarySource();
|
|
212
367
|
|
|
213
368
|
try {
|
|
214
|
-
|
|
215
|
-
|
|
369
|
+
upgradeOperation.setPhase('download');
|
|
370
|
+
installedPath = await installPinnedOpenCode2Cli({
|
|
371
|
+
version: target,
|
|
372
|
+
dataDir: resolveDataDir(),
|
|
373
|
+
});
|
|
374
|
+
const diskVersion = readOpenCode2BinaryVersion(installedPath);
|
|
375
|
+
if (diskVersion !== target) {
|
|
376
|
+
const error = new Error(
|
|
377
|
+
`Owned-cache binary version mismatch after install: expected ${target}, got ${diskVersion || 'unknown'}`,
|
|
378
|
+
);
|
|
379
|
+
error.code = 'UPGRADE_BINARY_VERSION_MISMATCH';
|
|
380
|
+
throw error;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
upgradeOperation.setPhase('pin-binary', { binaryPath: installedPath });
|
|
384
|
+
if (typeof forceResolvedOpenCodeBinary !== 'function') {
|
|
385
|
+
const error = new Error('Owned-cache upgrade requires forceResolvedOpenCodeBinary');
|
|
386
|
+
error.code = 'UPGRADE_FORCE_BINARY_UNAVAILABLE';
|
|
387
|
+
throw error;
|
|
388
|
+
}
|
|
389
|
+
// Keep target identity through restart — do not rediscover global CLI.
|
|
390
|
+
forceResolvedOpenCodeBinary(installedPath, 'installed');
|
|
391
|
+
|
|
392
|
+
upgradeOperation.setPhase('restart');
|
|
393
|
+
if (typeof restartOpenCode === 'function') {
|
|
394
|
+
await restartOpenCode(ownership.ownership === 'shared-service' ? { binaryPath: installedPath } : undefined);
|
|
395
|
+
} else if (typeof refreshOpenCodeAfterConfigChange === 'function') {
|
|
396
|
+
// Fallback: still pin binary first so restart prefers owned cache.
|
|
397
|
+
await refreshOpenCodeAfterConfigChange('OpenCode owned-cache upgrade');
|
|
398
|
+
} else {
|
|
399
|
+
const error = new Error('No OpenCode restart path is configured');
|
|
400
|
+
error.code = 'UPGRADE_RESTART_UNAVAILABLE';
|
|
401
|
+
throw error;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (typeof waitForOpenCodeReady === 'function') {
|
|
405
|
+
upgradeOperation.setPhase('wait-ready');
|
|
406
|
+
await waitForOpenCodeReady();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
upgradeOperation.setPhase('verify');
|
|
410
|
+
// Re-pin after restart helpers that may clear resolution.
|
|
411
|
+
forceResolvedOpenCodeBinary(installedPath, 'installed');
|
|
412
|
+
const contract = await buildLiveContract({ fresh: true });
|
|
413
|
+
const verification = evaluateOwnedUpgradeResult({
|
|
414
|
+
targetVersion: target,
|
|
415
|
+
serveVersion: contract.serveVersion,
|
|
416
|
+
cliVersion: contract.cliVersion,
|
|
417
|
+
binaryPath: typeof getResolvedOpenCodeBinary === 'function'
|
|
418
|
+
? getResolvedOpenCodeBinary()
|
|
419
|
+
: installedPath,
|
|
420
|
+
expectedBinaryPath: installedPath,
|
|
421
|
+
contract,
|
|
422
|
+
});
|
|
423
|
+
if (!verification.ok) {
|
|
424
|
+
const error = new Error(verification.error);
|
|
425
|
+
error.code = verification.errorCode;
|
|
426
|
+
error.serveVersion = verification.serveVersion;
|
|
427
|
+
error.contract = verification.contract;
|
|
428
|
+
throw error;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
upgradeOperation.succeed({
|
|
432
|
+
serveVersion: verification.serveVersion,
|
|
433
|
+
binaryPath: installedPath,
|
|
434
|
+
});
|
|
435
|
+
return res.json({
|
|
436
|
+
success: true,
|
|
437
|
+
upgraded: true,
|
|
438
|
+
restarted: true,
|
|
439
|
+
version: verification.serveVersion,
|
|
440
|
+
targetVersion: target,
|
|
441
|
+
pinned: true,
|
|
442
|
+
supplySource: 'owned-cache',
|
|
443
|
+
ownership: ownership.ownership === 'shared-service' ? 'shared-service' : 'owned-cache',
|
|
444
|
+
binaryPath: installedPath,
|
|
445
|
+
contract: verification.contract,
|
|
446
|
+
operation: upgradeOperation.getState(),
|
|
447
|
+
});
|
|
448
|
+
} catch (upgradeError) {
|
|
449
|
+
if (previousBinary && typeof forceResolvedOpenCodeBinary === 'function') {
|
|
450
|
+
forceResolvedOpenCodeBinary(previousBinary, previousSource);
|
|
451
|
+
}
|
|
452
|
+
const message = upgradeError instanceof Error ? upgradeError.message : 'Failed to upgrade OpenCode';
|
|
453
|
+
const errorCode = upgradeError?.code || 'UPGRADE_FAILED';
|
|
454
|
+
upgradeOperation.fail({
|
|
455
|
+
error: message,
|
|
456
|
+
errorCode,
|
|
457
|
+
phase: upgradeOperation.getState().phase,
|
|
458
|
+
serveVersion: upgradeError?.serveVersion ?? null,
|
|
459
|
+
binaryPath: installedPath,
|
|
460
|
+
});
|
|
461
|
+
// Preserve previous owned cache on disk; only report failure.
|
|
216
462
|
return res.status(500).json({
|
|
217
463
|
success: false,
|
|
218
|
-
upgraded:
|
|
219
|
-
error:
|
|
220
|
-
|
|
221
|
-
|
|
464
|
+
upgraded: false,
|
|
465
|
+
error: message,
|
|
466
|
+
errorCode,
|
|
467
|
+
targetVersion: target,
|
|
468
|
+
operation: upgradeOperation.getState(),
|
|
469
|
+
contract: upgradeError?.contract || null,
|
|
222
470
|
});
|
|
223
471
|
}
|
|
224
|
-
|
|
225
|
-
return res.json({ success: true, restarted: true, version: target, pinned: true });
|
|
226
472
|
} catch (error) {
|
|
227
473
|
console.error('Failed to upgrade OpenCode:', error);
|
|
228
474
|
return res.status(500).json({
|
|
@@ -234,42 +480,35 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
234
480
|
|
|
235
481
|
app.get('/api/opencode/upgrade-status', async (_req, res) => {
|
|
236
482
|
try {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const healthResponse = await fetch(buildOpenCodeUrl('/api/info', ''), {
|
|
248
|
-
method: 'GET',
|
|
249
|
-
headers: { Accept: 'application/json', ...getOpenCodeAuthHeaders() },
|
|
483
|
+
const status = await buildUpgradeStatus();
|
|
484
|
+
return res.json(status);
|
|
485
|
+
} catch (error) {
|
|
486
|
+
return res.status(500).json({
|
|
487
|
+
available: null,
|
|
488
|
+
error: error instanceof Error ? error.message : 'Failed to check OpenCode upgrade status',
|
|
489
|
+
operation: upgradeOperation.getState(),
|
|
250
490
|
});
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const currentVersion = typeof health?.version === 'string' ? health.version.replace(/^v/, '') : null;
|
|
259
|
-
const latestVersion = isOpenCode1xVersion(PINNED_OPENCODE2_VERSION) ? null : PINNED_OPENCODE2_VERSION;
|
|
260
|
-
if (!currentVersion || !latestVersion) {
|
|
261
|
-
return res.json({ available: null, currentVersion, latestVersion });
|
|
262
|
-
}
|
|
263
|
-
const available = !isOpenCode1xVersion(currentVersion) && compareVersions(latestVersion, currentVersion) > 0;
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
app.get('/api/opencode/contract', async (_req, res) => {
|
|
495
|
+
try {
|
|
496
|
+
const contract = await buildLiveContract();
|
|
497
|
+
const ownership = await resolveOwnershipContext();
|
|
264
498
|
return res.json({
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
499
|
+
...contract,
|
|
500
|
+
ownership: ownership.ownership,
|
|
501
|
+
supplySource: ownership.supplySource,
|
|
502
|
+
canManageUpgrade: ownership.canUpgradeInApp,
|
|
503
|
+
management: ownership.management,
|
|
504
|
+
guidance: ownership.guidance,
|
|
268
505
|
});
|
|
269
506
|
} catch (error) {
|
|
270
507
|
return res.status(500).json({
|
|
271
|
-
|
|
272
|
-
|
|
508
|
+
schemaVersion: 1,
|
|
509
|
+
phase: 'unknown',
|
|
510
|
+
executionAllowed: false,
|
|
511
|
+
error: error instanceof Error ? error.message : 'Failed to evaluate OpenCode runtime contract',
|
|
273
512
|
});
|
|
274
513
|
}
|
|
275
514
|
});
|
|
@@ -283,22 +522,45 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
283
522
|
});
|
|
284
523
|
const health = await healthResponse.json().catch(() => null);
|
|
285
524
|
if (!healthResponse.ok) {
|
|
525
|
+
const contract = evaluateRuntimeContract({
|
|
526
|
+
reachable: false,
|
|
527
|
+
authenticated: healthResponse.status === 401 || healthResponse.status === 403 ? false : null,
|
|
528
|
+
healthOk: false,
|
|
529
|
+
});
|
|
286
530
|
return res.status(healthResponse.status).json({
|
|
287
531
|
healthy: false,
|
|
288
532
|
error: health?.error || healthResponse.statusText || 'OpenCode health check failed',
|
|
533
|
+
contract,
|
|
289
534
|
});
|
|
290
535
|
}
|
|
291
|
-
|
|
536
|
+
// Reuse lifecycle/sidecar gate: official 2.x ServerInfo omits `healthy`.
|
|
537
|
+
const gate = evaluateOpenCodeHealthBody(health);
|
|
538
|
+
const contract = await buildLiveContract().catch(() => evaluateRuntimeContract({
|
|
539
|
+
serveVersion: gate.version,
|
|
540
|
+
reachable: gate.ok,
|
|
541
|
+
authenticated: true,
|
|
542
|
+
healthOk: gate.ok,
|
|
543
|
+
}));
|
|
544
|
+
return res.json({
|
|
545
|
+
healthy: gate.ok,
|
|
546
|
+
version: gate.version,
|
|
547
|
+
// Healthy is reachability/version shape only — not full execution semantics.
|
|
548
|
+
executionAllowed: contract.executionAllowed === true,
|
|
549
|
+
protocolCompatible: contract.protocolCompatible === true,
|
|
550
|
+
contract,
|
|
551
|
+
});
|
|
292
552
|
} catch (error) {
|
|
293
553
|
return res.status(503).json({
|
|
294
554
|
healthy: false,
|
|
295
555
|
error: error instanceof Error ? error.message : 'OpenCode health check failed',
|
|
556
|
+
contract: evaluateRuntimeContract({ reachable: false, healthOk: false }),
|
|
296
557
|
});
|
|
297
558
|
}
|
|
298
559
|
});
|
|
299
560
|
|
|
300
561
|
app.get('/api/opencode/version', async (_req, res) => {
|
|
301
562
|
try {
|
|
563
|
+
const contract = await buildLiveContract();
|
|
302
564
|
const healthResponse = await fetch(buildOpenCodeUrl('/api/info', ''), {
|
|
303
565
|
method: 'GET',
|
|
304
566
|
headers: { Accept: 'application/json', ...getOpenCodeAuthHeaders() },
|
|
@@ -307,11 +569,20 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
307
569
|
if (!healthResponse.ok) {
|
|
308
570
|
return res.status(healthResponse.status).json({
|
|
309
571
|
version: null,
|
|
572
|
+
serveVersion: null,
|
|
573
|
+
cliVersion: contract.cliVersion,
|
|
310
574
|
error: health?.error || healthResponse.statusText || 'Failed to read OpenCode version',
|
|
575
|
+
contract,
|
|
311
576
|
});
|
|
312
577
|
}
|
|
313
578
|
const version = typeof health?.version === 'string' ? health.version.replace(/^v/, '') : null;
|
|
314
|
-
return res.json({
|
|
579
|
+
return res.json({
|
|
580
|
+
version,
|
|
581
|
+
serveVersion: version,
|
|
582
|
+
cliVersion: contract.cliVersion,
|
|
583
|
+
versionMismatch: Boolean(version && contract.cliVersion && version !== contract.cliVersion),
|
|
584
|
+
contract,
|
|
585
|
+
});
|
|
315
586
|
} catch (error) {
|
|
316
587
|
return res.status(500).json({
|
|
317
588
|
version: null,
|
|
@@ -599,13 +870,6 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
599
870
|
|
|
600
871
|
await fs.promises.writeFile(AGENTS_MD_PATH, content, 'utf8');
|
|
601
872
|
|
|
602
|
-
// Refresh OpenCode so it picks up the new AGENTS.md without a full restart
|
|
603
|
-
try {
|
|
604
|
-
await refreshOpenCodeAfterConfigChange('global behavior (AGENTS.md) updated');
|
|
605
|
-
} catch {
|
|
606
|
-
// Non-fatal: file was written successfully
|
|
607
|
-
}
|
|
608
|
-
|
|
609
873
|
return res.json({ success: true });
|
|
610
874
|
} catch (error) {
|
|
611
875
|
console.error('Failed to write AGENTS.md:', error);
|