@@ -14,7 +14,45 @@ interface SessionManagementRuntimeApp {
1414 GetCodexSessionManagementSnapshot ?: ( ) => Promise < unknown > ;
1515 RefreshCodexSessionManagementSnapshot ?: ( ) => Promise < unknown > ;
1616 GetCodexSessionDetail ?: ( sessionID : string ) => Promise < unknown > ;
17- UpdateCodexSessionProviders ?: ( input : { projectID : string ; mappings : Array < { sourceProvider : string ; targetProvider : string } > } ) => Promise < unknown > ;
17+ UpdateCodexSessionProviders ?: ( input : {
18+ projectID : string ;
19+ mappings : Array < { sourceProvider : string ; targetProvider : string } > ;
20+ snapshot ?: RuntimeSessionManagementSnapshot ;
21+ } ) => Promise < unknown > ;
22+ }
23+
24+ interface RuntimeSessionManagementSnapshot {
25+ projectCount : number ;
26+ sessionCount : number ;
27+ activeSessionCount : number ;
28+ archivedSessionCount : number ;
29+ lastScanAt : string ;
30+ providerCounts : Record < string , number > ;
31+ projects : Array < {
32+ id : string ;
33+ name : string ;
34+ providerCounts : Record < string , number > ;
35+ sessionCount : number ;
36+ activeSessionCount : number ;
37+ archivedSessionCount : number ;
38+ lastActiveAt : string ;
39+ providerSummary : string ;
40+ sessions : Array < {
41+ id : string ;
42+ sessionID : string ;
43+ projectID : string ;
44+ projectName : string ;
45+ title : string ;
46+ status : string ;
47+ archived : boolean ;
48+ messageCount : number ;
49+ roleSummary : string ;
50+ updatedAt : string ;
51+ fileLabel : string ;
52+ summary : string ;
53+ provider : string ;
54+ } > ;
55+ } > ;
1856}
1957
2058declare global {
@@ -28,11 +66,21 @@ declare global {
2866}
2967
3068function resolveRuntimeMethod < T extends keyof SessionManagementRuntimeApp > ( methodName : T ) {
69+ const method = getRuntimeMethod ( methodName ) ;
70+
71+ if ( ! method ) {
72+ throw new Error ( `当前运行时缺少 ${ methodName } 绑定。` ) ;
73+ }
74+
75+ return method ;
76+ }
77+
78+ function getRuntimeMethod < T extends keyof SessionManagementRuntimeApp > ( methodName : T ) {
3179 const app = globalThis . window ?. go ?. main ?. App ;
3280 const method = app ?. [ methodName ] ;
3381
3482 if ( typeof method !== 'function' ) {
35- throw new Error ( `当前运行时缺少 ${ methodName } 绑定。` ) ;
83+ return null ;
3684 }
3785
3886 return method . bind ( app ) as NonNullable < SessionManagementRuntimeApp [ T ] > ;
@@ -141,57 +189,141 @@ async function updateDevProviders(projectID: string, mappings: Array<{ sourcePro
141189 throw lastError ?? new Error ( 'session management provider merge unavailable' ) ;
142190}
143191
192+ function addProviderCount ( counts : Record < string , number > , provider : string ) {
193+ const key = provider . trim ( ) ;
194+ if ( ! key || key === '—' ) {
195+ return ;
196+ }
197+ counts [ key ] = ( counts [ key ] ?? 0 ) + 1 ;
198+ }
199+
200+ function toRuntimeSessionManagementSnapshot (
201+ snapshot ?: SessionManagementSnapshot ,
202+ ) : RuntimeSessionManagementSnapshot | undefined {
203+ if ( ! snapshot ) {
204+ return undefined ;
205+ }
206+
207+ const providerCounts : Record < string , number > = { } ;
208+ const projects = snapshot . projects . map ( ( project ) => {
209+ const projectProviderCounts : Record < string , number > = { } ;
210+ const sessions = project . sessions . map ( ( session ) => {
211+ addProviderCount ( providerCounts , session . provider ) ;
212+ addProviderCount ( projectProviderCounts , session . provider ) ;
213+ return {
214+ id : session . id ,
215+ sessionID : session . id ,
216+ projectID : project . id ,
217+ projectName : project . name ,
218+ title : session . title ,
219+ status : session . status ,
220+ archived : session . status === 'archived' ,
221+ messageCount : session . messageCount ,
222+ roleSummary : session . roleSummary ,
223+ updatedAt : session . updatedAt ,
224+ fileLabel : session . fileLabel ,
225+ summary : session . summary ,
226+ provider : session . provider ,
227+ } ;
228+ } ) ;
229+
230+ return {
231+ id : project . id ,
232+ name : project . name ,
233+ providerCounts : projectProviderCounts ,
234+ sessionCount : project . sessionCount ,
235+ activeSessionCount : project . activeSessionCount ,
236+ archivedSessionCount : project . archivedSessionCount ,
237+ lastActiveAt : project . lastActiveAt ,
238+ providerSummary : project . providerSummary ,
239+ sessions,
240+ } ;
241+ } ) ;
242+
243+ return {
244+ projectCount : snapshot . stats . projectCount ,
245+ sessionCount : snapshot . stats . sessionCount ,
246+ activeSessionCount : snapshot . stats . activeSessionCount ,
247+ archivedSessionCount : snapshot . stats . archivedSessionCount ,
248+ lastScanAt : snapshot . stats . lastScanAt ,
249+ providerCounts,
250+ projects,
251+ } ;
252+ }
253+
144254export async function getCodexSessionManagementSnapshot ( ) : Promise < SessionManagementSnapshot > {
145255 if ( hasSessionManagementPreviewMode ( ) ) {
146256 return getSessionManagementPreviewSnapshot ( ) ;
147257 }
258+ const getSnapshot = getRuntimeMethod ( 'GetCodexSessionManagementSnapshot' ) ;
259+ if ( getSnapshot ) {
260+ const raw = await getSnapshot ( ) ;
261+ return mapSessionManagementSnapshotResponse ( raw ) ;
262+ }
148263 if ( canUseSessionManagementDevHTTP ( ) ) {
149264 return mapSessionManagementSnapshotResponse ( await loadDevSnapshot ( false ) ) ;
150265 }
151266
152- const getSnapshot = resolveRuntimeMethod ( 'GetCodexSessionManagementSnapshot' ) ;
153- const raw = await getSnapshot ( ) ;
267+ const missingSnapshot = resolveRuntimeMethod ( 'GetCodexSessionManagementSnapshot' ) ;
268+ const raw = await missingSnapshot ( ) ;
154269 return mapSessionManagementSnapshotResponse ( raw ) ;
155270}
156271
157272export async function refreshCodexSessionManagementSnapshot ( ) : Promise < SessionManagementSnapshot > {
158273 if ( hasSessionManagementPreviewMode ( ) ) {
159274 return getSessionManagementPreviewSnapshot ( ) ;
160275 }
276+ const refreshSnapshot = getRuntimeMethod ( 'RefreshCodexSessionManagementSnapshot' ) ;
277+ if ( refreshSnapshot ) {
278+ const raw = await refreshSnapshot ( ) ;
279+ return mapSessionManagementSnapshotResponse ( raw ) ;
280+ }
161281 if ( canUseSessionManagementDevHTTP ( ) ) {
162282 return mapSessionManagementSnapshotResponse ( await loadDevSnapshot ( true ) ) ;
163283 }
164284
165- const refreshSnapshot = resolveRuntimeMethod ( 'RefreshCodexSessionManagementSnapshot' ) ;
166- const raw = await refreshSnapshot ( ) ;
285+ const missingRefreshSnapshot = resolveRuntimeMethod ( 'RefreshCodexSessionManagementSnapshot' ) ;
286+ const raw = await missingRefreshSnapshot ( ) ;
167287 return mapSessionManagementSnapshotResponse ( raw ) ;
168288}
169289
170290export async function getCodexSessionDetail ( sessionID : string ) : Promise < SessionDetail > {
171291 if ( hasSessionManagementPreviewMode ( ) ) {
172292 return getSessionManagementPreviewDetail ( sessionID ) ;
173293 }
294+ const getDetail = getRuntimeMethod ( 'GetCodexSessionDetail' ) ;
295+ if ( getDetail ) {
296+ const raw = await getDetail ( sessionID ) ;
297+ return mapSessionDetailResponse ( raw ) ;
298+ }
174299 if ( canUseSessionManagementDevHTTP ( ) ) {
175300 return mapSessionDetailResponse ( await loadDevDetail ( sessionID ) ) ;
176301 }
177302
178- const getDetail = resolveRuntimeMethod ( 'GetCodexSessionDetail' ) ;
179- const raw = await getDetail ( sessionID ) ;
303+ const missingDetail = resolveRuntimeMethod ( 'GetCodexSessionDetail' ) ;
304+ const raw = await missingDetail ( sessionID ) ;
180305 return mapSessionDetailResponse ( raw ) ;
181306}
182307
183308export async function updateCodexSessionProviders (
184309 projectID : string ,
185310 mappings : Array < { sourceProvider : string ; targetProvider : string } > ,
311+ snapshot ?: SessionManagementSnapshot ,
186312) : Promise < SessionManagementSnapshot > {
187313 if ( hasSessionManagementPreviewMode ( ) ) {
188314 throw new Error ( 'preview 模式不支持修改 provider' ) ;
189315 }
316+ const updateProviders = getRuntimeMethod ( 'UpdateCodexSessionProviders' ) ;
317+ const runtimeSnapshot = toRuntimeSessionManagementSnapshot ( snapshot ) ;
318+ if ( updateProviders ) {
319+ const raw = await updateProviders ( { projectID, mappings, snapshot : runtimeSnapshot } ) ;
320+ return mapSessionManagementSnapshotResponse ( raw ) ;
321+ }
190322 if ( canUseSessionManagementDevHTTP ( ) ) {
191323 return mapSessionManagementSnapshotResponse ( await updateDevProviders ( projectID , mappings ) ) ;
192324 }
193325
194- const updateProviders = resolveRuntimeMethod ( 'UpdateCodexSessionProviders' ) ;
195- const raw = await updateProviders ( { projectID, mappings } ) ;
326+ const missingUpdateProviders = resolveRuntimeMethod ( 'UpdateCodexSessionProviders' ) ;
327+ const raw = await missingUpdateProviders ( { projectID, mappings, snapshot : runtimeSnapshot } ) ;
196328 return mapSessionManagementSnapshotResponse ( raw ) ;
197329}
0 commit comments