@openchambery/web 2.0.0-beta.1 → 2.0.0-beta.4
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-Q1SmFRx2.js} +1 -1
- package/dist/assets/AssistantView-CwXkiCAd.js +3 -0
- package/dist/assets/{DiagramView-xuSJTnv7.js → DiagramView-BW92schO.js} +1 -1
- package/dist/assets/{FadeInOnReveal-Ov0D96d0.js → FadeInOnReveal-BZmwl-zE.js} +1 -1
- package/dist/assets/{Icon-DD-BuMfZ.js → Icon-AQPvxMiU.js} +1 -1
- package/dist/assets/{MarkdownRenderer-bc_p1H7l.js → MarkdownRenderer-Bv05iDZZ.js} +2 -2
- package/dist/assets/{MarkdownRendererImpl-SKi4oG0c.js → MarkdownRendererImpl-C81xqYib.js} +3 -3
- package/dist/assets/MarkstreamRendererImpl-CXUCQuKJ.js +3 -0
- package/dist/assets/{MobileDetailNavigation-Bnx59U_J.js → MobileDetailNavigation-BMgIu7zc.js} +1 -1
- package/dist/assets/{MobileShareBridge-BQlP4J-F.js → MobileShareBridge-BOXGNHmC.js} +2 -2
- package/dist/assets/MobileSurface-xuc_z0_G.js +2 -0
- package/dist/assets/{MultiRunWindow-ChZGob0v.js → MultiRunWindow-B5At2Z95.js} +1 -1
- package/dist/assets/{OnboardingScreen-DtQJxZG-.js → OnboardingScreen-bsPLgz4r.js} +1 -1
- package/dist/assets/OverlayScrollbar-4wp4migh.js +2 -0
- package/dist/assets/SettingsView-CJ6tcH5_.js +25 -0
- package/dist/assets/{SettingsWindow-DfnsFa8y.js → SettingsWindow-CMtX2bMl.js} +1 -1
- package/dist/assets/{TerminalView-Dh9MWCpS.js → TerminalView-Dvr-ysTS.js} +1 -1
- package/dist/assets/{ToolOutputDialog-BejmjrRk.js → ToolOutputDialog-uH1ZZDSS.js} +2 -2
- package/dist/assets/appThemeRegistry-DK7q2juD.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-CcNJUxUd.js} +1 -1
- package/dist/assets/collapsible-ZmZ6rLWs.js +3 -0
- package/dist/assets/context-menu-B2LXJgXL.js +1 -0
- package/dist/assets/{desktopHosts-B1ixEylr.js → desktopHosts-C6HrP0jq.js} +1 -1
- package/dist/assets/{desktopRelayRestore-4JmFUw8r.js → desktopRelayRestore-DdVBp45U.js} +1 -1
- package/dist/assets/{diagram-DQf7Y_uR.js → diagram-CxTs9hCQ.js} +1 -1
- package/dist/assets/{dialog-bfbvR4VH.js → dialog-KMVL9QKF.js} +1 -1
- package/dist/assets/es-CN3E_zXj.js +15 -0
- package/dist/assets/{fileMentionTouchSelection-BvrNCroG.js → fileMentionTouchSelection-7RIwlpkB.js} +1 -1
- package/dist/assets/{fileQueries-DQc8EJUf.js → fileQueries-CjdBRy8y.js} +1 -1
- package/dist/assets/fr-9zZvQZD2.js +13 -0
- package/dist/assets/gitApi-yuWg9BN4.js +10 -0
- package/dist/assets/{imageSource-BlAJJUEI.js → imageSource-9vQBq3zp.js} +1 -1
- package/dist/assets/{input-8r6F_Fza.js → input-CrIvk3HZ.js} +1 -1
- package/dist/assets/insertionBoundaries-BiUCSkx-.js +1 -0
- package/dist/assets/ja-Dnjk_82N.js +15 -0
- package/dist/assets/ko-BxCEE99C.js +15 -0
- package/dist/assets/{main-CCE_4y5F.js → main-C9mIBo77.js} +2 -2
- package/dist/assets/main-DiL6w6KF.js +169 -0
- package/dist/assets/markdown-worker-bS5OgGO3.js +2 -0
- package/dist/assets/{markdownHeightCache-1Qo6y6IJ.js → markdownHeightCache-BmXVY_gc.js} +1 -1
- package/dist/assets/{markdownTheme-DOfGg-A7.js → markdownTheme-CKac3wKC.js} +1 -1
- package/dist/assets/mcpQueries-C7jknHV8.js +1 -0
- package/dist/assets/miniChat-CwtUaElU.js +2 -0
- package/dist/assets/mobile-DB-6--ws.js +2 -0
- package/dist/assets/multirun-TAsxFI8e.js +4 -0
- package/dist/assets/{persistence-Ce3AnpEr.js → persistence-56kq8Z4V.js} +2 -2
- package/dist/assets/pl-CNNsWnPM.js +15 -0
- package/dist/assets/platform-C13fMVEs.js +6 -0
- package/dist/assets/pt-BR-BZB2DJMp.js +15 -0
- package/dist/assets/{relay-image-stream-DM7atqJs.js → relay-image-stream-DrdVj99c.js} +1 -1
- package/dist/assets/renderElectronMiniChatApp-CGj0MNRU.js +2 -0
- package/dist/assets/renderMobileApp-CGMMqbsO.js +28 -0
- package/dist/assets/runtime-fetch-Fs9ZV2V8.js +1 -0
- package/dist/assets/{runtimeConfig-BMvqa5we.js → runtimeConfig-BEANkvOd.js} +1 -1
- package/dist/assets/runtimeEndpointReset-A_ZBUJFS.js +147 -0
- package/dist/assets/sessionChangeSummary-qOLrP9fw.js +2 -0
- package/dist/assets/{sessionLookup-gh-hVRIc.js → sessionLookup-34XFmP9C.js} +1 -1
- package/dist/assets/{sortable-tabs-strip-CudoSgV4.js → sortable-tabs-strip-DyEV0Heg.js} +1 -1
- package/dist/assets/src-ubCWXZhR.css +2 -0
- package/dist/assets/store-DLCiZaA6.js +15 -0
- package/dist/assets/{terminalApi-DiF6JmBP.js → terminalApi-CXaBEoa_.js} +1 -1
- package/dist/assets/textarea-BBOlRI9O.js +1 -0
- package/dist/assets/{tooltip-CQvpK-UV.js → tooltip-CPI4fr1a.js} +1 -1
- package/dist/assets/uk-rwQrxeYM.js +15 -0
- package/dist/assets/{url-_z7evzdK.js → url-DRDQXjyX.js} +1 -1
- package/dist/assets/{useAppFontEffects-Cpmpo7Wb.js → useAppFontEffects-CiDe42I5.js} +57 -43
- package/dist/assets/{useAssistantUIStore-CMutVh9B.js → useAssistantUIStore-asNG6K7n.js} +1 -1
- package/dist/assets/useDesktopWindowControlsLayout-BlizAlOt.js +1 -0
- package/dist/assets/useEffectiveDirectory-C_CouL5v.js +1 -0
- package/dist/assets/{useFontPreferences-DcbXQOkc.js → useFontPreferences-B0oUZAiB.js} +1 -1
- package/dist/assets/useMobileNavigationStore-DfPClaW-.js +414 -0
- package/dist/assets/{useRuntimeAPIs-DSLXJybW.js → useRuntimeAPIs-DwLtO0c_.js} +1 -1
- package/dist/assets/useSessionAutoCleanup-DtrfbxAp.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-Bqn4AiBL.js → useWorkerHighlightedLines-CPNYz6Wf.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-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-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 +1 -1
- package/server/index.js +327 -62
- 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/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/runtime.js +23 -5
- package/server/lib/notifications/runtime.test.js +11 -0
- package/server/lib/opencode/DOCUMENTATION.md +85 -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.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 +43 -4
- 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 +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 +252 -46
- package/server/lib/opencode/proxy.test.js +235 -2
- package/server/lib/opencode/routes.js +296 -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/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 +61 -16
- package/server/lib/session-metadata/routes.js +108 -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 +36 -0
- package/server/lib/session-metadata/session-metadata-store.js +212 -72
- 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 +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 +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/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/appThemeRegistry-COGfxTFV.js +0 -1
- package/dist/assets/collapsible-BXRd5_Hr.js +0 -1
- package/dist/assets/context-menu-jGtH6fR9.js +0 -1
- package/dist/assets/es-c52LTHHe.js +0 -15
- 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/markdown-worker-CptoICmq.js +0 -2
- 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/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/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,24 @@
|
|
|
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 { evaluateRuntimeContract } from './runtime-contract.js';
|
|
15
|
+
import {
|
|
16
|
+
buildUpgradeStatusSnapshot,
|
|
17
|
+
classifyRuntimeOwnership,
|
|
18
|
+
createUpgradeOperationState,
|
|
19
|
+
evaluateOwnedUpgradeResult,
|
|
20
|
+
resolveOwnedCacheBinaryPath,
|
|
21
|
+
} from './owned-runtime-upgrade.js';
|
|
4
22
|
import fs from 'fs';
|
|
5
23
|
import os from 'os';
|
|
6
24
|
import path from 'path';
|
|
@@ -24,8 +42,22 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
24
42
|
getOpenCodeAuthHeaders,
|
|
25
43
|
onSettingsPersisted,
|
|
26
44
|
getIsExternalOpenCode = () => false,
|
|
45
|
+
getIsSharedOpenCodeService = () => false,
|
|
46
|
+
forceResolvedOpenCodeBinary = null,
|
|
47
|
+
restartOpenCode = null,
|
|
48
|
+
waitForOpenCodeReady = null,
|
|
49
|
+
getRuntimeContract = () => null,
|
|
50
|
+
getOpenCodeServeVersion = () => null,
|
|
51
|
+
getOpenCodeCliVersion = () => null,
|
|
52
|
+
getResolvedOpenCodeBinary = () => null,
|
|
53
|
+
getResolvedOpenCodeBinarySource = () => null,
|
|
54
|
+
getActiveSessionCount = () => 0,
|
|
55
|
+
openchamberDataDir = null,
|
|
27
56
|
} = dependencies;
|
|
28
57
|
|
|
58
|
+
const upgradeOperation = createUpgradeOperationState();
|
|
59
|
+
const resolveDataDir = () => openchamberDataDir || resolveOpenChamberDataDir();
|
|
60
|
+
|
|
29
61
|
let authLibrary = null;
|
|
30
62
|
const pendingMcpAuthContextByState = new Map();
|
|
31
63
|
const PENDING_MCP_AUTH_TTL_MS = 30 * 60 * 1000;
|
|
@@ -58,10 +90,81 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
58
90
|
});
|
|
59
91
|
const health = await healthResponse.json().catch(() => null);
|
|
60
92
|
if (!healthResponse.ok) {
|
|
61
|
-
return {
|
|
93
|
+
return {
|
|
94
|
+
ok: false,
|
|
95
|
+
status: healthResponse.status,
|
|
96
|
+
error: health?.error || healthResponse.statusText,
|
|
97
|
+
authenticated: healthResponse.status === 401 || healthResponse.status === 403 ? false : null,
|
|
98
|
+
};
|
|
62
99
|
}
|
|
63
|
-
const
|
|
64
|
-
|
|
100
|
+
const gate = evaluateOpenCodeHealthBody(health);
|
|
101
|
+
const currentVersion = gate.version
|
|
102
|
+
|| (typeof health?.version === 'string' ? health.version.replace(/^v/, '') : null);
|
|
103
|
+
return { ok: gate.ok, currentVersion, healthOk: gate.ok, authenticated: true };
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const resolveOwnershipContext = async () => {
|
|
107
|
+
const isExternal = getIsExternalOpenCode() === true;
|
|
108
|
+
let binarySource = typeof getResolvedOpenCodeBinarySource === 'function'
|
|
109
|
+
? getResolvedOpenCodeBinarySource()
|
|
110
|
+
: null;
|
|
111
|
+
let binaryPath = typeof getResolvedOpenCodeBinary === 'function'
|
|
112
|
+
? getResolvedOpenCodeBinary()
|
|
113
|
+
: null;
|
|
114
|
+
try {
|
|
115
|
+
const settings = await readSettingsFromDiskMigrated();
|
|
116
|
+
const resolution = await getOpenCodeResolutionSnapshot(settings);
|
|
117
|
+
binarySource = binarySource || resolution?.source || resolution?.detectedSourceNow || null;
|
|
118
|
+
binaryPath = binaryPath || resolution?.resolved || null;
|
|
119
|
+
if (resolution?.source === 'bundled' || resolution?.detectedSourceNow === 'bundled') {
|
|
120
|
+
binarySource = 'bundled';
|
|
121
|
+
}
|
|
122
|
+
} catch {
|
|
123
|
+
// Resolution failures still allow ownership classification from runtime flags.
|
|
124
|
+
}
|
|
125
|
+
return classifyRuntimeOwnership({
|
|
126
|
+
isExternal,
|
|
127
|
+
isSharedService: getIsSharedOpenCodeService() === true,
|
|
128
|
+
binarySource,
|
|
129
|
+
binaryPath,
|
|
130
|
+
dataDir: resolveDataDir(),
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const buildLiveContract = async ({ fresh = false } = {}) => {
|
|
135
|
+
const cached = typeof getRuntimeContract === 'function' ? getRuntimeContract() : null;
|
|
136
|
+
const serveProbe = await readOpenCodeCurrentVersion().catch(() => ({ ok: false, currentVersion: null }));
|
|
137
|
+
const serveVersion = serveProbe.currentVersion
|
|
138
|
+
|| (!fresh && typeof getOpenCodeServeVersion === 'function' ? getOpenCodeServeVersion() : null);
|
|
139
|
+
const binaryPath = typeof getResolvedOpenCodeBinary === 'function' ? getResolvedOpenCodeBinary() : null;
|
|
140
|
+
const cliVersion = (typeof getOpenCodeCliVersion === 'function' ? getOpenCodeCliVersion() : null)
|
|
141
|
+
|| (binaryPath ? readOpenCode2BinaryVersion(binaryPath) : null)
|
|
142
|
+
|| null;
|
|
143
|
+
return evaluateRuntimeContract({
|
|
144
|
+
serveVersion,
|
|
145
|
+
cliVersion,
|
|
146
|
+
reachable: fresh ? serveProbe.ok === true : serveProbe.ok === true || Boolean(serveVersion) || Boolean(cached?.reachable),
|
|
147
|
+
authenticated: serveProbe.authenticated ?? (fresh ? null : cached?.authenticated) ?? null,
|
|
148
|
+
healthOk: serveProbe.healthOk ?? serveProbe.ok ?? (fresh ? false : cached?.healthOk) ?? null,
|
|
149
|
+
migrationAdmitTranscript: cached?.migrationExecutable ?? null,
|
|
150
|
+
migrationPhase: cached?.migrationPhase ?? null,
|
|
151
|
+
migrationError: cached?.migrationError ?? null,
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const buildUpgradeStatus = async () => {
|
|
156
|
+
const ownership = await resolveOwnershipContext();
|
|
157
|
+
const contract = await buildLiveContract();
|
|
158
|
+
const activeCount = typeof getActiveSessionCount === 'function' ? Number(getActiveSessionCount()) || 0 : 0;
|
|
159
|
+
return buildUpgradeStatusSnapshot({
|
|
160
|
+
ownership,
|
|
161
|
+
serveVersion: contract.serveVersion,
|
|
162
|
+
cliVersion: contract.cliVersion,
|
|
163
|
+
targetVersion: PINNED_OPENCODE2_VERSION,
|
|
164
|
+
contract,
|
|
165
|
+
operation: upgradeOperation.getState(),
|
|
166
|
+
hasActiveTasks: activeCount > 0,
|
|
167
|
+
});
|
|
65
168
|
};
|
|
66
169
|
|
|
67
170
|
const parseVersionForComparison = (value) => {
|
|
@@ -185,17 +288,17 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
185
288
|
|
|
186
289
|
app.post('/api/opencode/upgrade', async (req, res) => {
|
|
187
290
|
try {
|
|
188
|
-
|
|
189
|
-
|
|
291
|
+
const ownership = await resolveOwnershipContext();
|
|
292
|
+
if (!ownership.canUpgradeInApp) {
|
|
293
|
+
const status = ownership.ownership === 'external-serve' || ownership.ownership === 'bundled' ? 409 : 409;
|
|
294
|
+
return res.status(status).json({
|
|
190
295
|
success: false,
|
|
191
|
-
error:
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
success: false,
|
|
198
|
-
error: 'OpenCode is bundled with OpenChamber Desktop and cannot be upgraded separately.',
|
|
296
|
+
error: ownership.guidance
|
|
297
|
+
|| 'OpenChamber can only upgrade its owned OpenCode cache in-app.',
|
|
298
|
+
errorCode: ownership.reason || 'UPGRADE_NOT_MANAGED',
|
|
299
|
+
ownership: ownership.ownership,
|
|
300
|
+
management: ownership.management,
|
|
301
|
+
guidance: ownership.guidance,
|
|
199
302
|
});
|
|
200
303
|
}
|
|
201
304
|
|
|
@@ -206,23 +309,136 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
206
309
|
return res.status(400).json({
|
|
207
310
|
success: false,
|
|
208
311
|
error: 'OpenCode upgrade refuses 1.x targets. Only pinned opencode2 is allowed.',
|
|
312
|
+
errorCode: 'OPENCODE_UPGRADE_1X_REFUSED',
|
|
209
313
|
});
|
|
210
314
|
}
|
|
211
315
|
const target = resolveOpenCode2UpgradeTarget(rawTarget);
|
|
316
|
+
const confirmActive = req.body?.confirmActiveTasks === true || req.body?.force === true;
|
|
317
|
+
const activeCount = typeof getActiveSessionCount === 'function' ? Number(getActiveSessionCount()) || 0 : 0;
|
|
318
|
+
if (activeCount > 0 && !confirmActive) {
|
|
319
|
+
return res.status(409).json({
|
|
320
|
+
success: false,
|
|
321
|
+
error: 'OpenCode has active sessions. Confirm upgrade to interrupt them, or wait until idle.',
|
|
322
|
+
errorCode: 'UPGRADE_ACTIVE_TASKS',
|
|
323
|
+
hasActiveTasks: true,
|
|
324
|
+
activeSessionCount: activeCount,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const begin = upgradeOperation.begin(target);
|
|
329
|
+
if (!begin.ok) {
|
|
330
|
+
return res.status(begin.status).json(begin.body);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const expectedBinaryPath = resolveOwnedCacheBinaryPath(target, { dataDir: resolveDataDir() });
|
|
334
|
+
let installedPath = expectedBinaryPath;
|
|
335
|
+
const previousBinary = getResolvedOpenCodeBinary();
|
|
336
|
+
const previousSource = getResolvedOpenCodeBinarySource();
|
|
212
337
|
|
|
213
338
|
try {
|
|
214
|
-
|
|
215
|
-
|
|
339
|
+
upgradeOperation.setPhase('download');
|
|
340
|
+
installedPath = await installPinnedOpenCode2Cli({
|
|
341
|
+
version: target,
|
|
342
|
+
dataDir: resolveDataDir(),
|
|
343
|
+
});
|
|
344
|
+
const diskVersion = readOpenCode2BinaryVersion(installedPath);
|
|
345
|
+
if (diskVersion !== target) {
|
|
346
|
+
const error = new Error(
|
|
347
|
+
`Owned-cache binary version mismatch after install: expected ${target}, got ${diskVersion || 'unknown'}`,
|
|
348
|
+
);
|
|
349
|
+
error.code = 'UPGRADE_BINARY_VERSION_MISMATCH';
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
upgradeOperation.setPhase('pin-binary', { binaryPath: installedPath });
|
|
354
|
+
if (typeof forceResolvedOpenCodeBinary !== 'function') {
|
|
355
|
+
const error = new Error('Owned-cache upgrade requires forceResolvedOpenCodeBinary');
|
|
356
|
+
error.code = 'UPGRADE_FORCE_BINARY_UNAVAILABLE';
|
|
357
|
+
throw error;
|
|
358
|
+
}
|
|
359
|
+
// Keep target identity through restart — do not rediscover global CLI.
|
|
360
|
+
forceResolvedOpenCodeBinary(installedPath, 'installed');
|
|
361
|
+
|
|
362
|
+
upgradeOperation.setPhase('restart');
|
|
363
|
+
if (typeof restartOpenCode === 'function') {
|
|
364
|
+
await restartOpenCode(ownership.ownership === 'shared-service' ? { binaryPath: installedPath } : undefined);
|
|
365
|
+
} else if (typeof refreshOpenCodeAfterConfigChange === 'function') {
|
|
366
|
+
// Fallback: still pin binary first so restart prefers owned cache.
|
|
367
|
+
await refreshOpenCodeAfterConfigChange('OpenCode owned-cache upgrade');
|
|
368
|
+
} else {
|
|
369
|
+
const error = new Error('No OpenCode restart path is configured');
|
|
370
|
+
error.code = 'UPGRADE_RESTART_UNAVAILABLE';
|
|
371
|
+
throw error;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (typeof waitForOpenCodeReady === 'function') {
|
|
375
|
+
upgradeOperation.setPhase('wait-ready');
|
|
376
|
+
await waitForOpenCodeReady();
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
upgradeOperation.setPhase('verify');
|
|
380
|
+
// Re-pin after restart helpers that may clear resolution.
|
|
381
|
+
forceResolvedOpenCodeBinary(installedPath, 'installed');
|
|
382
|
+
const contract = await buildLiveContract({ fresh: true });
|
|
383
|
+
const verification = evaluateOwnedUpgradeResult({
|
|
384
|
+
targetVersion: target,
|
|
385
|
+
serveVersion: contract.serveVersion,
|
|
386
|
+
cliVersion: contract.cliVersion,
|
|
387
|
+
binaryPath: typeof getResolvedOpenCodeBinary === 'function'
|
|
388
|
+
? getResolvedOpenCodeBinary()
|
|
389
|
+
: installedPath,
|
|
390
|
+
expectedBinaryPath: installedPath,
|
|
391
|
+
contract,
|
|
392
|
+
});
|
|
393
|
+
if (!verification.ok) {
|
|
394
|
+
const error = new Error(verification.error);
|
|
395
|
+
error.code = verification.errorCode;
|
|
396
|
+
error.serveVersion = verification.serveVersion;
|
|
397
|
+
error.contract = verification.contract;
|
|
398
|
+
throw error;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
upgradeOperation.succeed({
|
|
402
|
+
serveVersion: verification.serveVersion,
|
|
403
|
+
binaryPath: installedPath,
|
|
404
|
+
});
|
|
405
|
+
return res.json({
|
|
406
|
+
success: true,
|
|
407
|
+
upgraded: true,
|
|
408
|
+
restarted: true,
|
|
409
|
+
version: verification.serveVersion,
|
|
410
|
+
targetVersion: target,
|
|
411
|
+
pinned: true,
|
|
412
|
+
supplySource: 'owned-cache',
|
|
413
|
+
ownership: ownership.ownership === 'shared-service' ? 'shared-service' : 'owned-cache',
|
|
414
|
+
binaryPath: installedPath,
|
|
415
|
+
contract: verification.contract,
|
|
416
|
+
operation: upgradeOperation.getState(),
|
|
417
|
+
});
|
|
418
|
+
} catch (upgradeError) {
|
|
419
|
+
if (previousBinary && typeof forceResolvedOpenCodeBinary === 'function') {
|
|
420
|
+
forceResolvedOpenCodeBinary(previousBinary, previousSource);
|
|
421
|
+
}
|
|
422
|
+
const message = upgradeError instanceof Error ? upgradeError.message : 'Failed to upgrade OpenCode';
|
|
423
|
+
const errorCode = upgradeError?.code || 'UPGRADE_FAILED';
|
|
424
|
+
upgradeOperation.fail({
|
|
425
|
+
error: message,
|
|
426
|
+
errorCode,
|
|
427
|
+
phase: upgradeOperation.getState().phase,
|
|
428
|
+
serveVersion: upgradeError?.serveVersion ?? null,
|
|
429
|
+
binaryPath: installedPath,
|
|
430
|
+
});
|
|
431
|
+
// Preserve previous owned cache on disk; only report failure.
|
|
216
432
|
return res.status(500).json({
|
|
217
433
|
success: false,
|
|
218
|
-
upgraded:
|
|
219
|
-
error:
|
|
220
|
-
|
|
221
|
-
|
|
434
|
+
upgraded: false,
|
|
435
|
+
error: message,
|
|
436
|
+
errorCode,
|
|
437
|
+
targetVersion: target,
|
|
438
|
+
operation: upgradeOperation.getState(),
|
|
439
|
+
contract: upgradeError?.contract || null,
|
|
222
440
|
});
|
|
223
441
|
}
|
|
224
|
-
|
|
225
|
-
return res.json({ success: true, restarted: true, version: target, pinned: true });
|
|
226
442
|
} catch (error) {
|
|
227
443
|
console.error('Failed to upgrade OpenCode:', error);
|
|
228
444
|
return res.status(500).json({
|
|
@@ -234,42 +450,35 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
234
450
|
|
|
235
451
|
app.get('/api/opencode/upgrade-status', async (_req, res) => {
|
|
236
452
|
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() },
|
|
453
|
+
const status = await buildUpgradeStatus();
|
|
454
|
+
return res.json(status);
|
|
455
|
+
} catch (error) {
|
|
456
|
+
return res.status(500).json({
|
|
457
|
+
available: null,
|
|
458
|
+
error: error instanceof Error ? error.message : 'Failed to check OpenCode upgrade status',
|
|
459
|
+
operation: upgradeOperation.getState(),
|
|
250
460
|
});
|
|
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;
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
app.get('/api/opencode/contract', async (_req, res) => {
|
|
465
|
+
try {
|
|
466
|
+
const contract = await buildLiveContract();
|
|
467
|
+
const ownership = await resolveOwnershipContext();
|
|
264
468
|
return res.json({
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
469
|
+
...contract,
|
|
470
|
+
ownership: ownership.ownership,
|
|
471
|
+
supplySource: ownership.supplySource,
|
|
472
|
+
canManageUpgrade: ownership.canUpgradeInApp,
|
|
473
|
+
management: ownership.management,
|
|
474
|
+
guidance: ownership.guidance,
|
|
268
475
|
});
|
|
269
476
|
} catch (error) {
|
|
270
477
|
return res.status(500).json({
|
|
271
|
-
|
|
272
|
-
|
|
478
|
+
schemaVersion: 1,
|
|
479
|
+
phase: 'unknown',
|
|
480
|
+
executionAllowed: false,
|
|
481
|
+
error: error instanceof Error ? error.message : 'Failed to evaluate OpenCode runtime contract',
|
|
273
482
|
});
|
|
274
483
|
}
|
|
275
484
|
});
|
|
@@ -283,22 +492,45 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
283
492
|
});
|
|
284
493
|
const health = await healthResponse.json().catch(() => null);
|
|
285
494
|
if (!healthResponse.ok) {
|
|
495
|
+
const contract = evaluateRuntimeContract({
|
|
496
|
+
reachable: false,
|
|
497
|
+
authenticated: healthResponse.status === 401 || healthResponse.status === 403 ? false : null,
|
|
498
|
+
healthOk: false,
|
|
499
|
+
});
|
|
286
500
|
return res.status(healthResponse.status).json({
|
|
287
501
|
healthy: false,
|
|
288
502
|
error: health?.error || healthResponse.statusText || 'OpenCode health check failed',
|
|
503
|
+
contract,
|
|
289
504
|
});
|
|
290
505
|
}
|
|
291
|
-
|
|
506
|
+
// Reuse lifecycle/sidecar gate: official 2.x ServerInfo omits `healthy`.
|
|
507
|
+
const gate = evaluateOpenCodeHealthBody(health);
|
|
508
|
+
const contract = await buildLiveContract().catch(() => evaluateRuntimeContract({
|
|
509
|
+
serveVersion: gate.version,
|
|
510
|
+
reachable: gate.ok,
|
|
511
|
+
authenticated: true,
|
|
512
|
+
healthOk: gate.ok,
|
|
513
|
+
}));
|
|
514
|
+
return res.json({
|
|
515
|
+
healthy: gate.ok,
|
|
516
|
+
version: gate.version,
|
|
517
|
+
// Healthy is reachability/version shape only — not full execution semantics.
|
|
518
|
+
executionAllowed: contract.executionAllowed === true,
|
|
519
|
+
protocolCompatible: contract.protocolCompatible === true,
|
|
520
|
+
contract,
|
|
521
|
+
});
|
|
292
522
|
} catch (error) {
|
|
293
523
|
return res.status(503).json({
|
|
294
524
|
healthy: false,
|
|
295
525
|
error: error instanceof Error ? error.message : 'OpenCode health check failed',
|
|
526
|
+
contract: evaluateRuntimeContract({ reachable: false, healthOk: false }),
|
|
296
527
|
});
|
|
297
528
|
}
|
|
298
529
|
});
|
|
299
530
|
|
|
300
531
|
app.get('/api/opencode/version', async (_req, res) => {
|
|
301
532
|
try {
|
|
533
|
+
const contract = await buildLiveContract();
|
|
302
534
|
const healthResponse = await fetch(buildOpenCodeUrl('/api/info', ''), {
|
|
303
535
|
method: 'GET',
|
|
304
536
|
headers: { Accept: 'application/json', ...getOpenCodeAuthHeaders() },
|
|
@@ -307,11 +539,20 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
307
539
|
if (!healthResponse.ok) {
|
|
308
540
|
return res.status(healthResponse.status).json({
|
|
309
541
|
version: null,
|
|
542
|
+
serveVersion: null,
|
|
543
|
+
cliVersion: contract.cliVersion,
|
|
310
544
|
error: health?.error || healthResponse.statusText || 'Failed to read OpenCode version',
|
|
545
|
+
contract,
|
|
311
546
|
});
|
|
312
547
|
}
|
|
313
548
|
const version = typeof health?.version === 'string' ? health.version.replace(/^v/, '') : null;
|
|
314
|
-
return res.json({
|
|
549
|
+
return res.json({
|
|
550
|
+
version,
|
|
551
|
+
serveVersion: version,
|
|
552
|
+
cliVersion: contract.cliVersion,
|
|
553
|
+
versionMismatch: Boolean(version && contract.cliVersion && version !== contract.cliVersion),
|
|
554
|
+
contract,
|
|
555
|
+
});
|
|
315
556
|
} catch (error) {
|
|
316
557
|
return res.status(500).json({
|
|
317
558
|
version: null,
|
|
@@ -599,13 +840,6 @@ export const registerOpenCodeRoutes = (app, dependencies) => {
|
|
|
599
840
|
|
|
600
841
|
await fs.promises.writeFile(AGENTS_MD_PATH, content, 'utf8');
|
|
601
842
|
|
|
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
843
|
return res.json({ success: true });
|
|
610
844
|
} catch (error) {
|
|
611
845
|
console.error('Failed to write AGENTS.md:', error);
|