@openchambery/web 1.18.2-beta.13 → 1.18.2-beta.15
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-BzRb9sP6.js → AgentAvatar-B4fj9PIe.js} +1 -1
- package/dist/assets/AssistantView-qRCdLcZN.js +1 -0
- package/dist/assets/{ChatContainer-hDTv6UXl.js → ChatContainer-CRWQAE6E.js} +23 -23
- package/dist/assets/{DiagramView-1hFDtyEy.js → DiagramView-B34t9o0C.js} +1 -1
- package/dist/assets/{FadeInOnReveal-oeyB_nIi.js → FadeInOnReveal-CKKU6fKI.js} +1 -1
- package/dist/assets/{Icon-DHaR0peD.js → Icon-DiIuWOuC.js} +1 -1
- package/dist/assets/{MarkdownRendererImpl-5BLw0qYH.js → MarkdownRendererImpl-CvpH7Y_l.js} +2 -2
- package/dist/assets/{MobileDetailNavigation-DIyVGM50.js → MobileDetailNavigation-CiZtnbwn.js} +1 -1
- package/dist/assets/{MobileShareBridge-BQM-WOll.js → MobileShareBridge-DwysiJW7.js} +1 -1
- package/dist/assets/MobileSurface-D1GUXnAt.js +2 -0
- package/dist/assets/{MultiRunWindow-DPOSSmY_.js → MultiRunWindow-CDENQDyB.js} +1 -1
- package/dist/assets/{OnboardingScreen-BZHN7C2r.js → OnboardingScreen-7mFH7iBm.js} +1 -1
- package/dist/assets/{OverlayScrollbar-C2pMNVMM.js → OverlayScrollbar-CmhitwHL.js} +1 -1
- package/dist/assets/SettingsView-Dv566NkF.js +25 -0
- package/dist/assets/{SettingsWindow-DJ2o4zvh.js → SettingsWindow-CbVwm2T6.js} +1 -1
- package/dist/assets/{TerminalView-BB3tvloy.js → TerminalView-BfTCj_PO.js} +1 -1
- package/dist/assets/{ToolOutputDialog-D7DqChuM.js → ToolOutputDialog-CdAO6ADz.js} +1 -1
- package/dist/assets/{appThemeRegistry-DhaoeTus.js → appThemeRegistry-Cvo1QkKA.js} +2 -2
- package/dist/assets/{button-DCUMIXDC.js → button-DaAoVF4X.js} +1 -1
- package/dist/assets/{clipboard-DF5tFLDb.js → clipboard-Cm4VHQ3n.js} +1 -1
- package/dist/assets/{collapsible-DNg5bLKV.js → collapsible-BmuQu0dq.js} +1 -1
- package/dist/assets/{context-menu-D88vCGyB.js → context-menu-C7P3at3V.js} +1 -1
- package/dist/assets/{desktopHosts-DSgGxDpI.js → desktopHosts-ZK_vkdzL.js} +1 -1
- package/dist/assets/{desktopRelayRestore-DVIx7jsz.js → desktopRelayRestore-CewM6-g5.js} +1 -1
- package/dist/assets/{diagram-cjvFqVa8.js → diagram-DAE4CZy2.js} +1 -1
- package/dist/assets/{dialog-DaSIYgrj.js → dialog-ruyemRYh.js} +1 -1
- package/dist/assets/{es-DCoGZljP.js → es-W_z2kSYf.js} +1 -1
- package/dist/assets/{fileQueries-DXvhIL_U.js → fileQueries-CmWYnRVz.js} +1 -1
- package/dist/assets/{fr-dkEoZpPz.js → fr-MYuf2QNQ.js} +1 -1
- package/dist/assets/{gitApi-DVNC4iYD.js → gitApi-GkEdeq0D.js} +1 -1
- package/dist/assets/{gitApiHttp-SLrnr8a5.js → gitApiHttp-BxGAFLTf.js} +1 -1
- package/dist/assets/{input-QS3IWgY5.js → input-XiL2-2gG.js} +1 -1
- package/dist/assets/insertionBoundaries-CDxRoLe7.js +1 -0
- package/dist/assets/{ja-bQwSsvRr.js → ja-DBkl4NXl.js} +1 -1
- package/dist/assets/{ko-Kq5C3hsv.js → ko-DwSsHsxa.js} +1 -1
- package/dist/assets/{main-CQrMAdMF.js → main-B-Pz3EI_.js} +20 -20
- package/dist/assets/{main-D4aa2ZJz.js → main-CKV54Ayt.js} +2 -2
- package/dist/assets/{markdown-worker-D-OR2e_G.js → markdown-worker-BDyY0vt6.js} +1 -1
- package/dist/assets/{markdownTheme-y_Rf6mLa.js → markdownTheme-D-aLQZaM.js} +1 -1
- package/dist/assets/{miniChat-4N2-z2vf.js → miniChat-D8VtCIh9.js} +2 -2
- package/dist/assets/mobile-B8jXmmPT.js +2 -0
- package/dist/assets/{multirun-Co8LbTjb.js → multirun-CQorhgZD.js} +1 -1
- package/dist/assets/{persistence-oSFWyKgV.js → persistence-D1lIuyqO.js} +1 -1
- package/dist/assets/{pl-CYpMAgVn.js → pl-BGLpnSSE.js} +1 -1
- package/dist/assets/projectMeta-D-t3tPnX.js +3 -0
- package/dist/assets/{pt-BR-MSPTLfTm.js → pt-BR-DuEh49lp.js} +1 -1
- package/dist/assets/{radio-CD4P-ogh.js → radio-BIl2YIoa.js} +1 -1
- package/dist/assets/renderElectronMiniChatApp-Dn0BTQ2T.js +2 -0
- package/dist/assets/renderMobileApp-BE9NXDDC.js +23 -0
- package/dist/assets/{runtimeConfig-n4QAk1lU.js → runtimeConfig-BXCt7ZsQ.js} +1 -1
- package/dist/assets/runtimeEndpointReset-B1IMFiKd.js +145 -0
- package/dist/assets/{sortable-tabs-strip-DQsv96ke.js → sortable-tabs-strip-QDIkcsUA.js} +1 -1
- package/dist/assets/{store-OURVnLSN.js → store-Cb8Q6EtD.js} +2 -2
- package/dist/assets/{terminalApi-_NnfkxgP.js → terminalApi-DpiAJlil.js} +1 -1
- package/dist/assets/{tooltip-xEnco9xY.js → tooltip-BLugzWq-.js} +1 -1
- package/dist/assets/{uk-cSkRAYFY.js → uk-CUoSz-Q8.js} +1 -1
- package/dist/assets/{url-DIZgk80M.js → url-DMs_PgIC.js} +1 -1
- package/dist/assets/useAppFontEffects-BwmqFEKp.js +7 -0
- package/dist/assets/useDesktopWindowControlsLayout-B5LGS8S5.js +1 -0
- package/dist/assets/{useEffectiveDirectory-Dc904Fjg.js → useEffectiveDirectory-BgIUpNz0.js} +1 -1
- package/dist/assets/{useFontPreferences-B-QHyR3C.js → useFontPreferences-92Qg-98H.js} +1 -1
- package/dist/assets/{useMobileNavigationStore-DNoNQA4y.js → useMobileNavigationStore-DIRiAvR1.js} +21 -21
- package/dist/assets/{useSessionAutoCleanup-bBkcz_hu.js → useSessionAutoCleanup-Ypc623bG.js} +1 -1
- package/dist/assets/{useWorkerHighlightedLines-mhBD0Do9.js → useWorkerHighlightedLines-BxaH8sAx.js} +1 -1
- package/dist/assets/{utils-Dxsi3J3l.js → utils-BxJEIWv5.js} +1 -1
- package/dist/assets/{zh-CN-BKqeT_uz.js → zh-CN-CJP5FWCK.js} +1 -1
- package/dist/assets/{zh-TW-BaNjJ8Y4.js → zh-TW-B_2h1yuo.js} +1 -1
- package/dist/index.html +7 -7
- package/dist/mini-chat.html +7 -7
- package/dist/mobile.html +7 -7
- package/package.json +1 -1
- package/server/lib/session-index/DOCUMENTATION.md +6 -1
- package/server/lib/session-index/routes.js +34 -0
- package/server/lib/session-index/routes.test.js +76 -0
- package/server/lib/session-index/service.js +52 -4
- package/server/lib/session-index/service.test.js +65 -0
- package/dist/assets/AssistantView-Bbqfj9CK.js +0 -1
- package/dist/assets/MobileSurface-KZ-kuSM-.js +0 -2
- package/dist/assets/SettingsView-DxL07Iba.js +0 -25
- package/dist/assets/insertionBoundaries-hcIB6RSd.js +0 -1
- package/dist/assets/mobile-C-RRGcDW.js +0 -2
- package/dist/assets/projectMeta-D-ncdr5Z.js +0 -3
- package/dist/assets/renderElectronMiniChatApp-D5QcQTL0.js +0 -2
- package/dist/assets/renderMobileApp-CnZZVbHU.js +0 -23
- package/dist/assets/runtimeEndpointReset-BQ5F5VZS.js +0 -145
- package/dist/assets/useAppFontEffects-DygV6JSW.js +0 -7
- package/dist/assets/useDesktopWindowControlsLayout-Cj63sNDg.js +0 -1
package/dist/index.html
CHANGED
|
@@ -552,7 +552,7 @@
|
|
|
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-CKV54Ayt.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">
|
|
@@ -560,14 +560,14 @@
|
|
|
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-D1lIuyqO.js">
|
|
564
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-ZK_vkdzL.js">
|
|
565
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-CewM6-g5.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/gitApiHttp-
|
|
569
|
-
<link rel="modulepreload" crossorigin href="/assets/terminalApi-
|
|
570
|
-
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-
|
|
568
|
+
<link rel="modulepreload" crossorigin href="/assets/gitApiHttp-BxGAFLTf.js">
|
|
569
|
+
<link rel="modulepreload" crossorigin href="/assets/terminalApi-DpiAJlil.js">
|
|
570
|
+
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-BXCt7ZsQ.js">
|
|
571
571
|
<link rel="stylesheet" crossorigin href="/assets/src-C8jn0x69.css">
|
|
572
572
|
</head>
|
|
573
573
|
<body class="h-full bg-background text-foreground">
|
package/dist/mini-chat.html
CHANGED
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
}
|
|
75
75
|
</style>
|
|
76
76
|
|
|
77
|
-
<script type="module" crossorigin src="/assets/miniChat-
|
|
77
|
+
<script type="module" crossorigin src="/assets/miniChat-D8VtCIh9.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">
|
|
@@ -82,14 +82,14 @@
|
|
|
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-D1lIuyqO.js">
|
|
86
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-ZK_vkdzL.js">
|
|
87
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-CewM6-g5.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/gitApiHttp-
|
|
91
|
-
<link rel="modulepreload" crossorigin href="/assets/terminalApi-
|
|
92
|
-
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-
|
|
90
|
+
<link rel="modulepreload" crossorigin href="/assets/gitApiHttp-BxGAFLTf.js">
|
|
91
|
+
<link rel="modulepreload" crossorigin href="/assets/terminalApi-DpiAJlil.js">
|
|
92
|
+
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-BXCt7ZsQ.js">
|
|
93
93
|
<link rel="stylesheet" crossorigin href="/assets/src-C8jn0x69.css">
|
|
94
94
|
</head>
|
|
95
95
|
<body class="h-full bg-background text-foreground">
|
package/dist/mobile.html
CHANGED
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
})();
|
|
64
64
|
</script>
|
|
65
65
|
|
|
66
|
-
<script type="module" crossorigin src="/assets/mobile-
|
|
66
|
+
<script type="module" crossorigin src="/assets/mobile-B8jXmmPT.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">
|
|
@@ -71,14 +71,14 @@
|
|
|
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-D1lIuyqO.js">
|
|
75
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-ZK_vkdzL.js">
|
|
76
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-CewM6-g5.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/gitApiHttp-
|
|
80
|
-
<link rel="modulepreload" crossorigin href="/assets/terminalApi-
|
|
81
|
-
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-
|
|
79
|
+
<link rel="modulepreload" crossorigin href="/assets/gitApiHttp-BxGAFLTf.js">
|
|
80
|
+
<link rel="modulepreload" crossorigin href="/assets/terminalApi-DpiAJlil.js">
|
|
81
|
+
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-BXCt7ZsQ.js">
|
|
82
82
|
<link rel="stylesheet" crossorigin href="/assets/src-C8jn0x69.css">
|
|
83
83
|
</head>
|
|
84
84
|
<body class="h-full bg-background text-foreground">
|
package/package.json
CHANGED
|
@@ -18,9 +18,14 @@ authoritative metadata only: a non-empty
|
|
|
18
18
|
`metadata.openchamber.assistant.assistantID` or
|
|
19
19
|
`metadata.openchamber.scheduledTask.taskID`. Title prefixes are human labels and
|
|
20
20
|
never participate in this filter. Metadata is the ownership/isolation signal;
|
|
21
|
-
`time.archived` is archive state;
|
|
21
|
+
`time.archived` is archive state; `time.pinned` is OpenChamber-owned pin state
|
|
22
|
+
(persisted as `pinned_at`, rescued across directory rebuilds, never overwritten
|
|
23
|
+
by live OpenCode upserts); titles are for recognition. The index does
|
|
22
24
|
not cache system sessions, so cold-start and live upserts stay aligned with
|
|
23
25
|
ordinary sidebar lists.
|
|
26
|
+
Pin and unpin use `POST` / `DELETE`
|
|
27
|
+
`/api/openchamber/session-index/session/:id/pin`, update `pinned_at`, then
|
|
28
|
+
`publishChange()` so revision tips broadcast `openchamber:session-index-changed`.
|
|
24
29
|
|
|
25
30
|
The server-side global OpenCode event subscriber writes session summary events
|
|
26
31
|
directly into this index. User `message.updated` events and `session.idle`
|
|
@@ -62,4 +62,38 @@ export const registerSessionIndexRoutes = (app, { sessionIndexService, sessionIn
|
|
|
62
62
|
}
|
|
63
63
|
res.json({ available: true, session: hit });
|
|
64
64
|
});
|
|
65
|
+
|
|
66
|
+
app.post('/api/openchamber/session-index/session/:id/pin', (req, res) => {
|
|
67
|
+
if (!sessionIndexService) return unsupported(res);
|
|
68
|
+
if (typeof sessionIndexService.setPinned !== 'function') {
|
|
69
|
+
return res.status(501).json({ error: 'Session pin is unavailable' });
|
|
70
|
+
}
|
|
71
|
+
const sessionId = req.params.id;
|
|
72
|
+
if (typeof sessionId !== 'string' || !sessionId.trim()) {
|
|
73
|
+
return res.status(400).json({ error: 'sessionId is required' });
|
|
74
|
+
}
|
|
75
|
+
const changed = sessionIndexService.setPinned(sessionId.trim());
|
|
76
|
+
if (!changed) {
|
|
77
|
+
return res.status(404).json({ error: 'session_not_found', sessionId: sessionId.trim() });
|
|
78
|
+
}
|
|
79
|
+
sessionIndexSyncRuntime?.publishChange?.();
|
|
80
|
+
res.status(204).end();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
app.delete('/api/openchamber/session-index/session/:id/pin', (req, res) => {
|
|
84
|
+
if (!sessionIndexService) return unsupported(res);
|
|
85
|
+
if (typeof sessionIndexService.clearPinned !== 'function') {
|
|
86
|
+
return res.status(501).json({ error: 'Session unpin is unavailable' });
|
|
87
|
+
}
|
|
88
|
+
const sessionId = req.params.id;
|
|
89
|
+
if (typeof sessionId !== 'string' || !sessionId.trim()) {
|
|
90
|
+
return res.status(400).json({ error: 'sessionId is required' });
|
|
91
|
+
}
|
|
92
|
+
const changed = sessionIndexService.clearPinned(sessionId.trim());
|
|
93
|
+
if (!changed) {
|
|
94
|
+
return res.status(404).json({ error: 'session_not_found', sessionId: sessionId.trim() });
|
|
95
|
+
}
|
|
96
|
+
sessionIndexSyncRuntime?.publishChange?.();
|
|
97
|
+
res.status(204).end();
|
|
98
|
+
});
|
|
65
99
|
};
|
|
@@ -137,4 +137,80 @@ describe('session index routes', () => {
|
|
|
137
137
|
expect(res.statusCode).toBe(404);
|
|
138
138
|
expect(res.body).toMatchObject({ error: 'session_not_found' });
|
|
139
139
|
});
|
|
140
|
+
|
|
141
|
+
it('pins a session and publishes a session-index change', () => {
|
|
142
|
+
const { app, route } = registry();
|
|
143
|
+
const setPinned = vi.fn(() => true);
|
|
144
|
+
const publishChange = vi.fn();
|
|
145
|
+
registerSessionIndexRoutes(app, {
|
|
146
|
+
sessionIndexService: {
|
|
147
|
+
snapshot: () => ({ directories: [] }),
|
|
148
|
+
setPinned,
|
|
149
|
+
},
|
|
150
|
+
sessionIndexSyncRuntime: { publishChange },
|
|
151
|
+
});
|
|
152
|
+
const res = response();
|
|
153
|
+
|
|
154
|
+
route('POST', '/api/openchamber/session-index/session/:id/pin')(
|
|
155
|
+
{ params: { id: 'ses_abc' } },
|
|
156
|
+
res,
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
expect(setPinned).toHaveBeenCalledWith('ses_abc');
|
|
160
|
+
expect(publishChange).toHaveBeenCalledTimes(1);
|
|
161
|
+
expect(res.statusCode).toBe(204);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('unpins a session and publishes a session-index change', () => {
|
|
165
|
+
const { app, route } = registry();
|
|
166
|
+
const clearPinned = vi.fn(() => true);
|
|
167
|
+
const publishChange = vi.fn();
|
|
168
|
+
registerSessionIndexRoutes(app, {
|
|
169
|
+
sessionIndexService: {
|
|
170
|
+
snapshot: () => ({ directories: [] }),
|
|
171
|
+
clearPinned,
|
|
172
|
+
},
|
|
173
|
+
sessionIndexSyncRuntime: { publishChange },
|
|
174
|
+
});
|
|
175
|
+
const res = response();
|
|
176
|
+
|
|
177
|
+
route('DELETE', '/api/openchamber/session-index/session/:id/pin')(
|
|
178
|
+
{ params: { id: 'ses_abc' } },
|
|
179
|
+
res,
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
expect(clearPinned).toHaveBeenCalledWith('ses_abc');
|
|
183
|
+
expect(publishChange).toHaveBeenCalledTimes(1);
|
|
184
|
+
expect(res.statusCode).toBe(204);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('returns 404 for pin and unpin when the session is missing', () => {
|
|
188
|
+
const { app, route } = registry();
|
|
189
|
+
const publishChange = vi.fn();
|
|
190
|
+
registerSessionIndexRoutes(app, {
|
|
191
|
+
sessionIndexService: {
|
|
192
|
+
snapshot: () => ({ directories: [] }),
|
|
193
|
+
setPinned: () => false,
|
|
194
|
+
clearPinned: () => false,
|
|
195
|
+
},
|
|
196
|
+
sessionIndexSyncRuntime: { publishChange },
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const pinRes = response();
|
|
200
|
+
route('POST', '/api/openchamber/session-index/session/:id/pin')(
|
|
201
|
+
{ params: { id: 'ses_missing' } },
|
|
202
|
+
pinRes,
|
|
203
|
+
);
|
|
204
|
+
expect(pinRes.statusCode).toBe(404);
|
|
205
|
+
expect(pinRes.body).toMatchObject({ error: 'session_not_found' });
|
|
206
|
+
|
|
207
|
+
const unpinRes = response();
|
|
208
|
+
route('DELETE', '/api/openchamber/session-index/session/:id/pin')(
|
|
209
|
+
{ params: { id: 'ses_missing' } },
|
|
210
|
+
unpinRes,
|
|
211
|
+
);
|
|
212
|
+
expect(unpinRes.statusCode).toBe(404);
|
|
213
|
+
expect(unpinRes.body).toMatchObject({ error: 'session_not_found' });
|
|
214
|
+
expect(publishChange).not.toHaveBeenCalled();
|
|
215
|
+
});
|
|
140
216
|
});
|
|
@@ -116,6 +116,7 @@ export const createSessionIndexService = ({ dbPath, getRuntimeConfig = () => nul
|
|
|
116
116
|
updated_at INTEGER NOT NULL,
|
|
117
117
|
activity_updated_at INTEGER NOT NULL,
|
|
118
118
|
archived_at INTEGER NOT NULL DEFAULT 0,
|
|
119
|
+
pinned_at INTEGER,
|
|
119
120
|
status TEXT,
|
|
120
121
|
status_changed_at INTEGER NOT NULL DEFAULT 0,
|
|
121
122
|
parent_id TEXT,
|
|
@@ -139,6 +140,12 @@ export const createSessionIndexService = ({ dbPath, getRuntimeConfig = () => nul
|
|
|
139
140
|
CREATE INDEX IF NOT EXISTS session_child_parent
|
|
140
141
|
ON session_child(runtime_key, directory, parent_id);
|
|
141
142
|
`);
|
|
143
|
+
const sessionSummaryColumns = new Set(
|
|
144
|
+
db.prepare("SELECT name FROM pragma_table_info('session_summary')").all().map((column) => column.name),
|
|
145
|
+
);
|
|
146
|
+
if (!sessionSummaryColumns.has('pinned_at')) {
|
|
147
|
+
db.exec('ALTER TABLE session_summary ADD COLUMN pinned_at INTEGER');
|
|
148
|
+
}
|
|
142
149
|
db.prepare('INSERT OR REPLACE INTO session_index_meta(key, value) VALUES (?, ?)')
|
|
143
150
|
.run('schema_version', String(SCHEMA_VERSION));
|
|
144
151
|
|
|
@@ -165,7 +172,7 @@ export const createSessionIndexService = ({ dbPath, getRuntimeConfig = () => nul
|
|
|
165
172
|
const deleteDirectoryRows = db.prepare('DELETE FROM session_summary WHERE runtime_key = ? AND directory = ?');
|
|
166
173
|
const existingSummaryState = db.prepare(`
|
|
167
174
|
SELECT session_id, has_children AS hasChildren, activity_updated_at AS activityUpdatedAt,
|
|
168
|
-
status, status_changed_at AS statusChangedAt
|
|
175
|
+
status, status_changed_at AS statusChangedAt, pinned_at AS pinnedAt
|
|
169
176
|
FROM session_summary WHERE runtime_key = ? AND directory = ?
|
|
170
177
|
`);
|
|
171
178
|
const readSummary = db.prepare(`
|
|
@@ -183,8 +190,8 @@ export const createSessionIndexService = ({ dbPath, getRuntimeConfig = () => nul
|
|
|
183
190
|
LIMIT 1 OFFSET ?
|
|
184
191
|
`);
|
|
185
192
|
const insertSummary = db.prepare(`
|
|
186
|
-
INSERT INTO session_summary(runtime_key, directory, session_id, title, created_at, updated_at, activity_updated_at, archived_at, status, status_changed_at, parent_id, has_children, assistant_id, assistant_name)
|
|
187
|
-
VALUES (@runtimeKey, @directory, @id, @title, @createdAt, @updatedAt, @activityUpdatedAt, @archivedAt, @status, @statusChangedAt, @parentID, @hasChildren, @assistantID, @assistantName)
|
|
193
|
+
INSERT INTO session_summary(runtime_key, directory, session_id, title, created_at, updated_at, activity_updated_at, archived_at, pinned_at, status, status_changed_at, parent_id, has_children, assistant_id, assistant_name)
|
|
194
|
+
VALUES (@runtimeKey, @directory, @id, @title, @createdAt, @updatedAt, @activityUpdatedAt, @archivedAt, @pinnedAt, @status, @statusChangedAt, @parentID, @hasChildren, @assistantID, @assistantName)
|
|
188
195
|
`);
|
|
189
196
|
const upsertSummary = db.prepare(`
|
|
190
197
|
INSERT INTO session_summary(runtime_key, directory, session_id, title, created_at, updated_at, activity_updated_at, archived_at, status, status_changed_at, parent_id, has_children, assistant_id, assistant_name)
|
|
@@ -259,6 +266,7 @@ export const createSessionIndexService = ({ dbPath, getRuntimeConfig = () => nul
|
|
|
259
266
|
insertSummary.run({
|
|
260
267
|
...summary,
|
|
261
268
|
activityUpdatedAt: Math.max(summary.activityUpdatedAt, toTimestamp(previous?.activityUpdatedAt)),
|
|
269
|
+
pinnedAt: previous?.pinnedAt != null ? toTimestamp(previous.pinnedAt) : null,
|
|
262
270
|
status: typeof previous?.status === 'string' ? previous.status : null,
|
|
263
271
|
statusChangedAt: toTimestamp(previous?.statusChangedAt),
|
|
264
272
|
hasChildren: toBooleanInt(summary.hasChildren ?? Boolean(previous?.hasChildren)),
|
|
@@ -364,6 +372,7 @@ export const createSessionIndexService = ({ dbPath, getRuntimeConfig = () => nul
|
|
|
364
372
|
sessions: db.prepare(`
|
|
365
373
|
SELECT session_id AS id, title, created_at AS createdAt, updated_at AS updatedAt,
|
|
366
374
|
activity_updated_at AS activityUpdatedAt, archived_at AS archivedAt,
|
|
375
|
+
pinned_at AS pinnedAt,
|
|
367
376
|
status, status_changed_at AS statusChangedAt, parent_id AS parentID,
|
|
368
377
|
has_children AS hasChildren, assistant_id AS assistantID, assistant_name AS assistantName
|
|
369
378
|
FROM session_summary WHERE runtime_key = ? AND directory = ?
|
|
@@ -373,7 +382,12 @@ export const createSessionIndexService = ({ dbPath, getRuntimeConfig = () => nul
|
|
|
373
382
|
id: session.id,
|
|
374
383
|
title: session.title,
|
|
375
384
|
directory: directory.directory,
|
|
376
|
-
time: {
|
|
385
|
+
time: {
|
|
386
|
+
created: session.createdAt,
|
|
387
|
+
updated: session.updatedAt,
|
|
388
|
+
...(session.archivedAt ? { archived: session.archivedAt } : {}),
|
|
389
|
+
...(session.pinnedAt ? { pinned: session.pinnedAt } : {}),
|
|
390
|
+
},
|
|
377
391
|
metadata: {
|
|
378
392
|
openchamber: {
|
|
379
393
|
titleRefresh: { activityUpdatedAt: session.activityUpdatedAt },
|
|
@@ -465,6 +479,38 @@ export const createSessionIndexService = ({ dbPath, getRuntimeConfig = () => nul
|
|
|
465
479
|
return result.changes > 0;
|
|
466
480
|
};
|
|
467
481
|
|
|
482
|
+
const summaryExists = db.prepare(`
|
|
483
|
+
SELECT 1 AS present FROM session_summary
|
|
484
|
+
WHERE runtime_key = ? AND session_id = ?
|
|
485
|
+
LIMIT 1
|
|
486
|
+
`);
|
|
487
|
+
|
|
488
|
+
const setPinned = (sessionID, pinnedAt = Date.now()) => {
|
|
489
|
+
if (typeof sessionID !== 'string' || !sessionID) return false;
|
|
490
|
+
const timestamp = toTimestamp(pinnedAt);
|
|
491
|
+
if (!timestamp) return false;
|
|
492
|
+
const key = runtimeKey();
|
|
493
|
+
if (!summaryExists.get(key, sessionID)) return false;
|
|
494
|
+
db.prepare(`
|
|
495
|
+
UPDATE session_summary
|
|
496
|
+
SET pinned_at = ?
|
|
497
|
+
WHERE runtime_key = ? AND session_id = ?
|
|
498
|
+
`).run(timestamp, key, sessionID);
|
|
499
|
+
return true;
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
const clearPinned = (sessionID) => {
|
|
503
|
+
if (typeof sessionID !== 'string' || !sessionID) return false;
|
|
504
|
+
const key = runtimeKey();
|
|
505
|
+
if (!summaryExists.get(key, sessionID)) return false;
|
|
506
|
+
db.prepare(`
|
|
507
|
+
UPDATE session_summary
|
|
508
|
+
SET pinned_at = NULL
|
|
509
|
+
WHERE runtime_key = ? AND session_id = ?
|
|
510
|
+
`).run(key, sessionID);
|
|
511
|
+
return true;
|
|
512
|
+
};
|
|
513
|
+
|
|
468
514
|
const replaceChildSessions = db.transaction((directory, parentSessionID, children) => {
|
|
469
515
|
const normalizedDirectory = normalizeDirectory(directory);
|
|
470
516
|
if (!normalizedDirectory || typeof parentSessionID !== 'string' || !parentSessionID) return false;
|
|
@@ -487,6 +533,8 @@ export const createSessionIndexService = ({ dbPath, getRuntimeConfig = () => nul
|
|
|
487
533
|
upsertAndReportChange,
|
|
488
534
|
touchActivity,
|
|
489
535
|
updateStatus,
|
|
536
|
+
setPinned,
|
|
537
|
+
clearPinned,
|
|
490
538
|
remove,
|
|
491
539
|
findBySessionId,
|
|
492
540
|
replaceChildSessions,
|
|
@@ -318,4 +318,69 @@ describe('Electron session index', () => {
|
|
|
318
318
|
expect(rebuilt.snapshot().directories).toEqual([]);
|
|
319
319
|
rebuilt.close();
|
|
320
320
|
});
|
|
321
|
+
|
|
322
|
+
it('exposes time.pinned in snapshots and clears it on unpin', () => {
|
|
323
|
+
const runtimeRef = { value: 'http://runtime-a.test' };
|
|
324
|
+
const service = createService(runtimeRef);
|
|
325
|
+
service.replaceDirectory({ directory: '/repo', sessions: [session('ses_a', 10)], cursor: null, hasMore: false });
|
|
326
|
+
|
|
327
|
+
expect(service.setPinned('ses_a', 55)).toBe(true);
|
|
328
|
+
expect(service.snapshot().directories[0].sessions[0].time).toMatchObject({
|
|
329
|
+
created: 9,
|
|
330
|
+
updated: 10,
|
|
331
|
+
pinned: 55,
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
expect(service.clearPinned('ses_a')).toBe(true);
|
|
335
|
+
expect(service.snapshot().directories[0].sessions[0].time).toEqual({
|
|
336
|
+
created: 9,
|
|
337
|
+
updated: 10,
|
|
338
|
+
});
|
|
339
|
+
service.close();
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it('rescues pinned_at across replaceDirectory rebuilds', () => {
|
|
343
|
+
const runtimeRef = { value: 'http://runtime-a.test' };
|
|
344
|
+
const service = createService(runtimeRef);
|
|
345
|
+
service.replaceDirectory({ directory: '/repo', sessions: [session('ses_a', 10)], cursor: null, hasMore: false });
|
|
346
|
+
expect(service.setPinned('ses_a', 77)).toBe(true);
|
|
347
|
+
|
|
348
|
+
service.replaceDirectory({
|
|
349
|
+
directory: '/repo',
|
|
350
|
+
sessions: [session('ses_a', 20)],
|
|
351
|
+
cursor: null,
|
|
352
|
+
hasMore: false,
|
|
353
|
+
now: 2000,
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
expect(service.snapshot().directories[0].sessions[0].time).toMatchObject({
|
|
357
|
+
updated: 20,
|
|
358
|
+
pinned: 77,
|
|
359
|
+
});
|
|
360
|
+
service.close();
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
it('does not let live upsert overwrite pinned_at', () => {
|
|
364
|
+
const runtimeRef = { value: 'http://runtime-a.test' };
|
|
365
|
+
const service = createService(runtimeRef);
|
|
366
|
+
service.replaceDirectory({ directory: '/repo', sessions: [session('ses_a', 10)], cursor: null, hasMore: false });
|
|
367
|
+
expect(service.setPinned('ses_a', 88)).toBe(true);
|
|
368
|
+
|
|
369
|
+
service.upsert(session('ses_a', 30));
|
|
370
|
+
|
|
371
|
+
expect(service.snapshot().directories[0].sessions[0].time.pinned).toBe(88);
|
|
372
|
+
service.close();
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
it('removes pinned rows when an archived upsert deletes the session', () => {
|
|
376
|
+
const runtimeRef = { value: 'http://runtime-a.test' };
|
|
377
|
+
const service = createService(runtimeRef);
|
|
378
|
+
service.replaceDirectory({ directory: '/repo', sessions: [session('ses_a', 10)], cursor: null, hasMore: false });
|
|
379
|
+
expect(service.setPinned('ses_a', 99)).toBe(true);
|
|
380
|
+
|
|
381
|
+
expect(service.upsert({ ...session('ses_a', 11), time: { created: 9, updated: 11, archived: 12 } })).toBe(true);
|
|
382
|
+
expect(service.snapshot().directories[0].sessions).toEqual([]);
|
|
383
|
+
expect(service.clearPinned('ses_a')).toBe(false);
|
|
384
|
+
service.close();
|
|
385
|
+
});
|
|
321
386
|
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as e,r as t}from"./rolldown-runtime-C0FnF6B9.js";import{D as n,T as r,j as i,t as a}from"./useUIStore-5agS8bsW.js";import{Ot as o,et as s,rt as c,yt as l}from"./persistence-oSFWyKgV.js";import{nt as u,rt as d}from"./vendor-base-ui-CnHfUmDN.js";import{n as f}from"./vendor-react-DLPElpoQ.js";import{r as p}from"./vendor-sonner-DVzioF3d.js";import{n as m}from"./vendor-reactuses-core-DDoDDyM9.js";import{n as h}from"./clipboard-DF5tFLDb.js";import{Ao as g,Co as _,Gr as v,Ia as y,Qi as b,Yr as x,_i as S,an as C,co as w,en as T,fn as E,ki as D,lo as O,mn as k,o as A,pn as j,za as M}from"./useMobileNavigationStore-DNoNQA4y.js";import{a as N,n as P,s as F}from"./MobileShareBridge-BQM-WOll.js";import{_ as I,a as L,c as R,d as ee,f as te,g as ne,l as re,n as ie,o as ae,p as oe,r as se,t as z,v as ce,x as B,y as le}from"./MobileDetailNavigation-DIyVGM50.js";import{i as ue,r as de}from"./useAssistantUIStore-Bq3cPj2x.js";import{t as fe}from"./AgentAvatar-BzRb9sP6.js";import{t as pe}from"./utils-Dxsi3J3l.js";import{n as me}from"./Icon-DHaR0peD.js";import{a as V,i as he,n as ge,o as H,r as U,t as W}from"./dialog-DaSIYgrj.js";import{t as _e}from"./button-DCUMIXDC.js";import{i as ve}from"./OverlayScrollbar-C2pMNVMM.js";import{F as G,P as ye,R as be,Y as xe,t as K,z as Se}from"./ChatContainer-hDTv6UXl.js";import{a as Ce,i as we,n as Te,r as Ee,t as De}from"./context-menu-D88vCGyB.js";var q=f(),J=e(d(),1),Y=u(),Oe=e=>{let t=(0,q.c)(46),{assistant:n,sessionID:r,warning:i,surface:a,onRevertMessage:o,onEditMessage:s,pendingUserMessages:c,onPendingUserMessagesMaterialized:l}=e,u=n.effectiveWorkspacePath,d;t[0]!==n.sessionGeneration||t[1]!==r?(d={sessionID:r,sessionGeneration:n.sessionGeneration},t[0]=n.sessionGeneration,t[1]=r,t[2]=d):d=t[2];let f=ce(n.id,d,a.active);f.data?.pages;let p;t[3]===f.data?.pages?p=t[4]:(p=f.data?.pages??[],t[3]=f.data?.pages,t[4]=p);let h;t[5]===p?h=t[6]:(h=S(p),t[5]=p,t[6]=h);let _=h,v;if(t[7]!==_){v=new Map;for(let e of _){let t=v.get(e.sessionID);v.set(e.sessionID,t===void 0||t===e.directory?e.directory:null)}t[7]=_,t[8]=v}else v=t[8];let y=v,b;t[9]===f?b=t[10]:(b=async()=>{(f.hasNextPage||f.isFetchNextPageError)&&await f.fetchNextPage()},t[9]=f,t[10]=b);let x=m(b),C=n.mode===`continuous`,w=ye(),T;t[11]!==u||t[12]!==y||t[13]!==w||t[14]!==r?(T=(e,t)=>{let n=e===r?u:y.get(e);if(!n||n!==t){j(e,`missing-directory`);return}k(e,t,{phoneShell:!!(w&&!g()),switchToChat:!0})},t[11]=u,t[12]=y,t[13]=w,t[14]=r,t[15]=T):T=t[15];let E=m(T),D;t[16]===C?D=t[17]:(D={...G,forkSession:!1,navigateNestedSession:!1,mutateSession:C},t[16]=C,t[17]=D);let O;t[18]===s?O=t[19]:(O=s?{onEditMessage:s}:{},t[18]=s,t[19]=O);let A;t[20]!==u||t[21]!==o||t[22]!==E||t[23]!==r||t[24]!==a.active||t[25]!==a.surfaceID||t[26]!==D||t[27]!==O?(A={kind:`embedded`,surfaceId:a.surfaceID,sessionId:r,directory:u,active:a.active,capabilities:D,onRevertMessage:o,...O,openSourceSession:E},t[20]=u,t[21]=o,t[22]=E,t[23]=r,t[24]=a.active,t[25]=a.surfaceID,t[26]=D,t[27]=O,t[28]=A):A=t[28];let M=A,N=f.isError||f.isSuccess&&!f.hasNextPage,P=f.isLoading||f.isFetchingNextPage,F;t[29]!==x||t[30]!==N||t[31]!==_||t[32]!==P?(F={entries:_,complete:N,loading:P,fetchPrevious:x},t[29]=x,t[30]=N,t[31]=_,t[32]=P,t[33]=F):F=t[33];let I;t[34]!==u||t[35]!==l||t[36]!==o||t[37]!==c||t[38]!==r||t[39]!==M||t[40]!==a||t[41]!==F||t[42]!==i?(I={sessionId:r,directory:u,composerSurface:a,sessionSurface:M,warning:i,pendingUserMessages:c,onPendingUserMessagesMaterialized:l,assistantHistory:F,onRevertMessage:o},t[34]=u,t[35]=l,t[36]=o,t[37]=c,t[38]=r,t[39]=M,t[40]=a,t[41]=F,t[42]=i,t[43]=I):I=t[43];let L=I,R;return t[44]===L?R=t[45]:(R=(0,Y.jsx)(K,{autoOpenDraft:!1,host:L}),t[44]=L,t[45]=R),R},ke=class extends Error{constructor(){super(`assistant_selection_stale`)}},Ae=(e,t)=>e.assistantID===t.assistantID&&e.transportIdentity===t.transportIdentity&&e.runtimeGeneration===t.runtimeGeneration,je=class{onBusyChange;onError;flight=null;authoritativeIdentity=null;constructor(e,t){this.onBusyChange=e,this.onError=t}activate(e){this.authoritativeIdentity&&!Ae(this.authoritativeIdentity,e)&&this.flight&&this.retire(this.flight),this.authoritativeIdentity=e}enqueue(e,t,n){if(!this.isAuthoritative(e))return Promise.reject(new ke);let r=this.flight;r||(r={identity:e,controller:new AbortController,running:!1,desired:null,waiters:[],activeWaiters:[],idleWaiters:[],retired:!1},this.flight=r),r.desired=t;let i=new Promise((e,t)=>{r.waiters.push({resolve:e,reject:t})});return r.running||(r.running=!0,this.onBusyChange(!0),this.run(r,n)),i}async flush(e){if(!this.isAuthoritative(e))throw new ke;let t=this.flight;t?.running&&await new Promise((e,n)=>t.idleWaiters.push({resolve:e,reject:n}))}assertAuthoritative(e){if(!this.isAuthoritative(e))throw new ke}dispose(){this.flight&&this.retire(this.flight),this.authoritativeIdentity=null}async run(e,t){for(;!e.retired&&e.desired;){let n=e.desired;e.desired=null;let r=e.waiters.splice(0);e.activeWaiters=r;try{if(await t({identity:e.identity,selection:n,signal:e.controller.signal}),!e.retired)for(let e of r)e.resolve()}catch(t){if(!e.retired){this.onError(t);for(let e of r)e.reject(t)}}e.activeWaiters=[]}e.running=!1;for(let t of e.idleWaiters.splice(0))t.resolve();this.flight===e&&this.onBusyChange(!1)}retire(e){e.retired=!0,e.controller.abort();let t=new ke;for(let n of e.activeWaiters.splice(0))n.reject(t);for(let n of e.waiters.splice(0))n.reject(t);for(let n of e.idleWaiters.splice(0))n.reject(t);this.flight===e&&(this.flight=null,this.onBusyChange(!1))}isAuthoritative(e){return this.authoritativeIdentity!==null&&Ae(this.authoritativeIdentity,e)}},X=(e,t)=>{let n=t.providerID??e.providerID,r=t.modelID??e.modelID,i=n!==e.providerID||r!==e.modelID;return{enabled:e.enabled,name:e.name,defaultPrompt:e.defaultPrompt,workspacePath:e.workspacePath,providerID:n,modelID:r,agent:t.agent??null,variant:i?null:t.variant??null,mode:e.mode}},Me=async(e,t,n)=>{n.assertAuthoritative();let r=n.readSnapshot()?.assistants.find(t=>t.id===e.assistantID);if(!r)throw Error(`assistant_unavailable`);try{n.assertAuthoritative(),await n.updateAssistant(r,X(r,t)),n.assertAuthoritative()}catch(i){if(n.assertAuthoritative(),n.signal.aborted)throw new ke;if(!(i instanceof B)||i.code!==`revision_conflict`)throw i;if(n.assertAuthoritative(),r=(await n.ensureSnapshot(n.signal)).assistants.find(t=>t.id===e.assistantID),n.assertAuthoritative(),!r)throw new B(`revision_conflict`,409);n.assertAuthoritative(),await n.updateAssistant(r,X(r,t)),n.assertAuthoritative()}};async function Z(e){await L(e);let t=ue.getState().defaultShareAssistant;if(t?.assistantID!==e.id)return;let n=await R();n.serverInstanceID&&t.serverInstanceID===n.serverInstanceID&&ue.getState().setDefaultShareAssistant(null)}function Ne({assistant:e,open:t,onOpenChange:n,onDeleted:r}){let{t:i}=h(),[a,o]=J.useState(!1),s=e?N(e.name).displayName||e.name:``,c=m(e=>{a&&!e||n(e)}),l=m(()=>{a||n(!1)}),u=m(async()=>{if(!(!e||a)){o(!0);try{await Z(e),r?.(e.id),n(!1),p.success(i(`assistants.settings.toast.deleted`))}catch{p.error(i(`assistants.settings.toast.deleteFailed`))}finally{o(!1)}}});return(0,Y.jsx)(W,{open:t&&e!==null,onOpenChange:c,children:(0,Y.jsxs)(ge,{className:`max-w-md`,children:[(0,Y.jsxs)(V,{children:[(0,Y.jsx)(H,{children:i(`assistants.settings.delete`)}),(0,Y.jsx)(U,{children:i(`assistants.settings.deleteConfirm`,{name:s})})]}),(0,Y.jsxs)(he,{children:[(0,Y.jsx)(_e,{size:`sm`,variant:`ghost`,onClick:l,disabled:a,children:i(`settings.common.actions.cancel`)}),(0,Y.jsx)(_e,{size:`sm`,variant:`destructive`,onClick:u,disabled:a,children:i(`settings.common.actions.delete`)})]})]})})}var Pe=[0,500,1500,4e3],Fe=(e,t,n)=>{let r=!1,i=e.map(e=>e.info.id!==t||e.info.sessionID===n?e:(r=!0,{...e,info:{...e.info,sessionID:n}}));return r?i:e},Ie=e=>{let t=e.refreshDelaysMs??Pe,n=e.sleep??(e=>new Promise(t=>setTimeout(t,e)));(async()=>{for(let r of t){if(r>0&&await n(r),!e.isCurrent())return;try{await e.refresh(e.binding);break}catch{}}})()},Le=e=>`${e.transport}\u0000${e.assistantID}`,Re=e=>({transport:e.transport,assistantID:e.assistantID}),ze=(e,t)=>e.assistantID===t.assistantID&&e.sessionID===t.sessionID&&e.directory===t.directory&&e.sessionGeneration===t.sessionGeneration&&e.transport===t.transport&&e.runtimeGeneration===t.runtimeGeneration,Be=(e,t)=>e.assistantID===t.assistantID&&e.sessionID===t.sessionID&&e.directory===t.directory&&e.sessionGeneration===t.sessionGeneration&&e.messageID===t.messageID&&e.transport===t.transport&&e.runtimeGeneration===t.runtimeGeneration,Ve=()=>{let e=new Map,t=new Map,n=1,r=e=>Le(e),i=async(e,n)=>{let i=r(e),a=t.get(i)??Promise.resolve(),o,s=new Promise(e=>{o=e}),c=a.catch(()=>void 0).then(()=>s);t.set(i,c),await a.catch(()=>void 0);try{return await n()}finally{o(),t.get(i)===c&&t.delete(i)}},a=(t,i)=>{let a=r(Re(t)),o=n++;return e.set(a,{identity:t,rollback:i,token:o}),o},o=t=>e.get(r(t))?.identity,s=t=>e.delete(r(t)),c=async e=>i(e,()=>s(e)),l=async t=>{let n=r(t),i=e.get(n);if(!i)return{kind:`none`};let a=i.token,o=i.identity,s;try{s=await i.rollback()}catch{return{kind:`blocked`,status:`failed`}}let c=e.get(n);return!c||c.token!==a||!Be(c.identity,o)?{kind:`superseded`}:s.status===`rolled-back`||s.status===`conflict`?(e.delete(n),{kind:`cleared`,status:s.status}):{kind:`blocked`,status:s.status}},u=async(t,n)=>{let i=r(t),a=e.get(i);if(!a)return{kind:`none`};if(ze(a.identity,n))return{kind:`match`};let o=a.token,s=a.identity,c=await a.rollback(),l=e.get(i);return!l||l.token!==o||!Be(l.identity,s)?{kind:`superseded`}:c.status===`rolled-back`||c.status===`conflict`?(e.delete(i),{kind:`cleared`,status:c.status}):{kind:`rollback_failed`,retained:!0,status:c.status}};return{register:a,read:o,clear:s,clearExclusive:c,retireCurrent:l,rollbackAndClearIfBindingMismatch:async(e,t)=>i(e,()=>u(e,t)),rollbackAllBestEffort:async t=>{let n=[...e.entries()];await Promise.all(n.map(async([,n])=>{if(t?.excludeTransport!==void 0&&n.identity.transport===t.excludeTransport)return;let a=Re(n.identity);await i(a,async()=>{let t=r(a),i=e.get(t);if(!i||i.token!==n.token)return;let o=i.token,s=i.identity;try{let n=await i.rollback(),r=e.get(t);if(!r||r.token!==o||!Be(r.identity,s))return;(n.status===`rolled-back`||n.status===`conflict`)&&e.delete(t)}catch{}})}))},stageExclusive:async(e,t)=>i(e,async()=>{let n=await l(e);if(n.kind===`blocked`)return{kind:`blocked`,status:n.status};let r=await t();if(!r)return{kind:`skipped`};let i=a(r.identity,r.rollback);return r.protectOnStale?{kind:`stale_protected`,token:i,identity:r.identity}:{kind:`registered`,token:i,identity:r.identity}})}},He=(e,t)=>!e?.attachments?.length||!t?[]:e.attachments.flatMap(e=>{let n=t[e.attachmentRefID];return n?[n]:[]}),Ue=(e,t)=>{let n=t??{};return e.map(e=>({partID:e.partID,text:e.text,...e.synthetic===!0?{synthetic:!0}:{},attachments:e.attachments.flatMap(e=>n[e.attachmentRefID]?[n[e.attachmentRefID]]:[])}))},We=(e,t)=>{if(t.length===0)return[...e];let n=new Map;for(let t of e)n.set(t.partID,t);for(let e of t)n.set(e.partID,e);let r=new Set,i=[];for(let t of e){let e=n.get(t.partID);e&&(i.push(e),r.add(t.partID))}for(let e of t)r.has(e.partID)||(i.push(e),r.add(e.partID));return i},Ge=t({AssistantView:()=>Qe}),Ke={},qe=[],Je=[],Ye=(e,t,n)=>[...e===void 0?[]:[{type:`text`,text:e}],...(t??[]).flatMap(e=>[{type:`text`,text:e.text,...e.synthetic===!0?{synthetic:!0}:{}},...(e.attachments??[]).map(e=>({type:`file`,mime:e.mimeType,url:e.dataUrl}))]),...(n??[]).map(e=>({type:`file`,mime:e.mimeType,url:e.dataUrl}))],Xe=e=>{let t=(0,q.c)(11),{assistant:n,onBack:r}=e,{t:i}=h(),a;t[0]===n?a=t[1]:(a=n?N(n.name):null,t[0]=n,t[1]=a);let o=a,s=n&&o?o.displayName||n.name:``,c;t[2]!==s||t[3]!==i?(c=s||i(`assistants.title`),t[2]=s,t[3]=i,t[4]=c):c=t[4];let l;t[5]===i?l=t[6]:(l=i(`assistants.actions.backToChat`),t[5]=i,t[6]=l);let u;return t[7]!==r||t[8]!==c||t[9]!==l?(u=(0,Y.jsx)(z,{title:c,backAriaLabel:l,onBack:r}),t[7]=r,t[8]=c,t[9]=l,t[10]=u):u=t[10],u},Ze=e=>{let t=(0,q.c)(45),{assistantID:n,displayName:r,avatarEmoji:i,modeLabel:a,selected:o,enabled:s,editLabel:c,deleteLabel:l,onSelect:u,onEdit:d,onDelete:f}=e,[p,h]=J.useState(!1),g;t[0]===u?g=t[1]:(g=()=>u(),t[0]=u,t[1]=g);let _=m(g),v;t[2]===d?v=t[3]:(v=()=>{h(!1),d()},t[2]=d,t[3]=v);let y=m(v),b;t[4]===f?b=t[5]:(b=()=>{h(!1),f()},t[4]=f,t[5]=b);let x=m(b),S;t[6]===Symbol.for(`react.memo_cache_sentinel`)?(S=e=>{e.preventDefault(),h(!0)},t[6]=S):S=t[6];let C=o?`border-border/50 bg-[var(--surface-elevated)]`:`border-transparent hover:bg-interactive-hover`,w=!s&&`opacity-65`,T;t[7]!==C||t[8]!==w?(T=pe(`flex w-full min-h-11 items-center gap-3 rounded-xl border px-3 py-3 text-left outline-none transition-[background-color,border-color,transform,opacity] duration-150 ease-out active:scale-[0.995] focus-visible:ring-2 focus-visible:ring-[var(--interactive-focus-ring)] motion-reduce:transition-none`,C,w),t[7]=C,t[8]=w,t[9]=T):T=t[9];let E;t[10]!==_||t[11]!==o||t[12]!==T?(E=(0,Y.jsx)(`button`,{type:`button`,role:`option`,"aria-selected":o,onClick:_,onContextMenu:S,className:T}),t[10]=_,t[11]=o,t[12]=T,t[13]=E):E=t[13];let D;t[14]!==n||t[15]!==i||t[16]!==r?(D=(0,Y.jsx)(fe,{name:n,emoji:i,size:24,label:r}),t[14]=n,t[15]=i,t[16]=r,t[17]=D):D=t[17];let O;t[18]===r?O=t[19]:(O=(0,Y.jsx)(`span`,{className:`block truncate typography-ui-label font-medium`,children:r}),t[18]=r,t[19]=O);let k;t[20]===a?k=t[21]:(k=(0,Y.jsx)(`span`,{className:`mt-0.5 block truncate typography-micro text-muted-foreground`,children:a}),t[20]=a,t[21]=k);let A;t[22]!==O||t[23]!==k?(A=(0,Y.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[O,k]}),t[22]=O,t[23]=k,t[24]=A):A=t[24];let j;t[25]!==A||t[26]!==E||t[27]!==D?(j=(0,Y.jsxs)(Ce,{render:E,children:[D,A]}),t[25]=A,t[26]=E,t[27]=D,t[28]=j):j=t[28];let M;t[29]===Symbol.for(`react.memo_cache_sentinel`)?(M=(0,Y.jsx)(me,{name:`edit`,className:`size-4`}),t[29]=M):M=t[29];let N;t[30]!==c||t[31]!==y?(N=(0,Y.jsxs)(Ee,{onClick:y,children:[M,c]}),t[30]=c,t[31]=y,t[32]=N):N=t[32];let P;t[33]===Symbol.for(`react.memo_cache_sentinel`)?(P=(0,Y.jsx)(we,{}),t[33]=P):P=t[33];let F;t[34]===Symbol.for(`react.memo_cache_sentinel`)?(F=(0,Y.jsx)(me,{name:`delete-bin`,className:`size-4`}),t[34]=F):F=t[34];let I;t[35]!==l||t[36]!==x?(I=(0,Y.jsxs)(Ee,{onClick:x,className:`text-[var(--status-error)] focus:text-[var(--status-error)] data-[highlighted]:text-[var(--status-error)] [&_svg]:text-[var(--status-error)]`,children:[F,l]}),t[35]=l,t[36]=x,t[37]=I):I=t[37];let L;t[38]!==N||t[39]!==I?(L=(0,Y.jsxs)(Te,{className:`min-w-[10rem]`,children:[N,P,I]}),t[38]=N,t[39]=I,t[40]=L):L=t[40];let R;return t[41]!==p||t[42]!==j||t[43]!==L?(R=(0,Y.jsxs)(De,{open:p,onOpenChange:h,children:[j,L]}),t[41]=p,t[42]=j,t[43]=L,t[44]=R):R=t[44],R},Qe=({activeOverride:e,onMobileBack:t})=>{let{t:u}=h(),{isMobile:d}=ve(),f=ye(),g=J.useSyncExternalStore(i,n,n),S=r(),k=a(e=>e.activeMainTab===`assistant`),j=e??k,L=a(e=>e.isMobile),R=d||L,z=I(),ce=le(),B=ce.data,V=ue(e=>e.assistantByTransport[g]??null),he=ue(e=>e.selectAssistant),ge=ue(e=>e.requestCreate),H=B?.assistants.find(e=>e.id===V)??null,U=H?.id??``,W=H?.sessionID??``,G=H?.effectiveWorkspacePath??``,K=J.useMemo(()=>o({transportIdentity:g},`assistant:${U}`),[U,g]),Ce=l(K),we=_(e=>e.draftAttachmentViews[Ce]??Ke),Te=_(e=>e.drafts[Ce]),Ee=J.useMemo(()=>{let e=He(Te,we);return e.length===0?qe:e},[we,Te]),De=Te?.attachments,q=Te?.syntheticParts,Ae=J.useMemo(()=>!De||!q?``:`${De.map(e=>e.attachmentRefID).join(``)}\u0004${q.map(e=>`${e.partID}\u0002${e.attachments.map(e=>e.attachmentRefID).join(``)}`).join(``)}`,[De,q]);J.useEffect(()=>{U&&_.getState().hydrateDraftAttachments(K)},[U,K,Ae]);let X=O(G||null,{enabled:!!G&&j}),Z=w(G||null,{enabled:!!G&&j}),Pe=T(W,G||void 0),Le=C(W,G||void 0),ze=E(W),Be=xe(),[Ge,Qe]=J.useState(()=>new Map),$e=J.useRef(0),et=J.useRef(Ve()),tt=Ge.get(U)??Je,[,nt]=J.useState(!1),rt=J.useRef(()=>{});rt.current=()=>{p.error(u(`assistants.composer.selectionSaveFailed`))};let it=J.useRef(null);it.current||=new je(nt,e=>rt.current(e));let at=J.useMemo(()=>({assistantID:U,transportIdentity:g,runtimeGeneration:S}),[U,S,g]),Q=it.current,ot=J.useMemo(()=>({transport:g,assistantID:U}),[U,g]),st=m(async(e,t=g)=>{await et.current.clearExclusive({transport:t,assistantID:e})}),ct=m(e=>{et.current.rollbackAllBestEffort(e).catch(()=>void 0)});J.useEffect(()=>{!V&&B?.assistants[0]&&he(B.assistants[0].id)},[he,V,B?.assistants]),J.useEffect(()=>{ce.isSuccess&&V&&!H&&he(B?.assistants[0]?.id??null)},[H,he,V,B?.assistants,ce.isSuccess]),J.useEffect(()=>{j&&U&&!W&&ae(U)},[j,U,W]),J.useEffect(()=>{$e.current++,Qe(new Map),ct({excludeTransport:g})},[g,S,ct]),J.useEffect(()=>()=>{$e.current++,ct()},[ct]),J.useEffect(()=>{Q.activate(at)},[Q,at]),J.useEffect(()=>()=>{Q.dispose()},[Q]),J.useEffect(()=>{U&&et.current.rollbackAndClearIfBindingMismatch(ot,{assistantID:U,sessionID:W,directory:G,sessionGeneration:H?.sessionGeneration??-1,transport:g,runtimeGeneration:S}).catch(()=>void 0)},[H?.sessionGeneration,U,G,S,W,ot,g]);let lt=m(e=>at.assistantID?Q.enqueue(at,e,async({identity:e,selection:t,signal:i})=>{await Me(e,t,{readSnapshot:()=>te(void 0,e.transportIdentity),ensureSnapshot:e=>re(e),updateAssistant:ne,signal:i,assertAuthoritative:()=>{if(Q.assertAuthoritative(e),n()!==e.transportIdentity||r()!==e.runtimeGeneration)throw new ke}})}):Promise.reject(Error(`assistant_unavailable`))),ut=J.useMemo(()=>Se(Z.data),[Z.data]),dt=m(e=>{if(!H)return;let t=y(ut,H.agent??void 0,e);if(t){let e=M({providerID:H.providerID,modelID:H.modelID,agent:H.agent},t,ut,X.data??[]),n=e.providerID===H.providerID&&e.modelID===H.modelID;lt({...e,agent:e.agent??void 0,variant:n?H.variant??void 0:void 0})}}),$=m(async(e,t)=>{e.sessionID&&await Be.ensureSessionRenderable(e.sessionID,{directory:e.directory,...t?.force?{force:!0}:{}})}),ft=H?.sessionGeneration;J.useEffect(()=>{!j||!U||!W||!G||ft===void 0||$({sessionID:W,directory:G,sessionGeneration:ft},{force:!0})},[j,U,G,$,ft,W]);let pt=m((e,t)=>{if(t.length===0)return;let n=new Set(t);Qe(t=>{let r=t.get(e);if(!r?.some(e=>n.has(e.info.id)))return t;let i=new Map(t),a=r.filter(e=>!n.has(e.info.id));return a.length>0?i.set(e,a):i.delete(e),i})}),mt=m((e,t,n)=>{Qe(r=>{let i=r.get(e);if(!i)return r;let a=Fe(i,t,n);if(a===i)return r;let o=new Map(r);return o.set(e,a),o})}),ht=m(e=>{pt(U,e)}),gt=m(async e=>{if(!W||!G)throw Error(`assistant_unavailable`);b(W,G).some(t=>t?.id===e)&&(await v(W,e,{directory:G,draftKey:K,restorePrimaryInput:!1}),await st(U))}),_t=m(async(e,t)=>{if(!H||H.mode!==`continuous`)return;if(!W||!G)throw Error(`assistant_unavailable`);if(!b(W,G).some(t=>t?.id===e))return;if(t.info.id!==e||t.info.sessionID!==W||t.info.role!==`user`)throw Error(`The selected user message is unavailable`);let i={assistantID:H.id,sessionID:W,directory:G,sessionGeneration:H.sessionGeneration,messageID:e,transport:g,runtimeGeneration:S},a=Re(i),o=await et.current.stageExclusive(a,async()=>{let a=await x(W,e,t,{directory:G,draftKey:K}),o=n()===i.transport&&r()===i.runtimeGeneration,s=o?te(void 0,i.transport)?.assistants.find(e=>e.id===i.assistantID):void 0,c=!!(s&&s.mode===`continuous`&&s.sessionID===i.sessionID&&s.sessionGeneration===i.sessionGeneration&&(s.effectiveWorkspacePath??``)===i.directory);if(o&&c)return{identity:i,rollback:()=>a.rollback()};let l=await a.rollback();return l.status===`failed`||l.status===`skipped`?{identity:i,rollback:()=>a.rollback(),protectOnStale:!0}:null});if(o.kind===`blocked`)throw Error(`assistant_stage_message_edit_prior_blocked`);if(o.kind===`stale_protected`)throw Error(`assistant_stage_message_edit_rollback_failed`)}),vt=J.useMemo(()=>{let e=D(K,()=>_.getState());return{busy:!1,attachments:Ee,addAttachment:t=>e.addLocal(t),removeAttachment:t=>e.removeByAttachmentID(t),clearAttachments:()=>e.clearRootAttachments(),restoreAttachments:t=>e.restoreRootAttachments(t),pendingInput:null,consumePendingInput:()=>null,pendingPreset:null,consumePendingPreset:()=>null,consumeSyntheticParts:()=>{let e=_.getState(),t=e.draftAttachmentViews[l(K)]??Ke,n=e.consumeDraftSyntheticParts(K,F);return n?Ue(n,t):null},restoreSyntheticParts:e=>{(async()=>{let t=_.getState(),n=e.map(e=>({partID:e.partID??s(),text:e.text,attachments:[],...e.synthetic===!0?{synthetic:!0}:{}})),r=We(t.getDraft(K)?.syntheticParts??[],n);t.setDraftSyntheticParts(K,r);for(let r=0;r<n.length;r++){let i=n[r].partID;for(let n of e[r]?.attachments??[])n.source===`server`&&n.dataUrl?t.addDraftDurableAttachment(K,{attachmentID:n.id,filename:n.filename,mimeType:n.mimeType,size:n.size,source:`server`,url:n.dataUrl,serverPath:n.serverPath,partID:i}):await t.addDraftLocalAttachment(K,n.file,{attachmentID:n.id,filename:n.filename,source:n.source===`vscode`?`vscode`:`local`,vscodePath:n.vscodePath,vscodeSource:n.vscodeSource===`selection`?`selection`:void 0,partID:i})}})()},inlineDrafts:[],removeInlineDraft:()=>{},restoreInlineDrafts:()=>{},history:ze,captureRuntime:()=>_.getState().captureDraftRuntime(),getDraft:e=>_.getState().getDraft(e),abortPrompt:{sessionID:null,clear:()=>{}}}},[Ee,K,ze]),yt=J.useMemo(()=>{let e=(X.data??[]).find(e=>e.id===H?.providerID)?.models?.find(e=>e.id===H?.modelID);return be(e)},[H?.modelID,H?.providerID,X.data]),bt=Pe.length>0,xt=J.useMemo(()=>{if(!H||!W||!G)return null;let e={sessionID:W,directory:G,sessionGeneration:H.sessionGeneration};return{kind:`secondary`,surfaceID:`assistant:${H.id}`,active:j,sessionID:W,directory:G,draftKey:K,transportIdentity:g,runtimeGeneration:S,deliveryTarget:{kind:`assistant`,assistantID:H.id},resources:vt,...H.mode===`stateless`?{queueSessionID:`assistant:${H.id}`}:{},selection:{value:{providerID:H.providerID,modelID:H.modelID,agent:H.agent??void 0,variant:H.variant??void 0},catalog:{providers:X.data??[],agents:ut,variants:yt,variantsReady:X.isSuccess,ready:X.isSuccess&&Z.isSuccess,loading:X.isPending||Z.isPending,error:X.isError||Z.isError},change:lt,flush:()=>Q.flush(at)},activity:{phase:Le?.type===`busy`?`busy`:Le?.type===`retry`?`retry`:`idle`,canAbort:Le?.type===`busy`||Le?.type===`retry`},commands:{sessionID:W,hasMessages:bt,hasNewDraft:!1},commandPolicy:e=>e.name!==`fork`&&e.name!==`thread`,backend:{send:async t=>{let n;for(let t of b(e.sessionID,e.directory)){let e=typeof t?.id==`string`?t.id:``;/^msg_[0-9a-f]{12}[0-9A-Za-z]{14}$/.test(e)&&(!n||e>n)&&(n=e)}let r=c(`msg`,n);t.options?.commitStagedMessageEdit&&et.current.clear({transport:g,assistantID:H.id});let i=A({messageID:r,sessionID:e.sessionID,providerID:t.providerID??H.providerID,modelID:t.modelID??H.modelID,agent:t.agent??H.agent??void 0,text:t.text,attachments:t.attachments,additionalParts:t.parts});Qe(e=>{let t=new Map(e);return t.set(H.id,[...e.get(H.id)??[],i]),t});let a;try{a=await oe(H.id,e,r,Ye(t.text,t.parts,t.attachments))}catch(e){throw pt(H.id,[r]),e}if(z.data?.serverInstanceID){let e=N(H.name);P({serverInstanceID:z.data.serverInstanceID,assistantID:H.id,name:e.displayName||H.name,avatarSeed:H.id,...e.avatarEmoji?{avatarEmoji:e.avatarEmoji}:{}}).catch(()=>void 0)}a.binding.sessionID&&mt(H.id,r,a.binding.sessionID);let o=$e.current;Ie({binding:a.binding,refresh:t=>$(t,{force:t.sessionID!==e.sessionID||t.sessionGeneration!==e.sessionGeneration}),isCurrent:()=>$e.current===o})},sendQueued:async()=>{throw Error(`assistant-server-queue-required`)},create:async()=>{let e=await ee(H.id);await st(H.id),await $(e,{force:!0})},compact:async()=>{let t=await se(H.id,e);await st(H.id),await $(t.binding,{force:!0})},abort:async()=>{await ie(H.id,e)}},shortcuts:{cycle:dt,new:async()=>{let e=await ee(H.id);await st(H.id),await $(e,{force:!0})},abort:async()=>{await ie(H.id,e)},submit:()=>{}}}},[j,H,z.data?.serverInstanceID,lt,st,dt,G,K,bt,X.data,X.isError,X.isPending,X.isSuccess,Z.isError,Z.isPending,Z.isSuccess,$,mt,pt,vt,S,Q,at,W,Le,g,yt,ut]),St=m(()=>{if(ge(),f){f.openSettings();return}let e=a.getState();e.setSettingsPage(`assistants`),e.setSettingsDialogOpen(!0)}),Ct=m(e=>{de(e,f?{openMobileSettings:f.openSettings}:void 0)}),[wt,Tt]=J.useState(null),Et=m(e=>{Tt(e)}),Dt=m(e=>{e||Tt(null)}),Ot=m(()=>{a.getState().setActiveMainTab(`chat`)}),kt=m(()=>{if(t){t();return}Ot()}),At=(e,t,n,r)=>(0,Y.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[R?(0,Y.jsx)(Xe,{assistant:H,onBack:kt}):null,(0,Y.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col items-center justify-center px-6 text-center`,children:[(0,Y.jsx)(me,{name:e,className:`size-6 text-muted-foreground`}),(0,Y.jsx)(`h1`,{className:`mt-4 typography-ui-header font-semibold`,children:t}),n?(0,Y.jsx)(`p`,{className:`mt-2 max-w-md typography-ui text-muted-foreground`,children:n}):null,r?(0,Y.jsx)(`div`,{className:`mt-5`,children:r}):null]})]});if(z.isPending||ce.isPending)return At(`ai-agent`,u(`assistants.state.unavailable`));if(z.isError||!z.data?.supported||!z.data.enabled||!B?.enabled)return At(`cloud-off`,u(`assistants.state.unavailable`));if(!B.assistants.length)return At(`ai-agent`,u(`assistants.onboarding.title`),u(`assistants.onboarding.description`),(0,Y.jsx)(_e,{onClick:St,children:u(`assistants.onboarding.action`)}));if(!H)return At(`ai-agent`,u(`assistants.state.unavailable`));if(!xt)return(0,Y.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col bg-background`,children:[R?(0,Y.jsx)(Xe,{assistant:H,onBack:kt}):null,(0,Y.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col items-center justify-center gap-3 px-6`,"aria-busy":`true`,"aria-label":u(`assistants.state.unavailable`),children:[(0,Y.jsx)(`div`,{className:`size-10 animate-pulse rounded-xl bg-[var(--surface-muted)] motion-reduce:animate-none`}),(0,Y.jsx)(`div`,{className:`h-3.5 w-36 animate-pulse rounded-md bg-[var(--surface-muted)] motion-reduce:animate-none`})]})]});let jt=N(H.name),Mt=H.enabled?ce.isError?u(`assistants.state.staleSnapshot`):null:u(`assistants.state.assistantDisabled`);return(0,Y.jsxs)(`div`,{className:`relative flex h-full min-h-0 overflow-hidden bg-background`,"data-presentation":`workspace`,children:[R?null:(0,Y.jsxs)(`section`,{className:`flex h-full min-h-0 w-[clamp(16rem,22vw,20rem)] shrink-0 flex-col overflow-hidden`,children:[(0,Y.jsx)(`header`,{className:`shrink-0 px-4 pb-3 pt-4 sm:px-5`,children:(0,Y.jsx)(`h1`,{className:`truncate typography-ui-label font-semibold text-foreground`,children:u(`assistants.title`)})}),(0,Y.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-3 pb-4 sm:px-4`,role:`listbox`,"aria-label":u(`assistants.listAria`),children:(0,Y.jsx)(`div`,{className:`flex flex-col gap-1 border-t border-border/40 pt-3`,children:B.assistants.map(e=>{let t=e.id===V,n=N(e.name);return(0,Y.jsx)(Ze,{assistantID:e.id,displayName:n.displayName,avatarEmoji:n.avatarEmoji??void 0,modeLabel:e.mode===`stateless`?u(`assistants.mode.stateless`):u(`assistants.mode.continuous`),selected:t,enabled:e.enabled,editLabel:u(`assistants.menu.edit`),deleteLabel:u(`assistants.settings.delete`),onSelect:()=>he(e.id),onEdit:()=>Ct(e.id),onDelete:()=>Et(e)},e.id)})})})]}),(0,Y.jsx)(Ne,{assistant:wt,open:wt!==null,onOpenChange:Dt}),(0,Y.jsxs)(`div`,{className:pe(`flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden bg-background`,!R&&`border-l border-border/60`),children:[R?(0,Y.jsx)(Xe,{assistant:H,onBack:kt}):(0,Y.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-3 border-b border-border/40 px-4 sm:px-5`,children:[(0,Y.jsx)(fe,{name:H.id,emoji:jt.avatarEmoji,size:24,label:jt.displayName||H.name}),(0,Y.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Y.jsx)(`div`,{className:`truncate typography-ui-label font-medium`,children:jt.displayName}),(0,Y.jsx)(`div`,{className:`mt-0.5 truncate typography-micro leading-none text-muted-foreground/70`,children:H.mode===`stateless`?u(`assistants.conversation.statelessHint`):u(`assistants.conversation.continuousHint`)})]})]}),(0,Y.jsx)(Oe,{onRevertMessage:gt,onEditMessage:H.mode===`continuous`?_t:void 0,assistant:H,sessionID:W,warning:Mt,surface:xt,pendingUserMessages:tt,onPendingUserMessagesMaterialized:ht})]})]})};export{Ge as n,Ne as r,Qe as t};
|