refactor(ui): simplify model button and optimize session index loading

- StatusBar model button: show model name instead of provider, click opens
  settings directly (scrolls to default model section), remove dropdown
- SessionIndexSection: replace N serial pluginQuery calls with single batch
  API (GET /_web/sessions/index-stats), add IntersectionObserver lazy loading
- Full-stack implementation: CLI route, Electron IPC/Worker, frontend adapters

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
diguaandCursor committed 2026-05-31 10:28:29 +08:00
1 parent 783d61f742
commit 9bc0c4279d
15 files changed
+140 -109

No files matched your search

@@ -2,6 +2,10 @@ import type { FastifyInstance } from 'fastify'
import { sessionIndexService, type SessionRuntimeAdapter } from '@openchatlab/node-runtime'
export function registerSessionIndexRoutes(server: FastifyInstance, adapter: SessionRuntimeAdapter): void {
server.get('/_web/sessions/index-stats', async () => {
return sessionIndexService.getAllIndexStats(adapter)
})
server.post<{
Params: { id: string }
Body: { gapThreshold?: number }
+9
View File
@@ -836,6 +836,15 @@ export function registerChatHandlers(ctx: IpcContext): void {
}
})
ipcMain.handle('session:getAllIndexStats', async () => {
try {
return await worker.getAllIndexStats()
} catch (error) {
console.error('Failed to get all index stats:', error)
return []
}
})
/**
* 清空会话索引
*/
+2
View File
@@ -60,6 +60,7 @@ import {
clearSessions,
hasSessionIndex,
getSessionStats,
getAllIndexStats,
updateSessionGapThreshold,
getSessions,
getSessionsByTimeRange,
@@ -228,6 +229,7 @@ const syncHandlers: Record<string, (payload: any) => any> = {
clearSessions: (p) => clearSessions(p.sessionId),
hasSessionIndex: (p) => hasSessionIndex(p.sessionId),
getSessionStats: (p) => getSessionStats(p.sessionId),
getAllIndexStats: (p) => getAllIndexStats(p.sessionIds),
updateSessionGapThreshold: (p) => updateSessionGapThreshold(p.sessionId, p.gapThreshold),
getSessions: (p) => getSessions(p.sessionId),
getSessionsByTimeRange: (p) => getSessionsByTimeRange(p.sessionId, p.startTs, p.endTs),
@@ -27,6 +27,7 @@ export {
clearSessions,
hasSessionIndex,
getSessionStats,
getAllIndexStats,
updateSessionGapThreshold,
getSessions,
getSessionsByTimeRange,
@@ -82,6 +82,19 @@ export function getSessionStats(sessionId: string): SessionIndexStats {
})
}
export interface SessionIndexStatusItem {
sessionId: string
hasIndex: boolean
sessionCount: number
}
export function getAllIndexStats(sessionIds: string[]): SessionIndexStatusItem[] {
return sessionIds.map((sessionId) => {
const stats = getSessionStats(sessionId)
return { sessionId, hasIndex: stats.hasIndex, sessionCount: stats.sessionCount }
})
}
export function updateSessionGapThreshold(sessionId: string, gapThreshold: number | null): void {
withWritableAdapter(sessionId, (adapter) => coreUpdateSessionGapThreshold(adapter, gapThreshold))
}
@@ -746,6 +746,14 @@ export async function getSessionStats(sessionId: string): Promise<SessionStats>
return sendToWorker('getSessionStats', { sessionId })
}
export async function getAllIndexStats(): Promise<
Array<{ sessionId: string; hasIndex: boolean; sessionCount: number }>
> {
const sessions = await getAllSessions()
const sessionIds = sessions.map((s: any) => s.id)
return sendToWorker('getAllIndexStats', { sessionIds })
}
/**
* 更新单个聊天的会话切分阈值
*/
+7
View File
@@ -256,6 +256,13 @@ export const sessionApi = {
return ipcRenderer.invoke('session:getStats', sessionId)
},
/**
* 批量获取所有会话的索引状态
*/
getAllIndexStats: (): Promise<Array<{ sessionId: string; hasIndex: boolean; sessionCount: number }>> => {
return ipcRenderer.invoke('session:getAllIndexStats')
},
/**
* 清空会话索引
*/
+1
View File
@@ -1128,6 +1128,7 @@ interface SessionApi {
generateIncremental: (sessionId: string, gapThreshold?: number) => Promise<number>
hasIndex: (sessionId: string) => Promise<boolean>
getStats: (sessionId: string) => Promise<SessionStats>
getAllIndexStats: () => Promise<Array<{ sessionId: string; hasIndex: boolean; sessionCount: number }>>
clear: (sessionId: string) => Promise<boolean>
updateGapThreshold: (sessionId: string, gapThreshold: number | null) => Promise<boolean>
getSessions: (sessionId: string) => Promise<ChatSessionItem[]>