feat: Archivierte Session-Versionen (OpenClaw .reset.* Files) in Diagnostic
OpenClaw resettet Sessions beim ersten chat.send nach Container-Restart (wenn abortedLastRun / systemSent Inkonsistenz erkannt wurde) und benennt die alte .jsonl in .jsonl.reset.<timestamp>.Z um. Der Inhalt war also gar nicht verloren, nur unsichtbar. Diagnostic: - handleListSessions scannt jetzt auch *.jsonl.reset.* Files - Reset-Files bekommen archived:true + resetAt-Timestamp - Neue UI-Sektion "Archivierte Versionen" (collapsible <details>) mit Export-Button, zeigt aufklappbar alle gesicherten alten Sessions - Aktivieren ist fuer Archive deaktiviert (zerstoert aktive Session) - Loeschen + Export stehen zur Verfuegung tools/export-jsonl-to-md.js: - Standalone Node-Script zum Konvertieren beliebiger .jsonl (auch reset-Files) - Nutzbar via stdin, exakt gleiche Export-Logik wie Diagnostic - Fuer Rettungsaktionen direkt auf der VM Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+24
-4
@@ -1575,14 +1575,13 @@ async function handleListSessions(clientWs) {
|
||||
try {
|
||||
log("info", "server", "Lade Sessions aus aria-core...");
|
||||
|
||||
// sessions.json als Index lesen + Datei-Details holen
|
||||
// sessions.json als Index lesen + Datei-Details holen (inkl. .reset.* Archive)
|
||||
const raw = await dockerExec("aria-core", `
|
||||
cat ${SESSIONS_DIR}/sessions.json 2>/dev/null || echo '{}' &&
|
||||
echo '===FILE_DETAILS===' &&
|
||||
for f in ${SESSIONS_DIR}/*.jsonl; do
|
||||
for f in ${SESSIONS_DIR}/*.jsonl ${SESSIONS_DIR}/*.jsonl.reset.*; do
|
||||
[ -f "$f" ] || continue
|
||||
name=$(basename "$f")
|
||||
# Nur echte User/Assistant Messages zaehlen — nicht Tool-Calls, Events etc.
|
||||
msgs=$(grep -cE '"role":"(user|assistant)"' "$f" 2>/dev/null || echo 0)
|
||||
size=$(du -h "$f" 2>/dev/null | cut -f1)
|
||||
modified=$(stat -c '%Y' "$f" 2>/dev/null || echo 0)
|
||||
@@ -1641,8 +1640,29 @@ async function handleListSessions(clientWs) {
|
||||
delete fileDetails[filename];
|
||||
}
|
||||
|
||||
// Dateien die nicht im Index stehen (Waisen / Reset-Files)
|
||||
// Dateien die nicht im Index stehen (Waisen ODER Reset-Archive)
|
||||
for (const [filename, details] of Object.entries(fileDetails)) {
|
||||
// .jsonl.reset.<ISO-Timestamp>.Z → archivierte Session (OpenClaw-Reset)
|
||||
const resetMatch = filename.match(/^([a-f0-9-]+)\.jsonl\.reset\.(.+)\.Z$/);
|
||||
if (resetMatch) {
|
||||
const id = resetMatch[1];
|
||||
// Timestamp ISO-8601 parsen (in Dateinamen: : durch - ersetzt)
|
||||
// z.B. 2026-04-18T09-49-44.814 → 2026-04-18T09:49:44.814Z
|
||||
const tsStr = resetMatch[2].replace(/T(\d{2})-(\d{2})-(\d{2})/, "T$1:$2:$3");
|
||||
const resetAt = Math.floor(new Date(tsStr + "Z").getTime() / 1000) || parseInt(details.MODIFIED) || 0;
|
||||
sessions.push({
|
||||
path: `${SESSIONS_DIR}/${filename}`,
|
||||
sessionKey: id.slice(0, 8) + "… (archiv)",
|
||||
sessionId: id,
|
||||
lines: parseInt(details.LINES) || 0,
|
||||
size: details.SIZE || "?",
|
||||
modified: resetAt,
|
||||
archived: true,
|
||||
resetAt,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
// Echte Waisen (UUID.jsonl ohne Eintrag in sessions.json)
|
||||
const id = filename.replace(".jsonl", "");
|
||||
sessions.push({
|
||||
path: `${SESSIONS_DIR}/${filename}`,
|
||||
|
||||
Reference in New Issue
Block a user