@openchambery/web 1.19.11 → 1.19.13-beta.1
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-CX0a1rKE.js → AgentAvatar-CiQIIM0d.js} +1 -1
- package/dist/assets/AssistantView-YmeyxehG.js +2 -0
- package/dist/assets/{DiagramView-BQO1cBLs.js → DiagramView-BpZb-G9P.js} +1 -1
- package/dist/assets/{FadeInOnReveal-CTlNE4Hg.js → FadeInOnReveal-nf6-ZCrs.js} +1 -1
- package/dist/assets/{Icon-BYM02QyU.js → Icon-CeKHYyKZ.js} +1 -1
- package/dist/assets/MarkdownRenderer-wpeGdciL.js +2 -0
- package/dist/assets/{MarkdownRendererImpl--takeMXN.js → MarkdownRendererImpl-Peu0GVSQ.js} +1 -1
- package/dist/assets/{MarkstreamRendererImpl-DGSqWcPN.js → MarkstreamRendererImpl-B-odd2Gz.js} +1 -1
- package/dist/assets/MobileDetailNavigation-CtYke_1C.js +1 -0
- package/dist/assets/{MobileShareBridge-D-BUjACe.js → MobileShareBridge-DIfOl8EZ.js} +3 -3
- package/dist/assets/MobileSurface-_KoX75Ff.js +2 -0
- package/dist/assets/{MultiRunWindow-BNR9ZWmD.js → MultiRunWindow-BT5Dwgzu.js} +1 -1
- package/dist/assets/{OnboardingScreen-DS2nugLX.js → OnboardingScreen-BPusUgFG.js} +1 -1
- package/dist/assets/{OverlayScrollbar-KUpvYHdv.js → OverlayScrollbar-DUghqFGg.js} +1 -1
- package/dist/assets/{SettingsView-DGerg-C2.js → SettingsView-BwQpbIZl.js} +11 -11
- package/dist/assets/{SettingsWindow-CSpd5JbJ.js → SettingsWindow-DfEGfyr8.js} +1 -1
- package/dist/assets/{TerminalView-DS-oUxJr.js → TerminalView-8402vpcO.js} +1 -1
- package/dist/assets/{ToolOutputDialog-Q1k9-IaY.js → ToolOutputDialog-B5RdkhsG.js} +1 -1
- package/dist/assets/{appThemeRegistry-CG7D-3-q.js → appThemeRegistry-CIZ-shMD.js} +1 -1
- package/dist/assets/{button-C0cth9tl.js → button-DFPOdZ0g.js} +1 -1
- package/dist/assets/{clipboard-DJ4nQEuY.js → clipboard-C05anBwU.js} +1 -1
- package/dist/assets/{collapsible-DFT9cE80.js → collapsible-oGbEvbe1.js} +1 -1
- package/dist/assets/{context-menu-CAp74NfV.js → context-menu-DGz4_2hs.js} +1 -1
- package/dist/assets/{desktopHosts-Dc2PS66M.js → desktopHosts-BVJXQq1S.js} +1 -1
- package/dist/assets/{desktopRelayRestore-T9y0orqa.js → desktopRelayRestore-RDfuj1M7.js} +1 -1
- package/dist/assets/{diagram-BryzMuta.js → diagram-Csk5GpDC.js} +1 -1
- package/dist/assets/{dialog-CgbV5ljg.js → dialog-rrqB-H6q.js} +1 -1
- package/dist/assets/{es-BHqnSjoZ.js → es-FE0sJ9EC.js} +1 -1
- package/dist/assets/{fileQueries-BY-9OWzp.js → fileQueries-BcdWOPlD.js} +1 -1
- package/dist/assets/{fr-BfrlJY9i.js → fr-DNDCSfGt.js} +1 -1
- package/dist/assets/{gitApi-Cr-joUEw.js → gitApi-_P0FsoXe.js} +1 -1
- package/dist/assets/{input-DFLpqjGR.js → input-BO3r20op.js} +1 -1
- package/dist/assets/{insertionBoundaries-X0xbikAA.js → insertionBoundaries-CWoioTdE.js} +1 -1
- package/dist/assets/{ja-DP-7qt-x.js → ja-BDwrk0cM.js} +1 -1
- package/dist/assets/{ko-E2B5vGQP.js → ko-BeeU2o4I.js} +1 -1
- package/dist/assets/{main-D0L7fIg3.js → main-CLj_WS1o.js} +2 -2
- package/dist/assets/{main-BI7fNQoi.js → main-CnSZ89pD.js} +4 -4
- package/dist/assets/{markdown-worker-CTsrtpPh.js → markdown-worker-CZWE1F1M.js} +1 -1
- package/dist/assets/{markdownHeightCache-CYDlisxr.js → markdownHeightCache-Cdd3hkMl.js} +1 -1
- package/dist/assets/{markdownTheme-DyJ4Gfcj.js → markdownTheme-DIB8WVmz.js} +1 -1
- package/dist/assets/miniChat-B9c3y2pD.js +2 -0
- package/dist/assets/{mobile-OcCu_0mG.js → mobile-DvbXUfNS.js} +2 -2
- package/dist/assets/{multirun-B0G_BEIN.js → multirun-CxhTsmRq.js} +1 -1
- package/dist/assets/{persistence-DdUac14I.js → persistence-CVTWFaqe.js} +2 -2
- package/dist/assets/{pl-r8X5gRM5.js → pl-BYuzpcI5.js} +1 -1
- package/dist/assets/{platform-B4KKLnZ5.js → platform-BY_Gtsqr.js} +1 -1
- package/dist/assets/{projectMeta-BNOzn1QS.js → projectMeta-Dl5iPCB6.js} +1 -1
- package/dist/assets/{pt-BR-DcpdXCf5.js → pt-BR-Bn7cwEzv.js} +1 -1
- package/dist/assets/{renderElectronMiniChatApp-BREc3uhX.js → renderElectronMiniChatApp-CkJ51qCh.js} +2 -2
- package/dist/assets/renderMobileApp-DcjQPhWw.js +28 -0
- package/dist/assets/{runtimeConfig-P8nVMYzE.js → runtimeConfig-Bsk2kWsW.js} +1 -1
- package/dist/assets/runtimeEndpointReset-BBLFgl85.js +147 -0
- package/dist/assets/{sessionChangeSummary-hVby3sJk.js → sessionChangeSummary-DDVT7O5J.js} +1 -1
- package/dist/assets/{sessionLookup-C_9-9ggp.js → sessionLookup-C8VZn0gJ.js} +1 -1
- package/dist/assets/{sortable-tabs-strip-C8_9kHqu.js → sortable-tabs-strip-s7UUxsa6.js} +1 -1
- package/dist/assets/src-BpHDMgud.css +2 -0
- package/dist/assets/{store-BDFdnk6l.js → store-n94dSb3M.js} +2 -2
- package/dist/assets/{terminalApi-947l7Ra3.js → terminalApi-C54_rKEK.js} +1 -1
- package/dist/assets/{textarea-Cgo_nWUU.js → textarea-BjX-KhMN.js} +1 -1
- package/dist/assets/{tooltip-BifLJ8o0.js → tooltip-CQGqGAG_.js} +1 -1
- package/dist/assets/{uk-Di0vl9V-.js → uk-CwpbHEa3.js} +1 -1
- package/dist/assets/{url-Pk6tQ1EZ.js → url-BMjqccCo.js} +1 -1
- package/dist/assets/{useAppFontEffects-CEmOsrr6.js → useAppFontEffects-BIFw36SA.js} +5 -5
- package/dist/assets/{useAssistantUIStore-me6s63b2.js → useAssistantUIStore-Cg9bsT4b.js} +1 -1
- package/dist/assets/{useDesktopWindowControlsLayout-CxaK-zXh.js → useDesktopWindowControlsLayout-DoygEcN4.js} +1 -1
- package/dist/assets/{useEffectiveDirectory-BIwv5r5l.js → useEffectiveDirectory-DJSYYkVp.js} +1 -1
- package/dist/assets/{useFontPreferences-BCOBlaAd.js → useFontPreferences-B5_apbBC.js} +1 -1
- package/dist/assets/{useMobileNavigationStore-DHm5kZPx.js → useMobileNavigationStore-DuTu0Mzh.js} +5 -5
- package/dist/assets/{useSessionAutoCleanup-CPLP9KWH.js → useSessionAutoCleanup-C-L9teva.js} +1 -1
- package/dist/assets/{useUIStore-CuaA8-Hp.js → useUIStore-DwpQTjLO.js} +1 -1
- package/dist/assets/{useWorkerHighlightedLines-CZ4ZTWEH.js → useWorkerHighlightedLines-DxTfgdEi.js} +1 -1
- package/dist/assets/{utils-BiK3tBGM.js → utils-81nUI_xp.js} +1 -1
- package/dist/assets/{zh-CN-coFCfeQE.js → zh-CN-BpzFZ-LU.js} +1 -1
- package/dist/assets/{zh-TW-oDRZ1-yb.js → zh-TW-Bopgc5Eo.js} +1 -1
- 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 +19 -0
- package/server/lib/assistants/DOCUMENTATION.md +21 -6
- package/server/lib/assistants/assign.js +455 -30
- package/server/lib/assistants/assign.test.js +351 -0
- package/server/lib/assistants/contact-active-turn.http.test.js +134 -0
- package/server/lib/assistants/contact-store.js +64 -0
- package/server/lib/assistants/contact-store.test.js +12 -0
- package/server/lib/assistants/contact-tools.js +216 -25
- package/server/lib/assistants/contact-tools.test.js +167 -0
- package/server/lib/assistants/contracts.js +2 -2
- package/server/lib/assistants/harness.js +20 -3
- package/server/lib/assistants/harness.test.js +120 -1
- package/server/lib/assistants/pi-tools.js +50 -3
- package/server/lib/assistants/pi-tools.test.js +25 -0
- package/server/lib/assistants/service.js +320 -27
- package/server/lib/assistants/service.test.js +581 -9
- package/server/lib/llm/DOCUMENTATION.md +31 -18
- package/server/lib/llm/catalog.js +91 -16
- package/server/lib/llm/catalog.test.js +152 -11
- package/server/lib/llm/generate.js +43 -7
- package/server/lib/llm/generate.test.js +98 -1
- package/server/lib/llm/temp-directory.js +34 -13
- package/server/lib/llm/temp-directory.test.js +57 -0
- package/server/lib/notifications/APNS.md +20 -4
- package/server/lib/notifications/DOCUMENTATION.md +5 -0
- package/server/lib/notifications/apns-runtime.js +136 -18
- package/server/lib/notifications/apns-runtime.test.js +128 -0
- package/server/lib/notifications/apns-titles.js +21 -1
- package/server/lib/notifications/live-activity-refresh-runtime.js +185 -0
- package/server/lib/notifications/live-activity-refresh-runtime.test.js +242 -0
- package/server/lib/notifications/runtime.js +93 -2
- package/server/lib/notifications/runtime.test.js +167 -4
- package/server/lib/opencode/settings-helpers.js +12 -0
- package/server/lib/opencode/settings-runtime.js +16 -0
- package/server/lib/opencode/settings-runtime.test.js +21 -0
- package/server/lib/scheduled-tasks/runtime.js +21 -0
- package/server/lib/scheduled-tasks/runtime.test.js +24 -0
- package/dist/assets/AssistantView-BwrcqJzu.js +0 -2
- package/dist/assets/MarkdownRenderer-C49bfcHx.js +0 -2
- package/dist/assets/MobileDetailNavigation-LZU2vFAs.js +0 -1
- package/dist/assets/MobileSurface-OAJjAQCZ.js +0 -2
- package/dist/assets/miniChat-BJ9AclZX.js +0 -2
- package/dist/assets/renderMobileApp-C4igZ42L.js +0 -28
- package/dist/assets/runtimeEndpointReset-6lVRspis.js +0 -147
- package/dist/assets/src-B-P5qIBc.css +0 -2
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-CLj_WS1o.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-DwpQTjLO.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-CVTWFaqe.js">
|
|
564
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-BVJXQq1S.js">
|
|
565
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-RDfuj1M7.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-BY_Gtsqr.js">
|
|
569
|
+
<link rel="modulepreload" crossorigin href="/assets/terminalApi-C54_rKEK.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-Bsk2kWsW.js">
|
|
573
|
+
<link rel="stylesheet" crossorigin href="/assets/src-BpHDMgud.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-B9c3y2pD.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-DwpQTjLO.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-CVTWFaqe.js">
|
|
86
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-BVJXQq1S.js">
|
|
87
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-RDfuj1M7.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-BY_Gtsqr.js">
|
|
91
|
+
<link rel="modulepreload" crossorigin href="/assets/terminalApi-C54_rKEK.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-Bsk2kWsW.js">
|
|
95
|
+
<link rel="stylesheet" crossorigin href="/assets/src-BpHDMgud.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-DvbXUfNS.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-DwpQTjLO.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-CVTWFaqe.js">
|
|
75
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-BVJXQq1S.js">
|
|
76
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-RDfuj1M7.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-BY_Gtsqr.js">
|
|
80
|
+
<link rel="modulepreload" crossorigin href="/assets/terminalApi-C54_rKEK.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-Bsk2kWsW.js">
|
|
84
|
+
<link rel="stylesheet" crossorigin href="/assets/src-BpHDMgud.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
|
@@ -80,6 +80,10 @@ import { createNotificationEmitterRuntime } from './lib/notifications/emitter-ru
|
|
|
80
80
|
import { createNotificationTriggerRuntime } from './lib/notifications/runtime.js';
|
|
81
81
|
import { createPushRuntime } from './lib/notifications/push-runtime.js';
|
|
82
82
|
import { createApnsRuntime } from './lib/notifications/apns-runtime.js';
|
|
83
|
+
import {
|
|
84
|
+
createLiveActivityRefreshRuntime,
|
|
85
|
+
resolveLiveActivityRefreshIntervalMs,
|
|
86
|
+
} from './lib/notifications/live-activity-refresh-runtime.js';
|
|
83
87
|
import { createNotificationTemplateRuntime } from './lib/notifications/template-runtime.js';
|
|
84
88
|
import { createPermissionAutoAcceptRuntime } from './lib/permission-auto-accept/runtime.js';
|
|
85
89
|
import { createGracefulShutdownRuntime } from './lib/opencode/shutdown-runtime.js';
|
|
@@ -670,6 +674,17 @@ const maybeSendPushForTrigger = (...args) => notificationTriggerRuntime.maybeSen
|
|
|
670
674
|
const setAutoAcceptSession = (sessionId, enabled) => permissionAutoAcceptRuntime.setSessionPolicy(sessionId, enabled);
|
|
671
675
|
clearPendingPushBadge = () => notificationTriggerRuntime.clearPendingPushBadge();
|
|
672
676
|
|
|
677
|
+
// Keeps Live Activity snapshots fresh for iOS devices whose app iOS suspended
|
|
678
|
+
// or killed: every interval (default 30s) recompute each registered token's
|
|
679
|
+
// snapshot from the authoritative session states and push only real changes.
|
|
680
|
+
// The tick is a no-op (one token-store read) when no device registered.
|
|
681
|
+
const liveActivityRefreshRuntime = createLiveActivityRefreshRuntime({
|
|
682
|
+
intervalMs: resolveLiveActivityRefreshIntervalMs(),
|
|
683
|
+
refreshLiveActivityTokens: (...args) => apnsRuntime.refreshLiveActivityTokens(...args),
|
|
684
|
+
getSessionStateSnapshot: () => sessionRuntime.getSessionStateSnapshot(),
|
|
685
|
+
resolveSession: (sessionId) => notificationTriggerRuntime.resolveLiveActivitySessionCandidate(sessionId),
|
|
686
|
+
});
|
|
687
|
+
|
|
673
688
|
// Single lazy small-model service for all consumers (feature routes, session
|
|
674
689
|
// assist/title/goal, scheduled tasks). Catalog loader is directory-scoped and
|
|
675
690
|
// never requests models.dev.
|
|
@@ -1036,6 +1051,7 @@ const scheduledTasksRuntime = createScheduledTasksRuntime({
|
|
|
1036
1051
|
}
|
|
1037
1052
|
}
|
|
1038
1053
|
},
|
|
1054
|
+
notifyTaskRun: (event) => notificationTriggerRuntime.sendScheduledTaskRunNotification(event),
|
|
1039
1055
|
logger: console,
|
|
1040
1056
|
});
|
|
1041
1057
|
|
|
@@ -1675,6 +1691,8 @@ async function main(options = {}) {
|
|
|
1675
1691
|
console.warn('[ScheduledTasks] Failed to start runtime:', error?.message || error);
|
|
1676
1692
|
}
|
|
1677
1693
|
|
|
1694
|
+
liveActivityRefreshRuntime.start();
|
|
1695
|
+
|
|
1678
1696
|
// Only desktop / SSH-managed remotes (OPENCHAMBER_RUNTIME=desktop|ssh-remote)
|
|
1679
1697
|
// open a relay host-control socket or poll relay demand. Local `dev` / `web`
|
|
1680
1698
|
// never reconcile, so they cannot inherit a leftover desktop env and start
|
|
@@ -1736,6 +1754,7 @@ async function main(options = {}) {
|
|
|
1736
1754
|
console.warn('[message-queue] Failed to close durable database during shutdown');
|
|
1737
1755
|
}
|
|
1738
1756
|
realtimeProxyRuntime.stop();
|
|
1757
|
+
liveActivityRefreshRuntime.dispose();
|
|
1739
1758
|
if (relayReconcileTimer) clearInterval(relayReconcileTimer);
|
|
1740
1759
|
try {
|
|
1741
1760
|
relayService.stop();
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Acceptance criteria
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Worker submission uses one admission path for new and existing sessions.
|
|
6
|
+
Definite rejection cleans up only a session created by that call. Ambiguous
|
|
7
|
+
admission keeps the worker and confirms the exact message ID before reporting
|
|
8
|
+
success. Attachment deduplication uses ordered content digests; reordering
|
|
9
|
+
attachments is a different request.
|
|
10
|
+
|
|
11
|
+
The in-app Assistant is an OpenChamber-owned **contact**. OpenCode is only the LLM gateway (`POST /api/openchamber/llm/chat/completions`) using already-connected `{providerID, modelID}`. Composer send runs `@earendil-works/pi-agent-core` with `thinkingLevel: 'off'`. When the assistant has an effective workspace, the harness attaches pi's four coding tools (`read`, `write`, `edit`, `bash`) via `NodeExecutionEnv` in that directory, applies `defaultPrompt`, and merges skills from `~/.claude/skills`, `~/.agents/skills`, plus the project's `.claude/skills` and `.agents/skills` (project wins on name). OpenChamber API tools remain (`new_conversation`, `clear_chat_history`, `list_projects`, `list_sessions`, `create_assistant`, `schedule_task`, `message_assistant`, `assign_session`). It does not use `SessionPrompt` / `promptAsync` as the conversation engine. The LLM gateway throwaway session still denies OpenCode tools (`session.create` PermissionRuleset deny-all + `promptAsync` tools map + hidden `openchamber-llm` agent `permission: { "*": deny }`); file and shell work runs in-process through pi. The contact system prompt includes **full argument schemas** for both pi coding tools and OpenChamber contact tools. Skill directory entries are instructions loaded via `read`, not native/MCP tool names.
|
|
6
12
|
|
|
7
13
|
Contact turns retain all eight OpenChamber operation tools alongside the four
|
|
8
14
|
pi tools. Skill discovery contributes instructions to this combined tool set.
|
|
@@ -22,13 +28,22 @@ and keep their existing error result handling.
|
|
|
22
28
|
|
|
23
29
|
- `assign_session` is an OpenChamber AgentTool on the contact harness. It creates or reuses a visible OpenCode/OpenChamber session on a **registered project path** (Settings projects / `getAllowedRoots()`), optionally an **existing** Chat worktree/branch via `getWorktrees`, then kicks the coding prompt into that session with `session.create` + `session.promptAsync` (same worker path as `POST /api/openchamber/conversations`).
|
|
24
30
|
- That worker session is the coder. The contact does not code. Assign sessions are **not** archived Assistant bindings and must not use `assistant-workspaces`.
|
|
25
|
-
-
|
|
31
|
+
- **Worker model selection:** optional tool args `providerID` / `modelID` / `model` resolve against the live connected OpenCode catalog (`loadConnectedCatalog` / `GET /provider` + `GET /config/providers`). Explicit selection must match uniquely — missing or ambiguous names fail closed (`model_not_found` / `model_ambiguous`) with **no silent fallback**. Omitting model args keeps the contact assistant's default provider/model for the worker only. Selecting a worker model **never** mutates the contact assistant row.
|
|
32
|
+
- Every contact turn injects a **Connected OpenCode models** block (providerID, modelID, name, acceptsImages) so the model can discover worker targets without a ninth contact tool. Still eight OpenChamber contact tools + four pi coding tools.
|
|
33
|
+
- **Current-turn attachments:** server-authoritative `userParts` file parts from this contact turn are forwarded into worker `promptAsync` parts by default (including “just open a session” intents). The model must not base64-encode or invent local paths. History images are **not** unbounded-forwarded. Image parts require a vision-capable catalog entry (`acceptsImages`); otherwise assign fails with `image_not_supported` before create. Sensitive file bodies are never logged.
|
|
34
|
+
- **Create-then-prompt failure:** if `session.create` succeeds and `promptAsync` fails, assign best-effort `session.delete`s the new worker so empty sessions are not left behind. Reused `sessionID` paths never delete on prompt failure.
|
|
35
|
+
- Successful `assign_session` returns `terminate: true` so the pi agent loop does **not** auto-follow-up the LLM (prevents a looping model from re-assigning dozens of times in one turn). Prerequisite tools (`list_projects` / `list_sessions`) may still run before assign in the same turn; multi-operation user intents remain ordered **across turns** after a successful assign.
|
|
36
|
+
- Same contact-turn assign gate (tools instance lifetime only, not cross-turn): identical args after success replay the cached success result (no second worker); different args after success, or parallel mismatched args, fail closed with a validation error. The idempotent key includes worker model selection and current-turn attachment scope. Failure clears the gate so a corrected retry may run. Parallel identical args share one in-flight promise.
|
|
37
|
+
- After a successful assign, the service persists the existing session card into the contact transcript (user bubbles first, then the card) and watches that worker session in `assistant_contact_watch`. The user-facing outcome is the session card plus a short confirm bubble.
|
|
26
38
|
- Existing OpenCode SSE on the same `globalEventHub` as notifications (`session.idle`, `session.error`, `session.status`, `question.asked`, `permission.asked`) updates **the same card** (`busy` → `complete` / `error` / `question`) and appends one idempotent settle bubble (`oc.settle.*`). Session-goal settle (`emitGoalNotification`) is wired into that same reporter — not a second scheduler. Idle after `session.error` must not rewrite 失败 as 完成.
|
|
27
39
|
- Restart or a missed `session.idle` cannot leave the watch stuck: boot and the existing 60s reconcile timer `listInFlightWatches` and poll OpenCode `session.get` / `session.messages`. Idle, `time.completed`, or a missing session settles the same card (`busy` → 完成) and appends the existing `oc.settle.complete` bubble. `session.error` or last-assistant `info.error` settles 失败. Transport / non-404 get errors leave the watch in flight (failure is not empty success). One failed watch does not block unrelated watches. Reconcile reuses `reportAssignedSession`, so an error watch is never rewritten as complete.
|
|
28
40
|
- Worker sessions stamp `metadata.openchamber.assigned` (`from: 'contact'`, `assistantID`, `name`). They must **not** use `openchamber.assistant.assistantID` — that marker hides archived Assistant bindings from Chat.
|
|
29
|
-
- `AssistantDTO.assignedSessionIDs` lists in-flight (`busy`/`question`) watches
|
|
41
|
+
- `AssistantDTO.assignedSessionIDs` lists in-flight (`busy`/`question`) watches for assigned worker sessions. Session-card busy stays on the card; it does **not** drive the list green dot.
|
|
42
|
+
- **Contact active turn (server authoritative):** process-local metadata tracks admission → `queued` → `running` → settled (removed). `AssistantDTO.working` is true only while that assistant has an unsettled contact turn. `AssistantDTO.activeContactTurn` is `{ turnID, messageID, status: 'queued'|'running', admittedAt }` or `null` so APP restart / reconnect can rehydrate list green dots and the contact 3-dot row from the snapshot HTTP GET — local optimistic and SSE preview are temporary only. A server process restart clears in-memory activity (no permanent green; tools are not auto-rerun). Per-assistant lanes isolate turns across assistants/runtimes. Stale `contact-turn-end` for an older `turnID` must not clear a newer active turn.
|
|
30
43
|
- No registered project → clear `project_required` (ask the user to configure a project). Never fall back to managed assistant-workspaces.
|
|
31
44
|
- Assign must not go through the peer DM channel.
|
|
45
|
+
- `assignWork` (service) resolves the worker model via the connected catalog (`capabilities.input.image` preferred), forwards tool `variant` (cross-model drops contact variant), passes AbortSignal into create/prompt/delete/catalog, and supplies `lookupMessage` over real SDK exact lookup (`v2.session.message` → `session.message` → bounded `session.messages`). Ambiguous prompt admission returns `prompt_ambiguous` with `sessionID`/`messageID` and does **not** delete the worker; the contact-turn assign gate retains that identity so a same-args retry reuses the session and cannot blind-create another worker this turn.
|
|
46
|
+
|
|
32
47
|
- Share/queue may still use `promptAsync` on Assistant bindings.
|
|
33
48
|
|
|
34
49
|
**Registered projects + sessions (this PR)**
|
|
@@ -42,7 +57,7 @@ and keep their existing error result handling.
|
|
|
42
57
|
- `create_assistant` calls the same in-process `createAssistant` (`name`, connected OpenCode `providerID`/`modelID`, `mode: 'continuous'`). It emits an `assistant` card that opens that contact.
|
|
43
58
|
- `schedule_task` calls in-process `projectConfigRuntime.upsertScheduledTask` with the same payload as `PUT /api/projects/:id/scheduled-tasks` (`name`, `schedule.kind/time/timezone`, `execution.prompt` + provider/model) on a registered project, then best-effort `scheduledTasksRuntime.syncProject`. It emits a `schedule` card.
|
|
44
59
|
- Successful `schedule_task` also writes an assistants-owned mapping row in `assistants.sqlite` (`assistant_scheduled_task`: assistantID + projectID + taskID). Project-config execution strips unknown fields, so ownership stays out of the task payload. `GET /api/openchamber/assistants/:id/scheduled-tasks` returns those mappings joined with live `listScheduledTasks` records when possible; failed project lookups keep the mapping with `task: null`.
|
|
45
|
-
- `CONTACT_SYSTEM_PROMPT` + `formatContactToolsPrompt` tell the model to call these from natural language (开新对话 / 找项目 / 现有对话 / 建助理 / 建会话 / 排定时任务 / 给 X 说一声). A reply without the tool call does nothing; never say 已创建 / 已发送 unless the tool returned. Completions are messages-only (no native tools), so `parseContactToolCalls` accepts a fence, a whole-message JSON object, or a bare `{name, arguments}` object anywhere in the reply.
|
|
60
|
+
- `CONTACT_SYSTEM_PROMPT` + `formatContactToolsPrompt` + `formatPiCodingPrompt` tell the model to call these from natural language (开新对话 / 找项目 / 现有对话 / 建助理 / 建会话 / 排定时任务 / 给 X 说一声). Catalog lines include each tool's JSON argument schema (pi `write`/`edit` require `path`+`content` / `path`+`edits[{oldText,newText}]`). A reply without the tool call does nothing; never say 已创建 / 已发送 unless the tool returned. Completions are messages-only (no native tools), so `parseContactToolCalls` accepts a fence, a whole-message JSON object, or a bare `{name, arguments}` object anywhere in the reply. Tool results are re-injected as user turns labeled `OpenChamber tool result name=<tool> call=<id>` so multi-step turns keep call/result association.
|
|
46
61
|
- If the user asked for `new_conversation` / `clear_chat_history` / `list_projects` / `list_sessions` / `create_assistant` / `schedule_task` / `message_assistant` / `assign_session` and the first completion has no tool call, the harness runs **one** follow-up completion whose user content is only `emit the fence now, do not claim success.` If still no tool, the turn replies that it could not complete and does not fake a card. No slash commands. No second store.
|
|
47
62
|
|
|
48
63
|
**Clear memory vs clear chat history (this PR)**
|
|
@@ -88,9 +103,9 @@ Snapshots expose the latest 50 `historySessionIDs` in chronological order and `h
|
|
|
88
103
|
**Contact send admission + SSE (this PR)**
|
|
89
104
|
|
|
90
105
|
- `POST /api/openchamber/assistants/:id/messages` returns **202** `{ messageID, admitted: true, binding }` as soon as the **user row** is persisted (`status: complete`). It does **not** wait for the LLM turn. Validation errors still fail synchronously with 4xx before admit.
|
|
91
|
-
- After admit: bump revision + `openchamber:assistants-changed`, broadcast `openchamber:contact-turn-start` `{ assistantID, turnID, messageID, occurredAt }` (`turnID` = client `messageID`), then kick `runContactTurn` asynchronously (serialized per assistant).
|
|
106
|
+
- After admit: bump revision + `openchamber:assistants-changed`, register active contact turn (`queued`), broadcast `openchamber:contact-turn-start` `{ assistantID, turnID, messageID, occurredAt }` (`turnID` = client `messageID`), then kick `runContactTurn` asynchronously (serialized per assistant). Lane start marks the turn `running`. Lane start marks the turn `running` and bumps revision. Same `messageID`+payload replays admission once (`replayed: true`) without a second lane run; payload mismatch → `idempotency_conflict`. Failures persist a durable assistant `status: error` bubble for query recovery. Catalog/project list loads use a bounded deadline so the lane cannot hang forever.
|
|
92
107
|
- Contact SSE reuses `/api/openchamber/events` (no new endpoint): `openchamber:contact-bubble-delta` `{ assistantID, turnID, bubbleIndex, delta, done, occurredAt }`. Raw completion tokens are **not** painted live — they are often chain-of-thought and would appear then vanish. A short spoken preamble (e.g. 我去找一下) may appear before a tool and is kept. Planning/CoT is stripped. No-tool replies emit each stripped bubble as `{ done:true }` after parse, with a short gap between bubbles so they arrive one beat at a time.
|
|
93
|
-
- Turn end: strip/parse/tools (existing), persist **assistant** bubbles + cards only (never re-insert the user row), bump + assistants-changed, broadcast `openchamber:contact-turn-end` `{ assistantID, turnID, status: 'complete'|'error', error?, occurredAt }`. On failure the admitted user row stays; clients must not spin forever. Completing a contact turn also sends the same completion notification path as a normal contact: SMS-style title (assistant name) + body (spoken bubbles), via desktop / UI SSE / push, gated by `notifyOnCompletion`.
|
|
108
|
+
- Turn end: strip/parse/tools (existing), persist **assistant** bubbles + cards only (never re-insert the user row), clear active contact turn, bump + assistants-changed (error paths bump even without assistant rows), broadcast `openchamber:contact-turn-end` `{ assistantID, turnID, status: 'complete'|'error', error?, occurredAt }`. On failure the admitted user row stays; clients must not spin forever. Completing a contact turn also sends the same completion notification path as a normal contact: SMS-style title (assistant name) + body (spoken bubbles), via desktop / UI SSE / push, gated by `notifyOnCompletion`.
|
|
94
109
|
- In-process tests use `whenContactTurnSettled(messageID)` (not part of the HTTP JSON body).
|
|
95
110
|
- Completions: public `POST /llm/chat/completions` still rejects `stream:true`. In-process contact harness passes `onTextDelta` + `globalEventHub` through `boundCompletion` → `createChatCompletion` → throwaway generate for real tokens only.
|
|
96
111
|
|