2026-02-19 14:59:34 -08:00

99 lines
2.6 KiB
TypeScript

import { readFileSync, readdirSync, existsSync } from "node:fs";
import { join } from "node:path";
import { resolveOpenClawStateDir } from "@/lib/workspace";
export const dynamic = "force-dynamic";
type SessionEntry = {
sessionId: string;
updatedAt: number;
label?: string;
displayName?: string;
channel?: string;
model?: string;
modelProvider?: string;
thinkingLevel?: string;
inputTokens?: number;
outputTokens?: number;
totalTokens?: number;
contextTokens?: number;
compactionCount?: number;
};
type SessionRow = {
key: string;
sessionId: string;
updatedAt: number;
label?: string;
displayName?: string;
channel?: string;
model?: string;
modelProvider?: string;
thinkingLevel?: string;
inputTokens?: number;
outputTokens?: number;
totalTokens?: number;
contextTokens?: number;
};
export async function GET() {
const openclawDir = resolveOpenClawStateDir();
const agentsDir = join(openclawDir, "agents");
if (!existsSync(agentsDir)) {
return Response.json({ agents: [], sessions: [] });
}
const allSessions: SessionRow[] = [];
const agentIds: string[] = [];
try {
const entries = readdirSync(agentsDir, { withFileTypes: true });
for (const entry of entries) {
if (!entry.isDirectory()) {
continue;
}
agentIds.push(entry.name);
const storePath = join(agentsDir, entry.name, "sessions", "sessions.json");
if (!existsSync(storePath)) {
continue;
}
try {
const raw = readFileSync(storePath, "utf-8");
const store = JSON.parse(raw) as Record<string, SessionEntry>;
for (const [key, session] of Object.entries(store)) {
if (!session || typeof session !== "object") {
continue;
}
allSessions.push({
key,
sessionId: session.sessionId,
updatedAt: session.updatedAt,
label: session.label,
displayName: session.displayName,
channel: session.channel,
model: session.model,
modelProvider: session.modelProvider,
thinkingLevel: session.thinkingLevel,
inputTokens: session.inputTokens,
outputTokens: session.outputTokens,
totalTokens: session.totalTokens,
contextTokens: session.contextTokens,
});
}
} catch {
// skip unreadable store files
}
}
} catch {
// agents dir unreadable
}
// Sort by updatedAt descending
allSessions.sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0));
return Response.json({ agents: agentIds, sessions: allSessions });
}