Files
boss/tests/master-agent-memory-ingestion.test.ts

139 lines
4.6 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import os from "node:os";
import path from "node:path";
import { mkdtemp, rm } from "node:fs/promises";
let runtimeRoot = "";
let queueMasterAgentTask: (typeof import("../src/lib/boss-data"))["queueMasterAgentTask"];
let completeMasterAgentTask: (typeof import("../src/lib/boss-data"))["completeMasterAgentTask"];
let listUserMasterMemories: (typeof import("../src/lib/boss-data"))["listUserMasterMemories"];
let readState: (typeof import("../src/lib/boss-data"))["readState"];
let writeState: (typeof import("../src/lib/boss-data"))["writeState"];
async function setup() {
if (runtimeRoot) return;
runtimeRoot = await mkdtemp(path.join(os.tmpdir(), "boss-master-agent-memory-ingestion-"));
process.env.BOSS_RUNTIME_ROOT = runtimeRoot;
process.env.BOSS_STATE_FILE = path.join(runtimeRoot, "boss-state.json");
const data = await import("../src/lib/boss-data.ts");
queueMasterAgentTask = data.queueMasterAgentTask;
completeMasterAgentTask = data.completeMasterAgentTask;
listUserMasterMemories = data.listUserMasterMemories;
readState = data.readState;
writeState = data.writeState;
}
async function ensureBossProject() {
const state = await readState();
if (state.projects.some((project) => project.id === "boss")) {
return;
}
await writeState({
...state,
projects: [
...state.projects,
{
id: "boss",
name: "boss",
pinned: false,
systemPinned: false,
deviceIds: ["mac-studio"],
preview: "等待项目同步。",
updatedAt: "2026-04-03T10:00:00+08:00",
lastMessageAt: "2026-04-03T10:00:00+08:00",
isGroup: false,
unreadCount: 0,
riskLevel: "low",
contextBudgetPct: 80,
contextBudgetLabel: "80%",
threadMeta: {
projectId: "boss",
threadId: "boss-thread",
threadDisplayName: "Boss开发主线程",
folderName: "boss",
activityIconCount: 0,
updatedAt: "2026-04-03T10:00:00+08:00",
codexFolderRef: "/Users/kris/code/boss",
codexThreadRef: "boss-thread",
},
groupMembers: [],
messages: [],
goals: [],
versions: [],
createdByAgent: true,
collaborationMode: "development",
approvalState: "not_required",
lightDispatchReminderEnabled: false,
},
],
});
}
test.after(async () => {
if (runtimeRoot) {
await rm(runtimeRoot, { recursive: true, force: true });
}
});
test("主 Agent 完成对话后会自动沉淀用户偏好和项目记忆", async () => {
await setup();
await ensureBossProject();
const task = await queueMasterAgentTask({
projectId: "master-agent",
requestMessageId: "msg-user-1",
requestText: "boss 项目后续都按微信式交互来做,并且默认中文回复。",
executionPrompt: "prompt",
requestedBy: "krisolo",
requestedByAccount: "krisolo",
deviceId: "master-agent-openai",
});
await completeMasterAgentTask({
taskId: task.taskId,
deviceId: "master-agent-openai",
status: "completed",
replyBody: "boss 项目当前进度已更新:会话页会继续按微信式交互推进。",
});
const memories = await listUserMasterMemories("krisolo", { includeArchived: false });
const globalMemory = memories.find((memory) => memory.scope === "global");
const projectMemory = memories.find((memory) => memory.scope === "project" && memory.projectId === "boss");
assert.ok(globalMemory, "expected a global user memory");
assert.ok(projectMemory, "expected a project-scoped memory");
assert.match(globalMemory?.content ?? "", /微信式交互|中文回复/);
assert.match(projectMemory?.content ?? "", /boss 项目当前进度已更新/);
});
test("主 Agent 不会把低价值短句和瞬时安排自动写入记忆", async () => {
await setup();
const task = await queueMasterAgentTask({
projectId: "master-agent",
requestMessageId: "msg-user-2",
requestText: "好的,先这样,稍后我再看。",
executionPrompt: "prompt",
requestedBy: "krisolo",
requestedByAccount: "krisolo",
deviceId: "master-agent-openai",
});
await completeMasterAgentTask({
taskId: task.taskId,
deviceId: "master-agent-openai",
status: "completed",
replyBody: "好的,稍后继续。",
});
const memories = await listUserMasterMemories("krisolo", { includeArchived: false });
const noisyMemory = memories.find(
(memory) => (memory.content ?? "").includes("先这样") || (memory.content ?? "").includes("稍后继续"),
);
assert.equal(noisyMemory, undefined);
});