deskpaw-memory/test/store.test.js

88 lines
5.2 KiB
JavaScript

import assert from "node:assert/strict";
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import test from "node:test";
import { MemoryStore } from "../src/store.js";
test("task transition recommends consolidation for an unrelated completed task", () => {
const directory = mkdtempSync(join(tmpdir(), "deskpaw-memory-"));
const store = new MemoryStore(join(directory, "memory.sqlite"), join(directory, "bundles"));
try {
store.completeTask({ task_id: "one", objective: "打开微信并发送日报", status: "completed", result: "已发送", context_epoch: "e1" });
const related = store.assessTransition({ objective: "继续发送刚才的日报" });
const unrelated = store.assessTransition({ objective: "分析项目中的 TypeScript 架构" });
assert.notEqual(related.relationship, "new");
assert.equal(unrelated.relationship, "new");
assert.equal(unrelated.recommended_action, "consolidate");
} finally {
store.close();
rmSync(directory, { recursive: true, force: true });
}
});
test("recall returns related and recent task memories for the shared session", () => {
const directory = mkdtempSync(join(tmpdir(), "deskpaw-memory-"));
const store = new MemoryStore(join(directory, "memory.sqlite"), join(directory, "bundles"));
try {
store.completeTask({ task_id: "screen", objective: "通过 HDMI 截取当前屏幕", status: "completed", result: "HDMI 抓帧成功", context_epoch: "e1" });
store.completeTask({ task_id: "ufo", objective: "检查 UFO RPC 是否恢复", status: "completed", result: "UFO 仍然超时", context_epoch: "e2" });
const recalled = store.recall({ query: "之前 UFO 检查怎么样了", limit: 2 });
assert.equal(recalled.related_task_cards[0].task_id, "ufo");
assert.deepEqual(recalled.recent_task_cards.map((task) => task.task_id), ["ufo", "screen"]);
assert.equal(recalled.recent_task_cards[0].result, "UFO 仍然超时");
} finally {
store.close();
rmSync(directory, { recursive: true, force: true });
}
});
test("recall includes durable top-level conversations without gateway isolation", () => {
const directory = mkdtempSync(join(tmpdir(), "deskpaw-memory-"));
const store = new MemoryStore(join(directory, "memory.sqlite"), join(directory, "bundles"));
try {
assert.deepEqual(store.rememberInteractions({ interactions: [
{ interaction_id: "one", source: "terminal", user: "我喜欢简短回复", manager: "记住了,会保持简短。", created_at: 1, updated_at: 1 },
{ interaction_id: "two", source: "feishu", user: "UFO 检查结果呢", manager: "UFO 仍然超时。", created_at: 2, updated_at: 2 },
] }), { stored: 2 });
assert.deepEqual(store.rememberInteractions({ interactions: [
{ interaction_id: "one", source: "terminal", user: "我喜欢简短回复", manager: "记住了,会保持简短。", created_at: 1, updated_at: 1 },
] }), { stored: 0 });
const recalled = store.recall({ query: "之前 UFO 怎么样", limit: 2 });
assert.equal(recalled.related_interactions[0].interaction_id, "two");
assert.deepEqual(recalled.recent_interactions.map((interaction) => interaction.source), ["feishu", "terminal"]);
} finally {
store.close();
rmSync(directory, { recursive: true, force: true });
}
});
test("schedule context creates and projects a stable bundle", () => {
const directory = mkdtempSync(join(tmpdir(), "deskpaw-memory-"));
const store = new MemoryStore(join(directory, "memory.sqlite"), join(directory, "bundles"));
try {
const context = store.prepareContext({ task_id: "run-1", objective: "每天发送 AI 简报", schedule_id: "daily-ai", schedule_name: "AI 简报" });
assert.equal(context.schedule_bundle.documents.some((document) => document.name === "requirements.md"), true);
store.completeTask({ task_id: "run-1", objective: "每天发送 AI 简报", status: "completed", result: "今日已发送 5 条", schedule_id: "daily-ai", schedule_name: "AI 简报", context_epoch: context.context_epoch });
assert.match(readFileSync(join(directory, "bundles", "schedule", "daily-ai", "runs", "run-1", "summary.md"), "utf8"), /今日已发送/);
} finally {
store.close();
rmSync(directory, { recursive: true, force: true });
}
});
test("bundle document updates use optimistic revisions", () => {
const directory = mkdtempSync(join(tmpdir(), "deskpaw-memory-"));
const store = new MemoryStore(join(directory, "memory.sqlite"), join(directory, "bundles"));
try {
store.prepareContext({ task_id: "run-1", objective: "每天发送 AI 简报", schedule_id: "daily-ai", schedule_name: "AI 简报" });
const bundle = store.bundle("schedule", "daily-ai");
const updated = store.updateBundleDocument({ scope: "schedule", object_id: "daily-ai", name: "preferences.md", body: "多放开源项目。", expected_revision: bundle.revision });
assert.equal(updated.revision, bundle.revision + 1);
assert.throws(() => store.updateBundleDocument({ scope: "schedule", object_id: "daily-ai", name: "preferences.md", body: "旧版本覆盖", expected_revision: bundle.revision }), /revision conflict/);
} finally {
store.close();
rmSync(directory, { recursive: true, force: true });
}
});