feat(workbench): paginate session rail history

This commit is contained in:
lyon
2026-06-19 01:29:52 +08:00
parent 23a946a415
commit e444f4d80d
10 changed files with 212 additions and 20 deletions
+20 -3
View File
@@ -208,23 +208,40 @@ async function authenticateWorkbenchRead(request, response, options) {
async function handleWorkbenchSessionList(response, url, options, actor) {
if (url.searchParams.has("projectId") || url.searchParams.has("workspaceId")) return sendJson(response, 400, workbenchError("workbench_authority_removed", "Workbench session list is keyed by sessionId only."));
const limit = boundedLimit(url.searchParams.get("limit"));
const offset = cursorOffset(url.searchParams.get("cursor") ?? url.searchParams.get("after"));
const includeSessionId = safeSessionId(url.searchParams.get("includeSessionId"));
const includeRouteId = includeSessionId ?? safeConversationId(url.searchParams.get("includeSessionId"));
const readModel = createWorkbenchReadModel(options, actor);
const sessions = await readModel.listSessions({ limit, includeRouteId });
const summaries = sessions.map((session) => sessionSummary(session, options)).filter(Boolean);
const naturalPage = await readModel.listSessions({ limit: limit + 1, offset });
const pageSessions = naturalPage.slice(0, limit);
let responseSessions = pageSessions;
if (includeRouteId && !pageSessions.some((session) => sessionMatchesRouteId(session, includeRouteId))) {
const included = await readModel.getSessionByRouteId(includeRouteId);
if (included) responseSessions = [included, ...pageSessions];
}
const summaries = responseSessions.map((session) => sessionSummary(session, options)).filter(Boolean);
const hasMore = naturalPage.length > limit;
sendJson(response, 200, {
ok: true,
status: "succeeded",
contractVersion: "workbench-sessions-v1",
sessions: summaries,
count: summaries.length,
nextCursor: null,
cursor: offset > 0 ? cursorFromOffset(offset) : null,
hasMore,
nextCursor: hasMore ? cursorFromOffset(offset + limit) : null,
valuesRedacted: true,
secretMaterialStored: false
});
}
function sessionMatchesRouteId(session, routeId) {
const sessionId = safeSessionId(routeId);
if (sessionId && session?.id === sessionId) return true;
const conversationId = safeConversationId(routeId);
return Boolean(conversationId && session?.conversationId === conversationId);
}
async function handleWorkbenchSessionDetail(response, options, actor, sessionId) {
const readModel = createWorkbenchReadModel(options, actor);
const session = await readModel.getSessionByRouteId(sessionId);