@openchambery/web 1.19.0-beta.3 → 1.19.0-beta.31
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/dist/assets/AgentAvatar-Dn37YqCC.js +1 -0
- package/dist/assets/AssistantView-H_Egesn6.js +1 -0
- package/dist/assets/{ChatContainer-CanA9Dye.js → ChatContainer-BgVAywjE.js} +39 -41
- package/dist/assets/ContextPanel-BLDsUzmw.js +288 -0
- package/dist/assets/{DiagramView-etLVThQw.js → DiagramView-b7WE5RTM.js} +1 -1
- package/dist/assets/{FadeInOnReveal-By2F9vcI.js → FadeInOnReveal-BpIMrqet.js} +1 -1
- package/dist/assets/{Icon-DpjYnXxn.js → Icon-Bs6GJIoO.js} +1 -1
- package/dist/assets/{MarkdownRendererImpl-BgvKQ5fZ.js → MarkdownRendererImpl-BqjVnlwZ.js} +1 -1
- package/dist/assets/{MobileDetailNavigation-BU_Ylck7.js → MobileDetailNavigation-CBfGRVD6.js} +1 -1
- package/dist/assets/{MobileShareBridge-UeR74BaG.js → MobileShareBridge-C4uORNn-.js} +2 -2
- package/dist/assets/MobileSurface-Cv5whd_e.js +2 -0
- package/dist/assets/{MultiRunWindow-KEhvo6JL.js → MultiRunWindow-Dn6aBoOY.js} +1 -1
- package/dist/assets/{OnboardingScreen-BKmuT7AL.js → OnboardingScreen-DRd1uYCr.js} +1 -1
- package/dist/assets/OverlayScrollbar-VZKKu-cu.js +2 -0
- package/dist/assets/SettingsView-DEKWoT4q.js +25 -0
- package/dist/assets/{SettingsWindow-DlEl2agU.js → SettingsWindow-bH2TdtcQ.js} +1 -1
- package/dist/assets/{TerminalView-4ji7f8PT.js → TerminalView-CbZo3MS_.js} +1 -1
- package/dist/assets/{ToolOutputDialog-B7vUFIz4.js → ToolOutputDialog-B_cdYsoL.js} +4 -4
- package/dist/assets/appThemeRegistry-Draz0Hww.js +2 -0
- package/dist/assets/{button-C7OXr4ae.js → button-DfF088a8.js} +1 -1
- package/dist/assets/{clipboard-DWuULPzo.js → clipboard-C7zcAKyC.js} +1 -1
- package/dist/assets/{collapsible-DaEya6b6.js → collapsible-CVL-5iEB.js} +1 -1
- package/dist/assets/{desktopHosts-Txp4xOVQ.js → desktopHosts-Dzx3McaD.js} +1 -1
- package/dist/assets/{desktopRelayRestore-C_FSEHKM.js → desktopRelayRestore-B9S0Rp5s.js} +1 -1
- package/dist/assets/dialog-BUQDNX62.js +1 -0
- package/dist/assets/{es-BX0Vm3Ac.js → es-CcbKrwi9.js} +2 -2
- package/dist/assets/{fileQueries-B_fTkH6s.js → fileQueries-_VUJM8AE.js} +1 -1
- package/dist/assets/{fr-CuPzXTYx.js → fr-D1YIDHP6.js} +3 -3
- package/dist/assets/{gitApi-BtRkoe9k.js → gitApi-PJj45MQT.js} +3 -3
- package/dist/assets/{input-BzYA603C.js → input-Ca2tUhgN.js} +1 -1
- package/dist/assets/insertionBoundaries-0B0gDxuq.js +4 -0
- package/dist/assets/{ja-DGtzjrFO.js → ja-xE7L_-ZU.js} +3 -3
- package/dist/assets/{ko-DZ9Di0je.js → ko-QUUzIgbd.js} +3 -3
- package/dist/assets/main-B-4uKWju.js +29 -0
- package/dist/assets/{main-CKEPlKbO.js → main-CtvSltoE.js} +2 -2
- package/dist/assets/{markdown-worker-W06-MhF5.js → markdown-worker-9Sn2jsDp.js} +1 -1
- package/dist/assets/{markdownTheme-B89dbj3N.js → markdownTheme-DidS-jC5.js} +1 -1
- package/dist/assets/{miniChat-B275LhR6.js → miniChat-DmpbJXFT.js} +2 -2
- package/dist/assets/mobile-CYGC7Ts7.js +2 -0
- package/dist/assets/multirun-Dhf2co1c.js +4 -0
- package/dist/assets/{persistence-6sclr7B6.js → persistence-aCOlo6ew.js} +2 -2
- package/dist/assets/pl-BQfz-_HE.js +15 -0
- package/dist/assets/platform-ulFAVx1H.js +2 -0
- package/dist/assets/projectMeta-CZPx7O1l.js +3 -0
- package/dist/assets/{pt-BR-Brf4RMsw.js → pt-BR-DaY3UW5q.js} +2 -2
- package/dist/assets/radio-BEdeeUAs.js +1 -0
- package/dist/assets/{renderElectronMiniChatApp-DrHB3d6Y.js → renderElectronMiniChatApp-CCyKaR_W.js} +2 -2
- package/dist/assets/renderMobileApp-CGV671aB.js +23 -0
- package/dist/assets/{runtimeConfig-BdMDmf4j.js → runtimeConfig-BlSyKINS.js} +1 -1
- package/dist/assets/runtimeEndpointReset-D8tkrKdU.js +4 -0
- package/dist/assets/{shikiHighlight-Gt4pZGSV.js → shikiHighlight-C7ioXFMp.js} +1 -1
- package/dist/assets/{sortable-tabs-strip-nLsPC06f.js → sortable-tabs-strip-COl2MAH7.js} +1 -1
- package/dist/assets/src-_LXgwcNH.css +2 -0
- package/dist/assets/{store-DQY8Fkb0.js → store-upwbPNfx.js} +4 -4
- package/dist/assets/{terminalApi-BpPeXWIu.js → terminalApi-HsIEks5U.js} +1 -1
- package/dist/assets/{tooltip-D_orJMYd.js → tooltip-GC3dg3gO.js} +1 -1
- package/dist/assets/{uk-C-wmaPTi.js → uk-yWcUag_v.js} +2 -2
- package/dist/assets/{url-BsaBG5-1.js → url-BQHM4bC4.js} +1 -1
- package/dist/assets/{useAppFontEffects-CbQSJicp.js → useAppFontEffects-DAoSoNat.js} +5 -5
- package/dist/assets/{useAssistantUIStore-BHsHXCKE.js → useAssistantUIStore-DxZsjSPQ.js} +1 -1
- package/dist/assets/{useDesktopWindowControlsLayout-BI_ZDdNF.js → useDesktopWindowControlsLayout-DEXAtbIH.js} +1 -1
- package/dist/assets/useEffectiveDirectory-D6GPWYrS.js +1 -0
- package/dist/assets/{useFontPreferences-ckzpXQaJ.js → useFontPreferences-DaFspdDd.js} +1 -1
- package/dist/assets/{useMobileNavigationStore-CGSKnVbj.js → useMobileNavigationStore-CEH3LoLB.js} +19 -19
- package/dist/assets/useSessionAutoCleanup-Bt041qaJ.js +1 -0
- package/dist/assets/{useUIStore-DzwCfRqr.js → useUIStore-Wyu09VUF.js} +1 -1
- package/dist/assets/{useWorkerHighlightedLines-BSyHhMx_.js → useWorkerHighlightedLines-B6jVogSy.js} +1 -1
- package/dist/assets/{utils-B1EK5zKa.js → utils-CJdWZupK.js} +1 -1
- package/dist/assets/{zh-CN-DueRrIql.js → zh-CN-jktTX6F0.js} +2 -2
- package/dist/assets/zh-TW-DS3LNe1V.js +15 -0
- package/dist/index.html +9 -9
- package/dist/mini-chat.html +9 -9
- package/dist/mobile.html +9 -9
- package/package.json +1 -1
- package/server/index.js +4 -14
- package/server/lib/config-sync/DOCUMENTATION.md +6 -7
- package/server/lib/config-sync/engine.js +0 -8
- package/server/lib/config-sync/index.js +0 -7
- package/server/lib/config-sync/receiver.js +0 -35
- package/server/lib/config-sync/routes.js +8 -41
- package/server/lib/config-sync/routes.test.js +1 -38
- package/server/lib/opencode/openchamber-routes.js +1 -7
- package/server/lib/opencode/settings-helpers.js +0 -3
- package/server/lib/opencode/shutdown-runtime.js +0 -2
- package/server/lib/session-goal/DOCUMENTATION.md +3 -3
- package/server/lib/session-goal/runtime.js +3 -3
- package/server/lib/session-title/DOCUMENTATION.md +1 -2
- package/dist/assets/AgentAvatar-DDcjamcJ.js +0 -1
- package/dist/assets/AssistantView-BSUBxkz8.js +0 -1
- package/dist/assets/ContextPanel-D-zm9idy.js +0 -288
- package/dist/assets/MobileSurface-BaJK1TC4.js +0 -2
- package/dist/assets/OverlayScrollbar-Ch3J6ASR.js +0 -2
- package/dist/assets/SettingsView-CC83BH32.js +0 -25
- package/dist/assets/appThemeRegistry-BWAStv0M.js +0 -2
- package/dist/assets/dialog-DPS0W9eS.js +0 -1
- package/dist/assets/insertionBoundaries-0QdvxqZx.js +0 -1
- package/dist/assets/main-C2gFG9wD.js +0 -29
- package/dist/assets/mobile-B4O-Iia5.js +0 -2
- package/dist/assets/multirun-CzvmS64T.js +0 -4
- package/dist/assets/pl-BuCO3qb1.js +0 -15
- package/dist/assets/platform-CbeLpKPk.js +0 -2
- package/dist/assets/projectMeta-B4BZoe_0.js +0 -3
- package/dist/assets/radio-BIFaTwYH.js +0 -1
- package/dist/assets/renderMobileApp-BB6JMX4q.js +0 -23
- package/dist/assets/runtimeEndpointReset-CqowcjzM.js +0 -4
- package/dist/assets/src-RGaBtbGz.css +0 -2
- package/dist/assets/useEffectiveDirectory-DRp5lrMh.js +0 -1
- package/dist/assets/useSessionAutoCleanup-C0sPQc3j.js +0 -1
- package/dist/assets/zh-TW-6875X80V.js +0 -15
- package/server/lib/config-sync/credential-auth.js +0 -39
- package/server/lib/session-assist/DOCUMENTATION.md +0 -62
- package/server/lib/session-assist/runtime.js +0 -376
- package/server/lib/session-assist/runtime.test.js +0 -114
package/dist/index.html
CHANGED
|
@@ -552,25 +552,25 @@
|
|
|
552
552
|
opacity: 0.72;
|
|
553
553
|
}
|
|
554
554
|
</style>
|
|
555
|
-
<script type="module" crossorigin src="/assets/main-
|
|
555
|
+
<script type="module" crossorigin src="/assets/main-CtvSltoE.js"></script>
|
|
556
556
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
|
|
557
557
|
<link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CnHfUmDN.js">
|
|
558
558
|
<link rel="modulepreload" crossorigin href="/assets/vendor-zustand-B4dlGEM2.js">
|
|
559
|
-
<link rel="modulepreload" crossorigin href="/assets/useUIStore-
|
|
559
|
+
<link rel="modulepreload" crossorigin href="/assets/useUIStore-Wyu09VUF.js">
|
|
560
560
|
<link rel="modulepreload" crossorigin href="/assets/vendor-pathe-vBmvQE8f.js">
|
|
561
561
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-DLPElpoQ.js">
|
|
562
562
|
<link rel="modulepreload" crossorigin href="/assets/vendor-tanstack-query-core-BWz0ose6.js">
|
|
563
|
-
<link rel="modulepreload" crossorigin href="/assets/persistence-
|
|
564
|
-
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-
|
|
565
|
-
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-
|
|
563
|
+
<link rel="modulepreload" crossorigin href="/assets/persistence-aCOlo6ew.js">
|
|
564
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-Dzx3McaD.js">
|
|
565
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-B9S0Rp5s.js">
|
|
566
566
|
<link rel="modulepreload" crossorigin href="/assets/vendor-opencode-sdk-C07HQypa.js">
|
|
567
567
|
<link rel="modulepreload" crossorigin href="/assets/vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js">
|
|
568
|
-
<link rel="modulepreload" crossorigin href="/assets/platform-
|
|
569
|
-
<link rel="modulepreload" crossorigin href="/assets/terminalApi-
|
|
568
|
+
<link rel="modulepreload" crossorigin href="/assets/platform-ulFAVx1H.js">
|
|
569
|
+
<link rel="modulepreload" crossorigin href="/assets/terminalApi-HsIEks5U.js">
|
|
570
570
|
<link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
|
|
571
571
|
<link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
|
|
572
|
-
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-
|
|
573
|
-
<link rel="stylesheet" crossorigin href="/assets/src-
|
|
572
|
+
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-BlSyKINS.js">
|
|
573
|
+
<link rel="stylesheet" crossorigin href="/assets/src-_LXgwcNH.css">
|
|
574
574
|
</head>
|
|
575
575
|
<body class="h-full bg-background text-foreground">
|
|
576
576
|
<!-- Keep the startup layer outside #root. React replaces every child of
|
package/dist/mini-chat.html
CHANGED
|
@@ -74,25 +74,25 @@
|
|
|
74
74
|
}
|
|
75
75
|
</style>
|
|
76
76
|
|
|
77
|
-
<script type="module" crossorigin src="/assets/miniChat-
|
|
77
|
+
<script type="module" crossorigin src="/assets/miniChat-DmpbJXFT.js"></script>
|
|
78
78
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
|
|
79
79
|
<link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CnHfUmDN.js">
|
|
80
80
|
<link rel="modulepreload" crossorigin href="/assets/vendor-zustand-B4dlGEM2.js">
|
|
81
|
-
<link rel="modulepreload" crossorigin href="/assets/useUIStore-
|
|
81
|
+
<link rel="modulepreload" crossorigin href="/assets/useUIStore-Wyu09VUF.js">
|
|
82
82
|
<link rel="modulepreload" crossorigin href="/assets/vendor-pathe-vBmvQE8f.js">
|
|
83
83
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-DLPElpoQ.js">
|
|
84
84
|
<link rel="modulepreload" crossorigin href="/assets/vendor-tanstack-query-core-BWz0ose6.js">
|
|
85
|
-
<link rel="modulepreload" crossorigin href="/assets/persistence-
|
|
86
|
-
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-
|
|
87
|
-
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-
|
|
85
|
+
<link rel="modulepreload" crossorigin href="/assets/persistence-aCOlo6ew.js">
|
|
86
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-Dzx3McaD.js">
|
|
87
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-B9S0Rp5s.js">
|
|
88
88
|
<link rel="modulepreload" crossorigin href="/assets/vendor-opencode-sdk-C07HQypa.js">
|
|
89
89
|
<link rel="modulepreload" crossorigin href="/assets/vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js">
|
|
90
|
-
<link rel="modulepreload" crossorigin href="/assets/platform-
|
|
91
|
-
<link rel="modulepreload" crossorigin href="/assets/terminalApi-
|
|
90
|
+
<link rel="modulepreload" crossorigin href="/assets/platform-ulFAVx1H.js">
|
|
91
|
+
<link rel="modulepreload" crossorigin href="/assets/terminalApi-HsIEks5U.js">
|
|
92
92
|
<link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
|
|
93
93
|
<link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
|
|
94
|
-
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-
|
|
95
|
-
<link rel="stylesheet" crossorigin href="/assets/src-
|
|
94
|
+
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-BlSyKINS.js">
|
|
95
|
+
<link rel="stylesheet" crossorigin href="/assets/src-_LXgwcNH.css">
|
|
96
96
|
</head>
|
|
97
97
|
<body class="h-full bg-background text-foreground">
|
|
98
98
|
<div id="root" class="h-full">
|
package/dist/mobile.html
CHANGED
|
@@ -63,25 +63,25 @@
|
|
|
63
63
|
})();
|
|
64
64
|
</script>
|
|
65
65
|
|
|
66
|
-
<script type="module" crossorigin src="/assets/mobile-
|
|
66
|
+
<script type="module" crossorigin src="/assets/mobile-CYGC7Ts7.js"></script>
|
|
67
67
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
|
|
68
68
|
<link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CnHfUmDN.js">
|
|
69
69
|
<link rel="modulepreload" crossorigin href="/assets/vendor-zustand-B4dlGEM2.js">
|
|
70
|
-
<link rel="modulepreload" crossorigin href="/assets/useUIStore-
|
|
70
|
+
<link rel="modulepreload" crossorigin href="/assets/useUIStore-Wyu09VUF.js">
|
|
71
71
|
<link rel="modulepreload" crossorigin href="/assets/vendor-pathe-vBmvQE8f.js">
|
|
72
72
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-DLPElpoQ.js">
|
|
73
73
|
<link rel="modulepreload" crossorigin href="/assets/vendor-tanstack-query-core-BWz0ose6.js">
|
|
74
|
-
<link rel="modulepreload" crossorigin href="/assets/persistence-
|
|
75
|
-
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-
|
|
76
|
-
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-
|
|
74
|
+
<link rel="modulepreload" crossorigin href="/assets/persistence-aCOlo6ew.js">
|
|
75
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-Dzx3McaD.js">
|
|
76
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-B9S0Rp5s.js">
|
|
77
77
|
<link rel="modulepreload" crossorigin href="/assets/vendor-opencode-sdk-C07HQypa.js">
|
|
78
78
|
<link rel="modulepreload" crossorigin href="/assets/vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js">
|
|
79
|
-
<link rel="modulepreload" crossorigin href="/assets/platform-
|
|
80
|
-
<link rel="modulepreload" crossorigin href="/assets/terminalApi-
|
|
79
|
+
<link rel="modulepreload" crossorigin href="/assets/platform-ulFAVx1H.js">
|
|
80
|
+
<link rel="modulepreload" crossorigin href="/assets/terminalApi-HsIEks5U.js">
|
|
81
81
|
<link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
|
|
82
82
|
<link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
|
|
83
|
-
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-
|
|
84
|
-
<link rel="stylesheet" crossorigin href="/assets/src-
|
|
83
|
+
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-BlSyKINS.js">
|
|
84
|
+
<link rel="stylesheet" crossorigin href="/assets/src-_LXgwcNH.css">
|
|
85
85
|
</head>
|
|
86
86
|
<body class="h-full bg-background text-foreground">
|
|
87
87
|
<div id="root" class="h-full"></div>
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -58,7 +58,6 @@ import { createOpenCodeResolutionRuntime } from './lib/opencode/opencode-resolut
|
|
|
58
58
|
import { createBootstrapRuntime } from './lib/opencode/bootstrap-runtime.js';
|
|
59
59
|
import { createSessionRuntime } from './lib/opencode/session-runtime.js';
|
|
60
60
|
import { createOpenCodeWatcherRuntime } from './lib/opencode/watcher.js';
|
|
61
|
-
import { createSessionAssistRuntime } from './lib/session-assist/runtime.js';
|
|
62
61
|
import { createSessionTitleRuntime } from './lib/session-title/runtime.js';
|
|
63
62
|
import { createSessionIndexService } from './lib/session-index/service.js';
|
|
64
63
|
import { createSessionIndexSyncRuntime } from './lib/session-index/sync-runtime.js';
|
|
@@ -685,12 +684,6 @@ const getSmallModelService = async () => {
|
|
|
685
684
|
return smallModelServiceInstance;
|
|
686
685
|
};
|
|
687
686
|
|
|
688
|
-
const sessionAssistRuntime = createSessionAssistRuntime({
|
|
689
|
-
buildOpenCodeUrl,
|
|
690
|
-
getOpenCodeAuthHeaders,
|
|
691
|
-
getSmallModelService,
|
|
692
|
-
});
|
|
693
|
-
|
|
694
687
|
const sessionTitleRuntime = createSessionTitleRuntime({
|
|
695
688
|
buildOpenCodeUrl,
|
|
696
689
|
getOpenCodeAuthHeaders,
|
|
@@ -769,9 +762,8 @@ const openCodeWatcherRuntime = createOpenCodeWatcherRuntime({
|
|
|
769
762
|
},
|
|
770
763
|
});
|
|
771
764
|
|
|
772
|
-
// Session-
|
|
765
|
+
// Session-title and session-goal subscribe to the hub directly: they need the
|
|
773
766
|
// envelope's directory to route their own OpenCode calls to the right instance.
|
|
774
|
-
console.log('[session-assist] listening for session events');
|
|
775
767
|
console.log('[session-title] listening for session events');
|
|
776
768
|
console.log('[session-goal] listening for session events');
|
|
777
769
|
globalMessageStreamHub.subscribeEvent((event) => {
|
|
@@ -781,7 +773,6 @@ globalMessageStreamHub.subscribeEvent((event) => {
|
|
|
781
773
|
const directory = typeof event?.directory === 'string' && event.directory && event.directory !== 'global'
|
|
782
774
|
? event.directory
|
|
783
775
|
: '';
|
|
784
|
-
sessionAssistRuntime.processPayload(payload, directory);
|
|
785
776
|
sessionTitleRuntime.processPayload(payload, directory);
|
|
786
777
|
sessionGoalRuntime.processPayload(payload, directory);
|
|
787
778
|
});
|
|
@@ -1065,9 +1056,9 @@ const completeOpenCodeStartup = () => {
|
|
|
1065
1056
|
if (openCodeLifecycleState.openCodeProcess && !openCodeLifecycleState.isExternalOpenCode) {
|
|
1066
1057
|
startHealthMonitoring();
|
|
1067
1058
|
}
|
|
1068
|
-
// The global watcher used to start only for desktop notifications;
|
|
1069
|
-
// session-
|
|
1070
|
-
//
|
|
1059
|
+
// The global watcher used to start only for desktop notifications; session-title
|
|
1060
|
+
// and session-goal also ride its event hub, so it now starts unconditionally
|
|
1061
|
+
// once OpenCode is up.
|
|
1071
1062
|
void ensureGlobalWatcherStarted().catch((error) => {
|
|
1072
1063
|
console.warn(`Global event watcher startup failed: ${error?.message || error}`);
|
|
1073
1064
|
});
|
|
@@ -1099,7 +1090,6 @@ const gracefulShutdownRuntime = createGracefulShutdownRuntime({
|
|
|
1099
1090
|
},
|
|
1100
1091
|
syncToHmrState,
|
|
1101
1092
|
openCodeWatcherRuntime,
|
|
1102
|
-
sessionAssistRuntime,
|
|
1103
1093
|
sessionTitleRuntime,
|
|
1104
1094
|
sessionGoalRuntime,
|
|
1105
1095
|
sessionRuntime,
|
|
@@ -17,7 +17,6 @@ Own the direction-agnostic OpenCode config sync contract: allowlist planning on
|
|
|
17
17
|
| `local-backup.js` | Local (pull destination) generational backup + tar extract |
|
|
18
18
|
| `tar.js` | `collectLocalTarBuffer` (buffered) |
|
|
19
19
|
| `engine.js` | `applyConfigSyncPlan` orchestration for **push** (prepare → putTar* → finalize) |
|
|
20
|
-
| `credential-auth.js` | Credential grant enforcement helpers |
|
|
21
20
|
| `target-id.js` | `ssh:<instanceId>` namespace helper |
|
|
22
21
|
|
|
23
22
|
## Contract shape
|
|
@@ -28,6 +27,7 @@ Own the direction-agnostic OpenCode config sync contract: allowlist planning on
|
|
|
28
27
|
- **Plan** (source-computed): `{ direction: 'push' | 'pull', syncRunId?, sourceTargetId?, targetId?, files, directories, agentsRoot, authFile, deletes, totalBytes, selections? }`
|
|
29
28
|
- **Selections**: `{ fileGroups: boolean[], singleFiles: boolean[], directories: boolean[], agentsRoot: boolean, authFile: boolean }`
|
|
30
29
|
- Preview and apply must share one selections snapshot so the confirmed scope cannot drift.
|
|
30
|
+
- `authFile` defaults unchecked like an opt-in ordinary selection; once checked it syncs the same way as other allowlisted files (no extra grant).
|
|
31
31
|
|
|
32
32
|
## Direction flow
|
|
33
33
|
|
|
@@ -45,7 +45,7 @@ Switching direction in the wizard **must** discard the previous preview and re-c
|
|
|
45
45
|
- Prepare (remote or local) writes generational backups under `<backupRoot>/<syncRunId>/` and prunes older than `OPENCODE_CONFIG_SYNC_BACKUP_GENERATIONS`. Failed runs keep their scene until pruned.
|
|
46
46
|
- Finalize confirms the run's backup directory exists.
|
|
47
47
|
- Run records (Electron `sync-run-store`) persist `direction` alongside `syncRunId` / summary; they are not stored in `settings.json`.
|
|
48
|
-
-
|
|
48
|
+
- **`auth.json` sync:** treated like any other selected allowlist item. Default selection leaves it unchecked; when selected, push/pull transfer it under the dedicated auth backup directory with no separate credential grant.
|
|
49
49
|
|
|
50
50
|
## HTTP receive protocol (direct / later relay)
|
|
51
51
|
|
|
@@ -53,18 +53,17 @@ Routes under `/api/openchamber/config-sync/*` (global `/api` auth gate: session
|
|
|
53
53
|
|
|
54
54
|
| Method | Path | Role |
|
|
55
55
|
|--------|------|------|
|
|
56
|
-
| POST | `/probe` | Inventory + existence vs plan
|
|
56
|
+
| POST | `/probe` | Inventory + existence vs plan |
|
|
57
57
|
| POST | `/prepare` | Generational local backup + deletes; one inflight `syncRunId` |
|
|
58
58
|
| PUT | `/put/:kind?syncRunId=` | Stream tar.gz (`config` \| `agents` \| `auth`) |
|
|
59
59
|
| GET | `/download/:kind` | Stream tar.gz for pull source |
|
|
60
60
|
| POST | `/finalize` | Confirm backup generation + success receipt |
|
|
61
61
|
| POST | `/abort` | Clear inflight |
|
|
62
|
-
| GET/PUT | `/credential-auth` | Host inbound credential grant (`configSyncInboundCredentialAuthorized`) |
|
|
63
62
|
|
|
64
|
-
`auth` put/download
|
|
63
|
+
`auth` put/download follows the same selection/plan rules as other kinds. Concurrent prepare → `sync_in_progress`.
|
|
65
64
|
|
|
66
65
|
## Composition
|
|
67
66
|
|
|
68
67
|
- Electron SSH: `TargetExecutor` push + inventory/tar pull.
|
|
69
|
-
- Electron direct hosts: `direct-config-sync.mjs` calls these HTTP routes
|
|
70
|
-
- **Relay hosts (ticket 06):** UI opens an E2EE tunnel (`packages/ui/src/lib/relay/relay-config-sync.ts`) and calls the same HTTP routes via `tunnel.fetch`. Target id is `relay:<serverId>` (signing-key fingerprint). Preview/apply refresh candidates and refuse on `serverId` mismatch (`relay_identity_changed`) with no fallback identity.
|
|
68
|
+
- Electron direct hosts: `direct-config-sync.mjs` calls these HTTP routes.
|
|
69
|
+
- **Relay hosts (ticket 06):** UI opens an E2EE tunnel (`packages/ui/src/lib/relay/relay-config-sync.ts`) and calls the same HTTP routes via `tunnel.fetch`. Target id is `relay:<serverId>` (signing-key fingerprint). Preview/apply refresh candidates and refuse on `serverId` mismatch (`relay_identity_changed`) with no fallback identity. Auth remains the global `/api` bearer gate; selected `auth.json` transfers without a separate credential grant.
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
|
|
3
3
|
import { assertPlanDirection } from './contract.js';
|
|
4
|
-
import { assertCredentialSyncAuthorized } from './credential-auth.js';
|
|
5
4
|
import { collectLocalTarBuffer } from './tar.js';
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Run a source-side plan against a TargetExecutor (probe → prepare → putTar* → finalize).
|
|
9
8
|
* Direction-agnostic orchestration; ticket 02 only drives push from a local home snapshot.
|
|
10
|
-
* Credential-bearing plans require an explicit per-target grant (ticket 03).
|
|
11
9
|
*
|
|
12
10
|
* @param {{
|
|
13
11
|
* plan: object,
|
|
@@ -15,7 +13,6 @@ import { collectLocalTarBuffer } from './tar.js';
|
|
|
15
13
|
* syncRunId: string,
|
|
16
14
|
* sourceHomedir: string,
|
|
17
15
|
* collectTar?: typeof collectLocalTarBuffer,
|
|
18
|
-
* credentialSyncAuthorized?: boolean,
|
|
19
16
|
* }} args
|
|
20
17
|
*/
|
|
21
18
|
export const applyConfigSyncPlan = async ({
|
|
@@ -24,13 +21,8 @@ export const applyConfigSyncPlan = async ({
|
|
|
24
21
|
syncRunId,
|
|
25
22
|
sourceHomedir,
|
|
26
23
|
collectTar = collectLocalTarBuffer,
|
|
27
|
-
credentialSyncAuthorized = false,
|
|
28
24
|
}) => {
|
|
29
25
|
assertPlanDirection(plan);
|
|
30
|
-
assertCredentialSyncAuthorized(plan, {
|
|
31
|
-
targetId: plan?.targetId || 'unknown',
|
|
32
|
-
authorized: credentialSyncAuthorized === true,
|
|
33
|
-
});
|
|
34
26
|
const home = String(sourceHomedir || '');
|
|
35
27
|
const configDir = path.join(home, '.config', 'opencode');
|
|
36
28
|
const tarEntries = [
|
|
@@ -48,13 +48,6 @@ export {
|
|
|
48
48
|
} from './scripts.js';
|
|
49
49
|
export { collectLocalTarBuffer } from './tar.js';
|
|
50
50
|
export { applyConfigSyncPlan, probePathsForPlan } from './engine.js';
|
|
51
|
-
export {
|
|
52
|
-
CREDENTIAL_SYNC_UNAUTHORIZED_CODE,
|
|
53
|
-
CREDENTIAL_SYNC_GRANT_CHANNEL_INSTANCE_SETTINGS,
|
|
54
|
-
CredentialSyncUnauthorizedError,
|
|
55
|
-
planIncludesCredentials,
|
|
56
|
-
assertCredentialSyncAuthorized,
|
|
57
|
-
} from './credential-auth.js';
|
|
58
51
|
export {
|
|
59
52
|
buildDefaultSyncSelections,
|
|
60
53
|
normalizeSyncSelections,
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
OPENCODE_CONFIG_SYNC_MAX_BYTES,
|
|
12
12
|
OPENCODE_CONFIG_SYNC_MAX_FILES,
|
|
13
13
|
} from './constants.js';
|
|
14
|
-
import { CREDENTIAL_SYNC_UNAUTHORIZED_CODE } from './credential-auth.js';
|
|
15
14
|
import {
|
|
16
15
|
extractTarGzBuffer,
|
|
17
16
|
finalizeLocalSyncDestination,
|
|
@@ -20,8 +19,6 @@ import {
|
|
|
20
19
|
import { walkAllowlistDirectory } from './plan.js';
|
|
21
20
|
import { sanitizeSyncRunIdForPath } from './scripts.js';
|
|
22
21
|
|
|
23
|
-
const INBOUND_CREDENTIAL_SETTINGS_KEY = 'configSyncInboundCredentialAuthorized';
|
|
24
|
-
|
|
25
22
|
/**
|
|
26
23
|
* In-process receiver for HTTP config-sync (direct/relay hosts).
|
|
27
24
|
* One inflight sync at a time; backups use the same local generational helpers as pull.
|
|
@@ -29,8 +26,6 @@ const INBOUND_CREDENTIAL_SETTINGS_KEY = 'configSyncInboundCredentialAuthorized';
|
|
|
29
26
|
export const createConfigSyncReceiver = (deps = {}) => {
|
|
30
27
|
const {
|
|
31
28
|
homedir = () => os.homedir(),
|
|
32
|
-
readSettings = async () => ({}),
|
|
33
|
-
writeSettingsPatch = async () => {},
|
|
34
29
|
} = deps;
|
|
35
30
|
|
|
36
31
|
let inflight = null;
|
|
@@ -148,18 +143,6 @@ export const createConfigSyncReceiver = (deps = {}) => {
|
|
|
148
143
|
};
|
|
149
144
|
};
|
|
150
145
|
|
|
151
|
-
const isInboundCredentialAuthorized = async () => {
|
|
152
|
-
const settings = await readSettings();
|
|
153
|
-
return settings?.[INBOUND_CREDENTIAL_SETTINGS_KEY] === true;
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
const setInboundCredentialAuthorized = async (authorized) => {
|
|
157
|
-
await writeSettingsPatch({
|
|
158
|
-
[INBOUND_CREDENTIAL_SETTINGS_KEY]: authorized === true,
|
|
159
|
-
});
|
|
160
|
-
return { authorized: authorized === true };
|
|
161
|
-
};
|
|
162
|
-
|
|
163
146
|
const probe = async (plan) => {
|
|
164
147
|
const snapshot = buildInventory();
|
|
165
148
|
const existing = new Set(snapshot.remoteExisting);
|
|
@@ -171,7 +154,6 @@ export const createConfigSyncReceiver = (deps = {}) => {
|
|
|
171
154
|
return {
|
|
172
155
|
...snapshot,
|
|
173
156
|
remoteExisting: [...new Set(planPaths.filter((rel) => existing.has(rel)))],
|
|
174
|
-
inboundCredentialAuthorized: await isInboundCredentialAuthorized(),
|
|
175
157
|
};
|
|
176
158
|
};
|
|
177
159
|
|
|
@@ -211,14 +193,6 @@ export const createConfigSyncReceiver = (deps = {}) => {
|
|
|
211
193
|
error.code = 'sync_not_prepared';
|
|
212
194
|
throw error;
|
|
213
195
|
}
|
|
214
|
-
if (kind === 'auth') {
|
|
215
|
-
const authorized = await isInboundCredentialAuthorized();
|
|
216
|
-
if (!authorized) {
|
|
217
|
-
const error = new Error('Credential sync is not authorized on this host');
|
|
218
|
-
error.code = CREDENTIAL_SYNC_UNAUTHORIZED_CODE;
|
|
219
|
-
throw error;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
196
|
const buffer = await readStreamToBuffer(stream, { maxBytes: OPENCODE_CONFIG_SYNC_MAX_BYTES });
|
|
223
197
|
const home = homedir();
|
|
224
198
|
if (kind === 'config') {
|
|
@@ -279,12 +253,6 @@ export const createConfigSyncReceiver = (deps = {}) => {
|
|
|
279
253
|
return collectTarGz(home, ['.agents']);
|
|
280
254
|
}
|
|
281
255
|
if (kind === 'auth') {
|
|
282
|
-
const authorized = await isInboundCredentialAuthorized();
|
|
283
|
-
if (!authorized) {
|
|
284
|
-
const error = new Error('Credential sync is not authorized on this host');
|
|
285
|
-
error.code = CREDENTIAL_SYNC_UNAUTHORIZED_CODE;
|
|
286
|
-
throw error;
|
|
287
|
-
}
|
|
288
256
|
return collectTarGz(path.join(home, '.local', 'share', 'opencode'), ['auth.json']);
|
|
289
257
|
}
|
|
290
258
|
const error = new Error(`Unsupported download kind: ${String(kind)}`);
|
|
@@ -315,7 +283,6 @@ export const createConfigSyncReceiver = (deps = {}) => {
|
|
|
315
283
|
};
|
|
316
284
|
|
|
317
285
|
return {
|
|
318
|
-
INBOUND_CREDENTIAL_SETTINGS_KEY,
|
|
319
286
|
probe,
|
|
320
287
|
prepare,
|
|
321
288
|
put,
|
|
@@ -323,8 +290,6 @@ export const createConfigSyncReceiver = (deps = {}) => {
|
|
|
323
290
|
finalize,
|
|
324
291
|
abort,
|
|
325
292
|
getInflight: () => inflight,
|
|
326
|
-
isInboundCredentialAuthorized,
|
|
327
|
-
setInboundCredentialAuthorized,
|
|
328
293
|
buildInventory,
|
|
329
294
|
};
|
|
330
295
|
};
|
|
@@ -2,43 +2,29 @@ import { createConfigSyncReceiver } from './receiver.js';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Register HTTP config-sync receive/download routes for direct (and later relay) hosts.
|
|
5
|
-
* Auth is the global `/api` UI/client-token gate.
|
|
6
|
-
*
|
|
5
|
+
* Auth is the global `/api` UI/client-token gate. Selected kinds (including auth)
|
|
6
|
+
* sync when present in the plan — no extra credential grant checks.
|
|
7
7
|
*
|
|
8
8
|
* @param {import('express').Express} app
|
|
9
9
|
* @param {{
|
|
10
10
|
* receiver?: ReturnType<typeof createConfigSyncReceiver>,
|
|
11
|
-
* readSettingsFromDiskMigrated?: () => Promise<object>,
|
|
12
|
-
* persistSettings?: (changes: object) => Promise<object>,
|
|
13
11
|
* express?: typeof import('express'),
|
|
14
12
|
* }} deps
|
|
15
13
|
*/
|
|
16
14
|
export const registerConfigSyncRoutes = (app, deps = {}) => {
|
|
17
15
|
const {
|
|
18
|
-
readSettingsFromDiskMigrated,
|
|
19
|
-
persistSettings,
|
|
20
16
|
express,
|
|
21
17
|
} = deps;
|
|
22
18
|
|
|
23
|
-
const receiver = deps.receiver || createConfigSyncReceiver(
|
|
24
|
-
readSettings: async () => (typeof readSettingsFromDiskMigrated === 'function'
|
|
25
|
-
? readSettingsFromDiskMigrated()
|
|
26
|
-
: {}),
|
|
27
|
-
writeSettingsPatch: async (patch) => {
|
|
28
|
-
if (typeof persistSettings === 'function') {
|
|
29
|
-
await persistSettings(patch);
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
});
|
|
19
|
+
const receiver = deps.receiver || createConfigSyncReceiver();
|
|
33
20
|
|
|
34
21
|
const sendError = (res, error, fallbackStatus = 500) => {
|
|
35
22
|
const code = typeof error?.code === 'string' ? error.code : undefined;
|
|
36
|
-
const status = code === '
|
|
37
|
-
: code === '
|
|
38
|
-
: code === '
|
|
39
|
-
: code === '
|
|
40
|
-
:
|
|
41
|
-
: fallbackStatus;
|
|
23
|
+
const status = code === 'sync_in_progress' ? 409
|
|
24
|
+
: code === 'sync_not_prepared' ? 409
|
|
25
|
+
: code === 'sync_payload_too_large' || code === 'sync_too_many_files' ? 413
|
|
26
|
+
: code === 'sync_invalid_kind' ? 400
|
|
27
|
+
: fallbackStatus;
|
|
42
28
|
res.status(status).json({
|
|
43
29
|
error: error instanceof Error ? error.message : String(error),
|
|
44
30
|
...(code ? { code } : {}),
|
|
@@ -118,24 +104,5 @@ export const registerConfigSyncRoutes = (app, deps = {}) => {
|
|
|
118
104
|
}
|
|
119
105
|
});
|
|
120
106
|
|
|
121
|
-
app.get('/api/openchamber/config-sync/credential-auth', async (_req, res) => {
|
|
122
|
-
try {
|
|
123
|
-
const authorized = await receiver.isInboundCredentialAuthorized();
|
|
124
|
-
res.json({ authorized });
|
|
125
|
-
} catch (error) {
|
|
126
|
-
sendError(res, error);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
app.put('/api/openchamber/config-sync/credential-auth', express?.json?.({ limit: '16kb' }) || ((req, _res, next) => next()), async (req, res) => {
|
|
131
|
-
try {
|
|
132
|
-
const authorized = req.body?.authorized === true;
|
|
133
|
-
const result = await receiver.setInboundCredentialAuthorized(authorized);
|
|
134
|
-
res.json(result);
|
|
135
|
-
} catch (error) {
|
|
136
|
-
sendError(res, error);
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
|
|
140
107
|
return { receiver };
|
|
141
108
|
};
|
|
@@ -8,7 +8,6 @@ import request from 'supertest';
|
|
|
8
8
|
|
|
9
9
|
import { createConfigSyncReceiver } from './receiver.js';
|
|
10
10
|
import { registerConfigSyncRoutes } from './routes.js';
|
|
11
|
-
import { CREDENTIAL_SYNC_UNAUTHORIZED_CODE } from './credential-auth.js';
|
|
12
11
|
|
|
13
12
|
const tempDirs = [];
|
|
14
13
|
|
|
@@ -31,18 +30,13 @@ const createApp = async () => {
|
|
|
31
30
|
await fsp.writeFile(path.join(configDir, 'opencode.jsonc'), '{}\n');
|
|
32
31
|
await fsp.writeFile(path.join(configDir, 'AGENTS.md'), 'hi\n');
|
|
33
32
|
|
|
34
|
-
let settings = {};
|
|
35
33
|
const receiver = createConfigSyncReceiver({
|
|
36
34
|
homedir: () => home,
|
|
37
|
-
readSettings: async () => ({ ...settings }),
|
|
38
|
-
writeSettingsPatch: async (patch) => {
|
|
39
|
-
settings = { ...settings, ...patch };
|
|
40
|
-
},
|
|
41
35
|
});
|
|
42
36
|
|
|
43
37
|
const app = express();
|
|
44
38
|
registerConfigSyncRoutes(app, { receiver, express });
|
|
45
|
-
return { app, home, receiver
|
|
39
|
+
return { app, home, receiver };
|
|
46
40
|
};
|
|
47
41
|
|
|
48
42
|
describe('config-sync HTTP routes', () => {
|
|
@@ -79,27 +73,6 @@ describe('config-sync HTTP routes', () => {
|
|
|
79
73
|
await expect(fsp.stat(backup)).resolves.toMatchObject({ });
|
|
80
74
|
});
|
|
81
75
|
|
|
82
|
-
it('rejects auth put without inbound credential authorization', async () => {
|
|
83
|
-
const { app } = await createApp();
|
|
84
|
-
const plan = {
|
|
85
|
-
direction: 'push',
|
|
86
|
-
files: [],
|
|
87
|
-
directories: [],
|
|
88
|
-
deletes: [],
|
|
89
|
-
agentsRoot: null,
|
|
90
|
-
authFile: { bytes: 2 },
|
|
91
|
-
totalBytes: 2,
|
|
92
|
-
};
|
|
93
|
-
await request(app).post('/api/openchamber/config-sync/prepare').send({ plan, syncRunId: 'run-auth' });
|
|
94
|
-
const put = await request(app)
|
|
95
|
-
.put('/api/openchamber/config-sync/put/auth?syncRunId=run-auth')
|
|
96
|
-
.set('Content-Type', 'application/gzip')
|
|
97
|
-
.send(Buffer.from('xx'));
|
|
98
|
-
expect(put.status).toBe(403);
|
|
99
|
-
expect(put.body.code).toBe(CREDENTIAL_SYNC_UNAUTHORIZED_CODE);
|
|
100
|
-
await request(app).post('/api/openchamber/config-sync/abort').send({ syncRunId: 'run-auth' });
|
|
101
|
-
});
|
|
102
|
-
|
|
103
76
|
it('rejects a second concurrent prepare', async () => {
|
|
104
77
|
const { app } = await createApp();
|
|
105
78
|
const plan = {
|
|
@@ -131,7 +104,6 @@ describe('config-sync HTTP routes', () => {
|
|
|
131
104
|
totalBytes: 0,
|
|
132
105
|
};
|
|
133
106
|
await request(app).post('/api/openchamber/config-sync/prepare').send({ plan, syncRunId: 'run-stream' });
|
|
134
|
-
await receiver.setInboundCredentialAuthorized(true);
|
|
135
107
|
|
|
136
108
|
// Tiny invalid tar still proves chunk aggregation reached extract.
|
|
137
109
|
await expect(receiver.put({
|
|
@@ -142,13 +114,4 @@ describe('config-sync HTTP routes', () => {
|
|
|
142
114
|
|
|
143
115
|
await request(app).post('/api/openchamber/config-sync/abort').send({ syncRunId: 'run-stream' });
|
|
144
116
|
});
|
|
145
|
-
|
|
146
|
-
it('persists inbound credential authorization flag', async () => {
|
|
147
|
-
const { app, getSettings } = await createApp();
|
|
148
|
-
const before = await request(app).get('/api/openchamber/config-sync/credential-auth');
|
|
149
|
-
expect(before.body.authorized).toBe(false);
|
|
150
|
-
const after = await request(app).put('/api/openchamber/config-sync/credential-auth').send({ authorized: true });
|
|
151
|
-
expect(after.body.authorized).toBe(true);
|
|
152
|
-
expect(getSettings().configSyncInboundCredentialAuthorized).toBe(true);
|
|
153
|
-
});
|
|
154
117
|
});
|
|
@@ -10,8 +10,6 @@ export const registerOpenChamberRoutes = (app, dependencies) => {
|
|
|
10
10
|
server,
|
|
11
11
|
__dirname,
|
|
12
12
|
openchamberDataDir,
|
|
13
|
-
readSettingsFromDiskMigrated,
|
|
14
|
-
persistSettings,
|
|
15
13
|
fetchFreeZenModels,
|
|
16
14
|
getCachedZenModels,
|
|
17
15
|
sessionIndexService,
|
|
@@ -22,11 +20,7 @@ export const registerOpenChamberRoutes = (app, dependencies) => {
|
|
|
22
20
|
|
|
23
21
|
registerSessionIndexRoutes(app, { sessionIndexService, sessionIndexSyncRuntime });
|
|
24
22
|
registerTranscriptCacheRoutes(app, { transcriptCacheService });
|
|
25
|
-
registerConfigSyncRoutes(app, {
|
|
26
|
-
readSettingsFromDiskMigrated,
|
|
27
|
-
persistSettings,
|
|
28
|
-
express,
|
|
29
|
-
});
|
|
23
|
+
registerConfigSyncRoutes(app, { express });
|
|
30
24
|
|
|
31
25
|
app.get('/api/openchamber/update-check', async (req, res) => {
|
|
32
26
|
try {
|
|
@@ -318,9 +318,6 @@ export const createSettingsHelpers = (dependencies) => {
|
|
|
318
318
|
if (typeof candidate.showReasoningTraces === 'boolean') {
|
|
319
319
|
result.showReasoningTraces = candidate.showReasoningTraces;
|
|
320
320
|
}
|
|
321
|
-
if (typeof candidate.sessionRecapEnabled === 'boolean') {
|
|
322
|
-
result.sessionRecapEnabled = candidate.sessionRecapEnabled;
|
|
323
|
-
}
|
|
324
321
|
if (typeof candidate.sessionTitleRefreshEnabled === 'boolean') {
|
|
325
322
|
result.sessionTitleRefreshEnabled = candidate.sessionTitleRefreshEnabled;
|
|
326
323
|
}
|
|
@@ -8,7 +8,6 @@ export const createGracefulShutdownRuntime = (dependencies) => {
|
|
|
8
8
|
syncToHmrState,
|
|
9
9
|
openCodeWatcherRuntime,
|
|
10
10
|
sessionRuntime,
|
|
11
|
-
sessionAssistRuntime,
|
|
12
11
|
sessionTitleRuntime,
|
|
13
12
|
sessionGoalRuntime,
|
|
14
13
|
scheduledTasksRuntime,
|
|
@@ -43,7 +42,6 @@ export const createGracefulShutdownRuntime = (dependencies) => {
|
|
|
43
42
|
|
|
44
43
|
openCodeWatcherRuntime.stop();
|
|
45
44
|
sessionRuntime.dispose();
|
|
46
|
-
sessionAssistRuntime?.stop?.();
|
|
47
45
|
sessionTitleRuntime?.stop?.();
|
|
48
46
|
sessionGoalRuntime?.stop?.();
|
|
49
47
|
// Stop timers/queue only. Keep the process-lifetime run history store open so
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Server-side control loop that keeps a session working toward a user-defined
|
|
4
4
|
objective stored under `metadata.openchamber.goal`, with the small model as
|
|
5
5
|
an independent progress auditor. Built on OpenChamber's backend-driven
|
|
6
|
-
architecture
|
|
6
|
+
architecture: the loop lives in
|
|
7
7
|
the web server and survives UI disconnects.
|
|
8
8
|
|
|
9
9
|
## Goal payload (`metadata.openchamber.goal`)
|
|
@@ -69,8 +69,8 @@ before touching the filesystem). Rationale: metadata rides every
|
|
|
69
69
|
|
|
70
70
|
## Flow
|
|
71
71
|
|
|
72
|
-
1. `createSessionGoalRuntime` subscribes to the global SSE hub (
|
|
73
|
-
|
|
72
|
+
1. `createSessionGoalRuntime` subscribes to the global SSE hub (it needs
|
|
73
|
+
the envelope's `directory`).
|
|
74
74
|
2. `session.status: idle` arms a 15s per-session timer; `busy`/`retry` clears
|
|
75
75
|
it. A `session.updated` carrying a fresh active goal (`turnsUsed === 0` or
|
|
76
76
|
`statusReason === 'resumed'`) arms a kickoff timer — 3s for fresh goals,
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// has no channel to settle its own goal. When the small model is unavailable
|
|
12
12
|
// the loop still terminates via the budget and the continuation cap.
|
|
13
13
|
//
|
|
14
|
-
// Purely event-driven
|
|
14
|
+
// Purely event-driven: no polling, no backfill, no session
|
|
15
15
|
// scans. Only sessions that emit events while the server runs ever tick.
|
|
16
16
|
|
|
17
17
|
import fs from 'fs';
|
|
@@ -110,8 +110,8 @@ const buildAuditSystemPrompt = () => [
|
|
|
110
110
|
].join('\n');
|
|
111
111
|
|
|
112
112
|
// Hard guard against language hallucination (account-side personalization
|
|
113
|
-
// can leak a different language despite the instruction
|
|
114
|
-
//
|
|
113
|
+
// can leak a different language despite the instruction): if the note uses
|
|
114
|
+
// a script absent from the objective
|
|
115
115
|
// and the agent's reply, drop the note but keep the verdict.
|
|
116
116
|
const SCRIPT_RANGES = [
|
|
117
117
|
/[Ѐ-ӿ]/, // Cyrillic
|
|
@@ -14,8 +14,7 @@ throttle (`TITLE_THROTTLE_MS`) when a refresh is armed.
|
|
|
14
14
|
## Flow
|
|
15
15
|
|
|
16
16
|
1. `createSessionTitleRuntime` is a consumer of the server's global SSE
|
|
17
|
-
fan-out (`index.js` → `globalMessageStreamHub.subscribeEvent`)
|
|
18
|
-
pattern as session-assist. Purely event-driven — dormant sessions never
|
|
17
|
+
fan-out (`index.js` → `globalMessageStreamHub.subscribeEvent`). Purely event-driven — dormant sessions never
|
|
19
18
|
generate anything.
|
|
20
19
|
2. Auto title refresh is intentionally sparse (title stability first). A newly
|
|
21
20
|
observed root `session.created` generates its first title immediately on the
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./rolldown-runtime-C0FnF6B9.js";import{nt as e,rt as t}from"./vendor-base-ui-CnHfUmDN.js";import{n}from"./vendor-react-DLPElpoQ.js";import{t as r}from"./utils-B1EK5zKa.js";t();var i=n(),a=[{var:`--status-success`,class:`agent-success`},{var:`--syntax-keyword`,class:`agent-keyword`},{var:`--syntax-type`,class:`agent-type`},{var:`--syntax-function`,class:`agent-function`},{var:`--syntax-number`,class:`agent-number`},{var:`--status-info`,class:`agent-info`},{var:`--status-warning`,class:`agent-warning`},{var:`--syntax-variable`,class:`agent-variable`}];function o(e){if(!e||e===`build`)return a[0];let t=0;for(let n=0;n<e.length;n++){let r=e.charCodeAt(n);t=(t<<5)-t+r,t&=t}return a[1+Math.abs(t)%(a.length-1)]}var s=5,c=Math.ceil(s/2);function l(e){let t=0;for(let n=0;n<e.length;n++)t=(t<<5)-t+e.charCodeAt(n),t|=0;return t>>>0}function u(e){let t=Array.from({length:s},()=>Array.from({length:s},()=>!1));if(!e)return t;let n=l(e);for(let e=0;e<s;e++)for(let r=0;r<c;r++){let i=(n&1)==1;n>>>=1,t[e][r]=i,t[e][4-r]=i}return t}var d=e(),f=e=>{let t=(0,i.c)(27),{name:n,emoji:a,size:s,className:c,label:l}=e,f=s===void 0?16:s,m,h,g;if(t[0]!==c||t[1]!==a||t[2]!==n){m=o(n);let e;t[6]===n?e=t[7]:(e=u(n),t[6]=n,t[7]=e),h=e,g=r(`inline-flex aspect-square shrink-0 overflow-hidden rounded-sm`,a&&`items-center justify-center select-none`,m.class,c),t[0]=c,t[1]=a,t[2]=n,t[3]=m,t[4]=h,t[5]=g}else m=t[3],h=t[4],g=t[5];let _=`calc(${f}px * var(--dpt-n, 1))`,v=`calc(${f}px * var(--dpt-n, 1))`,y=`calc(${f}px * var(--dpt-n, 1))`,b=`calc(${f}px * var(--dpt-n, 1))`,x=`calc(${f}px * var(--dpt-n, 1))`,S=`calc(${f}px * var(--dpt-n, 1))`,C=`var(${m.var})`,w;t[8]!==_||t[9]!==v||t[10]!==y||t[11]!==b||t[12]!==x||t[13]!==S||t[14]!==C?(w={width:_,minWidth:v,maxWidth:y,height:b,minHeight:x,maxHeight:S,color:C},t[8]=_,t[9]=v,t[10]=y,t[11]=b,t[12]=x,t[13]=S,t[14]=C,t[15]=w):w=t[15];let T=l?`img`:void 0,E=!l||void 0,D;t[16]!==a||t[17]!==h||t[18]!==f?(D=a?(0,d.jsx)(`span`,{"aria-hidden":`true`,style:{fontSize:`calc(${f*.75}px * var(--dpt-n, 1))`,lineHeight:1},children:a}):(0,d.jsxs)(`svg`,{width:f,height:f,viewBox:`0 0 5 5`,shapeRendering:`crispEdges`,className:`oc-agent-avatar block h-full w-full`,"aria-hidden":`true`,children:[(0,d.jsx)(`rect`,{width:`5`,height:`5`,fill:`currentColor`,opacity:.14}),h.map(p)]}),t[16]=a,t[17]=h,t[18]=f,t[19]=D):D=t[19];let O;return t[20]!==l||t[21]!==w||t[22]!==T||t[23]!==E||t[24]!==D||t[25]!==g?(O=(0,d.jsx)(`span`,{className:g,style:w,role:T,"aria-label":l,"aria-hidden":E,children:D}),t[20]=l,t[21]=w,t[22]=T,t[23]=E,t[24]=D,t[25]=g,t[26]=O):O=t[26],O};function p(e,t){return e.map((e,n)=>e?(0,d.jsx)(`rect`,{x:n,y:t,width:`1`,height:`1`,fill:`currentColor`},`${n}-${t}`):null)}export{o as n,f as t};
|