mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 09:01:22 +00:00
feat: add sessions preview rpc and menu prewarm
This commit is contained in:
@@ -6,6 +6,7 @@ import { stopSubagentsForRequester } from "../../auto-reply/reply/abort.js";
|
||||
import { clearSessionQueues } from "../../auto-reply/reply/queue.js";
|
||||
import { loadConfig } from "../../config/config.js";
|
||||
import {
|
||||
loadSessionStore,
|
||||
snapshotSessionOrigin,
|
||||
resolveMainSessionKey,
|
||||
type SessionEntry,
|
||||
@@ -19,6 +20,7 @@ import {
|
||||
validateSessionsDeleteParams,
|
||||
validateSessionsListParams,
|
||||
validateSessionsPatchParams,
|
||||
validateSessionsPreviewParams,
|
||||
validateSessionsResetParams,
|
||||
validateSessionsResolveParams,
|
||||
} from "../protocol/index.js";
|
||||
@@ -27,9 +29,12 @@ import {
|
||||
listSessionsFromStore,
|
||||
loadCombinedSessionStoreForGateway,
|
||||
loadSessionEntry,
|
||||
readSessionPreviewItemsFromTranscript,
|
||||
resolveGatewaySessionStoreTarget,
|
||||
resolveSessionTranscriptCandidates,
|
||||
type SessionsPatchResult,
|
||||
type SessionsPreviewEntry,
|
||||
type SessionsPreviewResult,
|
||||
} from "../session-utils.js";
|
||||
import { applySessionsPatchToStore } from "../sessions-patch.js";
|
||||
import { resolveSessionKeyFromResolveParams } from "../sessions-resolve.js";
|
||||
@@ -59,6 +64,74 @@ export const sessionsHandlers: GatewayRequestHandlers = {
|
||||
});
|
||||
respond(true, result, undefined);
|
||||
},
|
||||
"sessions.preview": ({ params, respond }) => {
|
||||
if (!validateSessionsPreviewParams(params)) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(
|
||||
ErrorCodes.INVALID_REQUEST,
|
||||
`invalid sessions.preview params: ${formatValidationErrors(
|
||||
validateSessionsPreviewParams.errors,
|
||||
)}`,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
const p = params as import("../protocol/index.js").SessionsPreviewParams;
|
||||
const keysRaw = Array.isArray(p.keys) ? p.keys : [];
|
||||
const keys = keysRaw
|
||||
.map((key) => String(key ?? "").trim())
|
||||
.filter(Boolean)
|
||||
.slice(0, 64);
|
||||
const limit =
|
||||
typeof p.limit === "number" && Number.isFinite(p.limit) ? Math.max(1, p.limit) : 12;
|
||||
const maxChars =
|
||||
typeof p.maxChars === "number" && Number.isFinite(p.maxChars)
|
||||
? Math.max(20, p.maxChars)
|
||||
: 240;
|
||||
|
||||
if (keys.length === 0) {
|
||||
respond(true, { ts: Date.now(), previews: [] } satisfies SessionsPreviewResult, undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
const cfg = loadConfig();
|
||||
const storeCache = new Map<string, Record<string, SessionEntry>>();
|
||||
const previews: SessionsPreviewEntry[] = [];
|
||||
|
||||
for (const key of keys) {
|
||||
try {
|
||||
const target = resolveGatewaySessionStoreTarget({ cfg, key });
|
||||
const store = storeCache.get(target.storePath) ?? loadSessionStore(target.storePath);
|
||||
storeCache.set(target.storePath, store);
|
||||
const entry =
|
||||
target.storeKeys.map((candidate) => store[candidate]).find(Boolean) ??
|
||||
store[target.canonicalKey];
|
||||
if (!entry?.sessionId) {
|
||||
previews.push({ key, status: "missing", items: [] });
|
||||
continue;
|
||||
}
|
||||
const items = readSessionPreviewItemsFromTranscript(
|
||||
entry.sessionId,
|
||||
target.storePath,
|
||||
entry.sessionFile,
|
||||
target.agentId,
|
||||
limit,
|
||||
maxChars,
|
||||
);
|
||||
previews.push({
|
||||
key,
|
||||
status: items.length > 0 ? "ok" : "empty",
|
||||
items,
|
||||
});
|
||||
} catch {
|
||||
previews.push({ key, status: "error", items: [] });
|
||||
}
|
||||
}
|
||||
|
||||
respond(true, { ts: Date.now(), previews } satisfies SessionsPreviewResult, undefined);
|
||||
},
|
||||
"sessions.resolve": ({ params, respond }) => {
|
||||
if (!validateSessionsResolveParams(params)) {
|
||||
respond(
|
||||
|
||||
Reference in New Issue
Block a user