mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 19:40:42 +00:00
Fix dreaming replay, repair polluted artifacts, and gate wiki tabs (#65138)
* fix(active-memory): preserve parent channel context for recall runs * fix(active-memory): keep recall runs on the resolved channel * fix(active-memory): prefer resolved recall channel over wrapper hints * fix(active-memory): trust explicit recall channel hints * fix(active-memory): rank recall channel fallbacks by trust * Fix dreaming replay and recovery flows * fix: prevent dreaming event loss and diary write races * chore: add changelog entry for memory fixes * fix: harden dreaming repair and diary writes * fix: harden dreaming artifact archive naming
This commit is contained in:
@@ -17,8 +17,32 @@ export type SessionFileEntry = {
|
||||
content: string;
|
||||
/** Maps each content line (0-indexed) to its 1-indexed JSONL source line. */
|
||||
lineMap: number[];
|
||||
/** True when this transcript belongs to an internal dreaming narrative run. */
|
||||
generatedByDreamingNarrative?: boolean;
|
||||
};
|
||||
|
||||
function isDreamingNarrativeBootstrapRecord(record: unknown): boolean {
|
||||
if (!record || typeof record !== "object" || Array.isArray(record)) {
|
||||
return false;
|
||||
}
|
||||
const candidate = record as {
|
||||
type?: unknown;
|
||||
customType?: unknown;
|
||||
data?: unknown;
|
||||
};
|
||||
if (
|
||||
candidate.type !== "custom" ||
|
||||
candidate.customType !== "openclaw:bootstrap-context:full" ||
|
||||
!candidate.data ||
|
||||
typeof candidate.data !== "object" ||
|
||||
Array.isArray(candidate.data)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
const runId = (candidate.data as { runId?: unknown }).runId;
|
||||
return typeof runId === "string" && runId.startsWith("dreaming-narrative-");
|
||||
}
|
||||
|
||||
export async function listSessionFilesForAgent(agentId: string): Promise<string[]> {
|
||||
const dir = resolveSessionTranscriptsDirForAgent(agentId);
|
||||
try {
|
||||
@@ -79,6 +103,7 @@ export async function buildSessionEntry(absPath: string): Promise<SessionFileEnt
|
||||
const lines = raw.split("\n");
|
||||
const collected: string[] = [];
|
||||
const lineMap: number[] = [];
|
||||
let generatedByDreamingNarrative = false;
|
||||
for (let jsonlIdx = 0; jsonlIdx < lines.length; jsonlIdx++) {
|
||||
const line = lines[jsonlIdx];
|
||||
if (!line.trim()) {
|
||||
@@ -90,6 +115,9 @@ export async function buildSessionEntry(absPath: string): Promise<SessionFileEnt
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
if (!generatedByDreamingNarrative && isDreamingNarrativeBootstrapRecord(record)) {
|
||||
generatedByDreamingNarrative = true;
|
||||
}
|
||||
if (
|
||||
!record ||
|
||||
typeof record !== "object" ||
|
||||
@@ -124,6 +152,7 @@ export async function buildSessionEntry(absPath: string): Promise<SessionFileEnt
|
||||
hash: hashText(content + "\n" + lineMap.join(",")),
|
||||
content,
|
||||
lineMap,
|
||||
...(generatedByDreamingNarrative ? { generatedByDreamingNarrative: true } : {}),
|
||||
};
|
||||
} catch (err) {
|
||||
log.debug(`Failed reading session file ${absPath}: ${String(err)}`);
|
||||
|
||||
Reference in New Issue
Block a user