test(memory): cover dream session-state extraction and undefined output
Update dashboard mocks to push assistant text into session.state.messages (matching real session.prompt() void return) and add a regression test for array-shaped content. Add core unit tests for extractDreamProcessorResult to lock in undefined/null safety. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,11 +9,33 @@ import {
|
||||
createMemoryDreamsAutomation,
|
||||
DEFAULT_MEMORY_DREAMS_SCHEDULE,
|
||||
ensureAgentMemoryFiles,
|
||||
extractDreamProcessorResult,
|
||||
MEMORY_DREAMS_SCHEDULE_NAME,
|
||||
processAgentMemoryDreams,
|
||||
syncMemoryDreamsAutomation,
|
||||
} from "../memory-dreams.js";
|
||||
|
||||
describe("extractDreamProcessorResult", () => {
|
||||
it("parses dreams and long-term updates from well-formed output", () => {
|
||||
const result = extractDreamProcessorResult(
|
||||
"## DREAMS\n\nPattern A.\n\n## LONG_TERM_UPDATES\n\n- Lesson A.",
|
||||
);
|
||||
expect(result).toEqual({
|
||||
dreams: "Pattern A.",
|
||||
longTermUpdates: "- Lesson A.",
|
||||
});
|
||||
});
|
||||
|
||||
it("returns empty fields when input is undefined (regression: prompt() returns void)", () => {
|
||||
expect(extractDreamProcessorResult(undefined)).toEqual({ dreams: "", longTermUpdates: "" });
|
||||
expect(extractDreamProcessorResult(null)).toEqual({ dreams: "", longTermUpdates: "" });
|
||||
});
|
||||
|
||||
it("returns empty fields when sections are missing", () => {
|
||||
expect(extractDreamProcessorResult("no headings here")).toEqual({ dreams: "", longTermUpdates: "" });
|
||||
});
|
||||
});
|
||||
|
||||
describe("memory-dreams automation", () => {
|
||||
it("creates a scheduled dream processor automation with defaults", () => {
|
||||
const automation = createMemoryDreamsAutomation({});
|
||||
|
||||
@@ -15439,12 +15439,17 @@ describe("POST /api/memory/dream", () => {
|
||||
}
|
||||
|
||||
it("returns 200 with dream results on success", async () => {
|
||||
vi.mocked(createFnAgent).mockResolvedValue({
|
||||
session: {
|
||||
prompt: vi.fn().mockResolvedValue("## DREAMS\nSynthesis\n\n## LONG_TERM_UPDATES\nLesson"),
|
||||
dispose: vi.fn(),
|
||||
},
|
||||
} as never);
|
||||
const session = {
|
||||
prompt: vi.fn().mockImplementation(async function (this: { state: { messages: unknown[] } }) {
|
||||
this.state.messages.push({
|
||||
role: "assistant",
|
||||
content: "## DREAMS\nSynthesis\n\n## LONG_TERM_UPDATES\nLesson",
|
||||
});
|
||||
}),
|
||||
dispose: vi.fn(),
|
||||
state: { messages: [] as unknown[] },
|
||||
};
|
||||
vi.mocked(createFnAgent).mockResolvedValue({ session } as never);
|
||||
|
||||
const res = await REQUEST(buildApp(), "POST", "/api/memory/dream", JSON.stringify({}), {
|
||||
"Content-Type": "application/json",
|
||||
@@ -15460,12 +15465,17 @@ describe("POST /api/memory/dream", () => {
|
||||
|
||||
it("returns 200 with empty results when no daily notes to process", async () => {
|
||||
writeFileSync(join(rootDir, ".fusion", "memory", `${new Date().toISOString().slice(0, 10)}.md`), "");
|
||||
vi.mocked(createFnAgent).mockResolvedValue({
|
||||
session: {
|
||||
prompt: vi.fn().mockResolvedValue("## DREAMS\n\n## LONG_TERM_UPDATES\n"),
|
||||
dispose: vi.fn(),
|
||||
},
|
||||
} as never);
|
||||
const session = {
|
||||
prompt: vi.fn().mockImplementation(async function (this: { state: { messages: unknown[] } }) {
|
||||
this.state.messages.push({
|
||||
role: "assistant",
|
||||
content: "## DREAMS\n\n## LONG_TERM_UPDATES\n",
|
||||
});
|
||||
}),
|
||||
dispose: vi.fn(),
|
||||
state: { messages: [] as unknown[] },
|
||||
};
|
||||
vi.mocked(createFnAgent).mockResolvedValue({ session } as never);
|
||||
|
||||
const res = await REQUEST(buildApp(), "POST", "/api/memory/dream", JSON.stringify({}), {
|
||||
"Content-Type": "application/json",
|
||||
@@ -15505,6 +15515,31 @@ describe("POST /api/memory/dream", () => {
|
||||
expect(res.body.error).toContain("AI");
|
||||
});
|
||||
|
||||
it("parses assistant text from session.state when content is an array (regression: undefined .match crash)", async () => {
|
||||
const session = {
|
||||
prompt: vi.fn().mockImplementation(async function (this: { state: { messages: unknown[] } }) {
|
||||
this.state.messages.push({
|
||||
role: "assistant",
|
||||
content: [{ text: "## DREAMS\nArrayContent\n\n## LONG_TERM_UPDATES\nArrayLesson" }],
|
||||
});
|
||||
}),
|
||||
dispose: vi.fn(),
|
||||
state: { messages: [] as unknown[] },
|
||||
};
|
||||
vi.mocked(createFnAgent).mockResolvedValue({ session } as never);
|
||||
|
||||
const res = await REQUEST(buildApp(), "POST", "/api/memory/dream", JSON.stringify({}), {
|
||||
"Content-Type": "application/json",
|
||||
});
|
||||
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.body).toMatchObject({
|
||||
success: true,
|
||||
dreamsWritten: true,
|
||||
longTermUpdatesWritten: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("returns 500 on unexpected processing failure", async () => {
|
||||
vi.mocked(createFnAgent).mockResolvedValue({
|
||||
session: {
|
||||
|
||||
Reference in New Issue
Block a user