惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MyScale Blog
MyScale Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
人人都是产品经理
人人都是产品经理
V
Visual Studio Blog
博客园 - 叶小钗
A
About on SuperTechFans
Last Week in AI
Last Week in AI
量子位
博客园 - 三生石上(FineUI控件)
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
MongoDB | Blog
MongoDB | Blog
T
The Blog of Author Tim Ferriss
Vercel News
Vercel News
博客园 - 司徒正美
博客园 - Franky
博客园 - 【当耐特】
月光博客
月光博客
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Apple Machine Learning Research
Apple Machine Learning Research
Hugging Face - Blog
Hugging Face - Blog
S
SegmentFault 最新的问题
大猫的无限游戏
大猫的无限游戏
博客园 - 聂微东
J
Java Code Geeks

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
fix(memory-core): vary dream diary recall snippets (#9122...
mushuiyu886 · 2026-06-15 · via Recent Commits to openclaw:main

@@ -21,6 +21,7 @@ import {

2121

formatNarrativeDate,

2222

formatBackfillDiaryDate,

2323

generateAndAppendDreamNarrative,

24+

readRecentDreamDiaryEntries,

2425

removeBackfillDiaryEntries,

2526

runDetachedDreamNarrative,

2627

type NarrativePhaseData,

@@ -133,6 +134,19 @@ describe("buildNarrativePrompt", () => {

133134

expect(prompt).toContain("snippet-11");

134135

expect(prompt).not.toContain("snippet-12");

135136

});

137+138+

it("includes current sweep and recent diary context", () => {

139+

const prompt = buildNarrativePrompt({

140+

phase: "light",

141+

snippets: ["Later workspace routing notes surfaced."],

142+

currentDate: "April 6, 2026, 9:00 AM UTC",

143+

recentDiaryEntries: ["The first meeting memory already filled the page."],

144+

});

145+

expect(prompt).toContain("Diary continuity context");

146+

expect(prompt).toContain("Current sweep: April 6, 2026, 9:00 AM UTC");

147+

expect(prompt).toContain("The first meeting memory already filled the page.");

148+

expect(prompt).toContain("do not replay the same first-day framing");

149+

});

136150

});

137151138152

describe("extractNarrativeText", () => {

@@ -388,6 +402,77 @@ describe("appendNarrativeEntry", () => {

388402

expect(secondIdx).toBeLessThan(end);

389403

});

390404405+

it("reads recent diary entries without timestamps or markers", async () => {

406+

const workspaceDir = await createTempWorkspace("openclaw-dreaming-narrative-");

407+

await appendNarrativeEntry({

408+

workspaceDir,

409+

narrative: "The first meeting memory already filled the page.",

410+

nowMs: Date.parse("2026-04-04T03:00:00Z"),

411+

timezone: "UTC",

412+

});

413+

await appendNarrativeEntry({

414+

workspaceDir,

415+

narrative: "A later routing note flickered in the margins.",

416+

nowMs: Date.parse("2026-04-05T03:00:00Z"),

417+

timezone: "UTC",

418+

});

419+420+

await expect(readRecentDreamDiaryEntries({ workspaceDir, limit: 1 })).resolves.toEqual([

421+

"A later routing note flickered in the margins.",

422+

]);

423+

});

424+425+

it("skips symlinked DREAMS.md when building recent diary context", async () => {

426+

const workspaceDir = await createTempWorkspace("openclaw-dreaming-narrative-");

427+

const targetPath = path.join(workspaceDir, "target-dreams.md");

428+

const dreamsPath = path.join(workspaceDir, "DREAMS.md");

429+

const symlinkTargetDiary = "Symlink target diary text must not enter the prompt.";

430+

await fs.writeFile(

431+

targetPath,

432+

[

433+

"# Dream Diary",

434+

"",

435+

"<!-- openclaw:dreaming:diary:start -->",

436+

"---",

437+

"",

438+

"*April 5, 2026, 3:00 AM UTC*",

439+

"",

440+

symlinkTargetDiary,

441+

"",

442+

"<!-- openclaw:dreaming:diary:end -->",

443+

"",

444+

].join("\n"),

445+

"utf-8",

446+

);

447+

await fs.symlink(targetPath, dreamsPath);

448+449+

const entries = await readRecentDreamDiaryEntries({ workspaceDir, limit: 3 });

450+

expect(entries).toEqual([]);

451+

const prompt = buildNarrativePrompt({

452+

phase: "light",

453+

snippets: ["A fresh routing memory arrived."],

454+

recentDiaryEntries: entries,

455+

});

456+

expect(prompt).not.toContain(symlinkTargetDiary);

457+

});

458+459+

it("skips non-file DREAMS.md when reading recent diary context", async () => {

460+

const workspaceDir = await createTempWorkspace("openclaw-dreaming-narrative-");

461+

await fs.mkdir(path.join(workspaceDir, "DREAMS.md"));

462+463+

await expect(readRecentDreamDiaryEntries({ workspaceDir, limit: 3 })).resolves.toEqual([]);

464+

});

465+466+

it("treats unreadable DREAMS.md as empty recent diary context", async () => {

467+

const workspaceDir = await createTempWorkspace("openclaw-dreaming-narrative-");

468+

await fs.writeFile(path.join(workspaceDir, "DREAMS.md"), "unreadable", "utf-8");

469+

vi.spyOn(fs, "access").mockRejectedValueOnce(

470+

Object.assign(new Error("permission denied"), { code: "EACCES" }),

471+

);

472+473+

await expect(readRecentDreamDiaryEntries({ workspaceDir, limit: 3 })).resolves.toEqual([]);

474+

});

475+391476

it("prepends diary before existing managed blocks", async () => {

392477

const workspaceDir = await createTempWorkspace("openclaw-dreaming-narrative-");

393478

const dreamsPath = path.join(workspaceDir, "DREAMS.md");