Files
boss/tests/master-agent-thread-status-prompt.test.ts

791 lines
30 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 readState: (typeof import("../src/lib/boss-data"))["readState"];
let writeState: (typeof import("../src/lib/boss-data"))["writeState"];
let saveAiAccount: (typeof import("../src/lib/boss-data"))["saveAiAccount"];
let updateMasterAgentPromptPolicy: (typeof import("../src/lib/boss-data"))["updateMasterAgentPromptPolicy"];
let updateUserMasterPrompt: (typeof import("../src/lib/boss-data"))["updateUserMasterPrompt"];
let createUserMasterMemory: (typeof import("../src/lib/boss-data"))["createUserMasterMemory"];
let updateProjectAgentControls: (typeof import("../src/lib/boss-data"))["updateProjectAgentControls"];
let appendProjectMessage: (typeof import("../src/lib/boss-data"))["appendProjectMessage"];
let resolveMasterAgentExecutionConfig: (typeof import("../src/lib/boss-master-agent"))["resolveMasterAgentExecutionConfig"];
let replyToMasterAgentUserMessage: (typeof import("../src/lib/boss-master-agent"))["replyToMasterAgentUserMessage"];
let completeMasterAgentTask: (typeof import("../src/lib/boss-data"))["completeMasterAgentTask"];
async function setup() {
if (runtimeRoot) return;
runtimeRoot = await mkdtemp(path.join(os.tmpdir(), "boss-master-agent-thread-status-"));
process.env.BOSS_RUNTIME_ROOT = runtimeRoot;
process.env.BOSS_STATE_FILE = path.join(runtimeRoot, "boss-state.json");
const [data, masterAgent] = await Promise.all([
import("../src/lib/boss-data.ts"),
import("../src/lib/boss-master-agent.ts"),
]);
readState = data.readState;
writeState = data.writeState;
saveAiAccount = data.saveAiAccount;
updateMasterAgentPromptPolicy = data.updateMasterAgentPromptPolicy;
updateUserMasterPrompt = data.updateUserMasterPrompt;
createUserMasterMemory = data.createUserMasterMemory;
updateProjectAgentControls = data.updateProjectAgentControls;
appendProjectMessage = data.appendProjectMessage;
resolveMasterAgentExecutionConfig = masterAgent.resolveMasterAgentExecutionConfig;
replyToMasterAgentUserMessage = masterAgent.replyToMasterAgentUserMessage;
completeMasterAgentTask = data.completeMasterAgentTask;
}
test.after(async () => {
if (runtimeRoot) {
await rm(runtimeRoot, { recursive: true, force: true });
}
});
test("主 Agent 执行 prompt 命中线程时只读取相关状态文档和最近进展事件,不再常态注入深拉兜底", async () => {
await setup();
await saveAiAccount({
accountId: "master-codex-primary",
label: "主 GPT",
role: "primary",
provider: "master_codex_node",
displayName: "krisolo · Master Codex Node",
nodeId: "mac-studio",
nodeLabel: "Mac Studio",
enabled: true,
setActive: true,
status: "ready",
loginStatusNote: "主节点可用。",
});
await updateMasterAgentPromptPolicy({
globalPrompt: "管理员全局主提示词",
updatedBy: "krisolo",
});
await updateUserMasterPrompt("krisolo", "用户私有主提示词");
await updateProjectAgentControls("master-agent", {
promptOverride: "当前对话提示词",
});
await createUserMasterMemory({
account: "krisolo",
scope: "project",
projectId: "master-agent",
title: "项目记忆",
content: "项目记忆正文",
memoryType: "project_progress",
tags: ["线程状态"],
});
await createUserMasterMemory({
account: "master-codex-primary",
scope: "project",
projectId: "master-agent",
title: "项目记忆",
content: "项目记忆正文",
memoryType: "project_progress",
tags: ["线程状态"],
});
const state = await readState();
const auditProject = state.projects.find((project) => project.id === "audit-collab");
assert.ok(auditProject, "expected seeded audit-collab project");
const masterProject = state.projects.find((project) => project.id === "master-agent");
assert.ok(masterProject, "expected seeded master-agent project");
auditProject!.projectUnderstanding = {
projectGoal: "深拉兜底目标",
currentProgress: "深拉兜底进度",
technicalArchitecture: "深拉兜底架构",
currentBlockers: "深拉兜底阻塞",
recommendedNextStep: "深拉兜底下一步",
sourceTaskId: "task-deep-pull",
updatedAt: "2026-04-04T18:00:00+08:00",
sourceKind: "thread_sync",
};
masterProject!.projectUnderstanding = {
projectGoal: "主 Agent 旧目标",
currentProgress: "主 Agent 旧进度",
technicalArchitecture: "主 Agent 旧架构",
currentBlockers: "主 Agent 旧阻塞",
recommendedNextStep: "主 Agent 旧下一步",
sourceTaskId: "task-master-legacy",
updatedAt: "2026-04-04T17:50:00+08:00",
sourceKind: "thread_sync",
};
state.threadStatusDocuments = [
{
documentId: "thread-status-doc-master",
projectId: "master-agent",
threadId: "thread-master-main",
threadDisplayName: "主 Agent 汇总",
folderName: "主控线程",
deviceId: "mac-studio",
projectGoal: "主 Agent 额外状态目标",
currentPhase: "主 Agent 额外阶段",
currentProgress: "主 Agent 额外进度",
technicalArchitecture: "主 Agent 额外架构",
currentBlockers: "主 Agent 额外阻塞",
recommendedNextStep: "主 Agent 额外下一步",
keyFiles: ["src/lib/boss-master-agent.ts"],
keyCommands: ["npm run lint"],
updatedAt: "2026-04-04T18:03:00+08:00",
sourceTaskId: "task-master-status",
sourceKind: "incremental_sync",
},
{
documentId: "thread-status-doc-1",
projectId: "audit-collab",
threadId: "thread-audit-chief",
threadDisplayName: "审计对话",
folderName: "审计群聊",
deviceId: "mac-studio",
projectGoal: "线程状态目标",
currentPhase: "线程状态阶段",
currentProgress: "线程状态进度",
technicalArchitecture: "线程状态架构",
currentBlockers: "线程状态阻塞",
recommendedNextStep: "线程状态下一步",
keyFiles: ["src/lib/boss-master-agent.ts"],
keyCommands: ["npm run build"],
updatedAt: "2026-04-04T18:01:00+08:00",
sourceTaskId: "task-thread-status",
sourceKind: "incremental_sync",
},
];
state.threadProgressEvents = [
{
eventId: "thread-progress-event-master",
projectId: "master-agent",
threadId: "thread-master-main",
threadDisplayName: "主 Agent 汇总",
deviceId: "mac-studio",
eventType: "progress_updated",
summary: "主 Agent 额外进展摘要",
phase: "主 Agent 额外阶段",
blockerDelta: "主 Agent 额外阻塞",
nextStepDelta: "主 Agent 额外下一步",
createdAt: "2026-04-04T18:03:30+08:00",
sourceTaskId: "task-master-progress",
},
{
eventId: "thread-progress-event-1",
projectId: "audit-collab",
threadId: "thread-audit-chief",
threadDisplayName: "审计对话",
deviceId: "mac-studio",
eventType: "progress_updated",
summary: "最近进展事件摘要",
phase: "线程状态阶段",
blockerDelta: "线程状态阻塞",
nextStepDelta: "线程状态下一步",
createdAt: "2026-04-04T18:02:00+08:00",
sourceTaskId: "task-thread-progress",
},
];
await writeState(state);
const resolved = await resolveMasterAgentExecutionConfig(
"master-agent",
"krisolo",
"审计对话,请继续推进线程状态同步",
);
assert.ok(resolved.projectMemories.length > 0);
assert.equal(resolved.projectMemories[0]?.content, "项目记忆正文");
assert.ok(resolved.executionPrompt.includes("当前对话提示词"));
assert.ok(
resolved.executionPrompt.indexOf("管理员全局主提示词:") <
resolved.executionPrompt.indexOf("用户私有主提示词:") &&
resolved.executionPrompt.indexOf("用户私有主提示词:") <
resolved.executionPrompt.indexOf("当前对话附加提示词:") &&
resolved.executionPrompt.indexOf("当前对话附加提示词:") <
resolved.executionPrompt.indexOf("当前消息:"),
);
const reply = await replyToMasterAgentUserMessage({
requestText: "审计对话,请继续推进线程状态同步",
requestedBy: "Boss 超级管理员",
requestedByAccount: "krisolo",
mode: "enqueue",
});
assert.equal(reply.ok, true);
assert.equal(reply.masterReplyState, "queued");
const queuedTask = (await readState()).masterAgentTasks.find(
(task) => task.projectId === "master-agent" && task.requestText === "审计对话,请继续推进线程状态同步",
);
assert.ok(queuedTask, "expected master-agent task to be queued");
assert.ok(queuedTask?.executionPrompt.includes("线程状态文档:"));
assert.ok(queuedTask?.executionPrompt.includes("线程状态目标"));
assert.ok(!queuedTask?.executionPrompt.includes("主 Agent 额外状态目标"));
assert.ok(queuedTask?.executionPrompt.includes("最近进展事件:"));
assert.ok(queuedTask?.executionPrompt.includes("最近进展事件摘要"));
assert.ok(!queuedTask?.executionPrompt.includes("主 Agent 额外进展摘要"));
assert.ok(!queuedTask?.executionPrompt.includes("深拉兜底目标"));
assert.ok(!queuedTask?.executionPrompt.includes("关键时刻深拉线程兜底:"));
});
test("主 Agent 执行 prompt 在未命中时退回最近活跃项目,且不会常态注入深拉兜底", async () => {
await setup();
const state = await readState();
const auditProject = state.projects.find((project) => project.id === "audit-collab");
const masterProject = state.projects.find((project) => project.id === "master-agent");
assert.ok(auditProject, "expected seeded audit-collab project");
assert.ok(masterProject, "expected seeded master-agent project");
auditProject!.projectUnderstanding = {
projectGoal: "审计兜底目标",
currentProgress: "审计兜底进度",
technicalArchitecture: "审计兜底架构",
currentBlockers: "审计兜底阻塞",
recommendedNextStep: "审计兜底下一步",
sourceTaskId: "task-audit-fallback",
updatedAt: "2026-04-04T17:55:00+08:00",
sourceKind: "thread_sync",
};
masterProject!.projectUnderstanding = {
projectGoal: "最近活跃目标",
currentProgress: "最近活跃进度",
technicalArchitecture: "最近活跃架构",
currentBlockers: "最近活跃阻塞",
recommendedNextStep: "最近活跃下一步",
sourceTaskId: "task-master-active",
updatedAt: "2026-04-04T18:05:00+08:00",
sourceKind: "thread_sync",
};
state.threadStatusDocuments = [
{
documentId: "thread-status-doc-audit-fallback",
projectId: "audit-collab",
threadId: "thread-audit-chief",
threadDisplayName: "审计对话",
folderName: "审计群聊",
deviceId: "mac-studio",
projectGoal: "审计兜底状态",
currentPhase: "审计兜底阶段",
currentProgress: "审计兜底进度",
technicalArchitecture: "审计兜底架构",
currentBlockers: "审计兜底阻塞",
recommendedNextStep: "审计兜底下一步",
keyFiles: ["src/lib/boss-master-agent.ts"],
keyCommands: ["npm run build"],
updatedAt: "2026-04-04T17:56:00+08:00",
sourceTaskId: "task-audit-status",
sourceKind: "incremental_sync",
},
{
documentId: "thread-status-doc-master-fallback",
projectId: "master-agent",
threadId: "thread-master-main",
threadDisplayName: "主 Agent 汇总",
folderName: "主控线程",
deviceId: "mac-studio",
projectGoal: "最近活跃状态",
currentPhase: "最近活跃阶段",
currentProgress: "最近活跃进度",
technicalArchitecture: "最近活跃架构",
currentBlockers: "最近活跃阻塞",
recommendedNextStep: "最近活跃下一步",
keyFiles: ["src/lib/boss-data.ts"],
keyCommands: ["npm run lint"],
updatedAt: "2026-04-04T18:06:00+08:00",
sourceTaskId: "task-master-status-fallback",
sourceKind: "incremental_sync",
},
];
state.threadProgressEvents = [
{
eventId: "thread-progress-event-audit-fallback",
projectId: "audit-collab",
threadId: "thread-audit-chief",
threadDisplayName: "审计对话",
deviceId: "mac-studio",
eventType: "progress_updated",
summary: "审计兜底进展摘要",
phase: "审计兜底阶段",
blockerDelta: "审计兜底阻塞",
nextStepDelta: "审计兜底下一步",
createdAt: "2026-04-04T17:56:30+08:00",
sourceTaskId: "task-audit-progress",
},
{
eventId: "thread-progress-event-master-fallback",
projectId: "master-agent",
threadId: "thread-master-main",
threadDisplayName: "主 Agent 汇总",
deviceId: "mac-studio",
eventType: "progress_updated",
summary: "最近活跃进展摘要",
phase: "最近活跃阶段",
blockerDelta: "最近活跃阻塞",
nextStepDelta: "最近活跃下一步",
createdAt: "2026-04-04T18:06:30+08:00",
sourceTaskId: "task-master-progress-fallback",
},
];
await writeState(state);
const reply = await replyToMasterAgentUserMessage({
requestText: "请继续推进线程状态同步(仅深拉兜底)",
requestedBy: "Boss 超级管理员",
requestedByAccount: "krisolo",
mode: "enqueue",
});
assert.equal(reply.ok, true);
const queuedTask = (await readState()).masterAgentTasks.find(
(task) => task.projectId === "master-agent" && task.requestText === "请继续推进线程状态同步(仅深拉兜底)",
);
assert.ok(queuedTask, "expected master-agent task to be queued");
assert.ok(queuedTask?.executionPrompt.includes("最近活跃状态"));
assert.ok(queuedTask?.executionPrompt.includes("最近活跃进展摘要"));
assert.ok(!queuedTask?.executionPrompt.includes("关键时刻深拉线程兜底:"));
});
test("主 Agent 执行 prompt 在没有线程状态文档和进展事件时才会注入深拉兜底", async () => {
await setup();
const state = await readState();
const auditProject = state.projects.find((project) => project.id === "audit-collab");
assert.ok(auditProject, "expected seeded audit-collab project");
auditProject!.projectUnderstanding = {
projectGoal: "深拉兜底目标",
currentProgress: "深拉兜底进度",
technicalArchitecture: "深拉兜底架构",
currentBlockers: "深拉兜底阻塞",
recommendedNextStep: "深拉兜底下一步",
sourceTaskId: "task-deep-pull",
updatedAt: "2026-04-04T18:00:00+08:00",
sourceKind: "thread_sync",
};
state.threadStatusDocuments = [];
state.threadProgressEvents = [];
await writeState(state);
const reply = await replyToMasterAgentUserMessage({
requestText: "请继续推进线程状态同步",
requestedBy: "Boss 超级管理员",
requestedByAccount: "krisolo",
mode: "enqueue",
});
assert.equal(reply.ok, true);
const queuedTask = (await readState()).masterAgentTasks.find(
(task) => task.projectId === "master-agent" && task.requestText === "请继续推进线程状态同步",
);
assert.ok(queuedTask, "expected master-agent task to be queued");
assert.ok(queuedTask?.executionPrompt.includes("关键时刻深拉线程兜底:"));
assert.ok(queuedTask?.executionPrompt.includes("深拉兜底目标"));
});
test("非主会话里 @主Agent 时,运行时摘要只允许读取当前项目上下文,不允许串到最近活跃项目", async () => {
await setup();
await saveAiAccount({
accountId: "master-codex-primary-thread-scope",
label: "主 GPT",
role: "primary",
provider: "master_codex_node",
displayName: "krisolo · Master Codex Node",
nodeId: "mac-studio",
nodeLabel: "Mac Studio",
enabled: true,
setActive: true,
status: "ready",
loginStatusNote: "主节点可用。",
});
const state = await readState();
const auditProject = state.projects.find((project) => project.id === "audit-collab");
assert.ok(auditProject, "expected seeded audit-collab project");
state.projects.push({
id: "aitoukui-thread",
name: "AItoukui",
pinned: false,
deviceIds: ["mac-studio"],
preview: "等待同步",
updatedAt: "2026-04-05T11:59:00+08:00",
lastMessageAt: "2026-04-05T11:59:00+08:00",
isGroup: false,
threadMeta: {
projectId: "aitoukui-thread",
threadId: "thread-aitoukui-main",
threadDisplayName: "AItoukui 主线程",
folderName: "AItoukui",
activityIconCount: 1,
updatedAt: "2026-04-05T11:59:00+08:00",
lastObservedCodexActivityAt: "2026-04-05T11:59:00+08:00",
codexThreadRef: "thread-aitoukui-main",
codexFolderRef: "aitoukui",
},
groupMembers: [],
createdByAgent: true,
collaborationMode: "development",
approvalState: "not_required",
unreadCount: 0,
riskLevel: "low",
messages: [],
goals: [],
versions: [],
});
state.threadStatusDocuments = [
{
documentId: "thread-status-doc-current-project",
projectId: "audit-collab",
threadId: "thread-audit-chief",
threadDisplayName: "审计对话",
folderName: "审计群聊",
deviceId: "mac-studio",
projectGoal: "当前项目目标",
currentPhase: "当前项目阶段",
currentProgress: "当前项目进度",
technicalArchitecture: "当前项目架构",
currentBlockers: "当前项目阻塞",
recommendedNextStep: "当前项目下一步",
keyFiles: ["src/lib/current-thread.ts"],
keyCommands: ["npm run lint"],
updatedAt: "2026-04-05T10:00:00+08:00",
sourceTaskId: "task-current-project",
sourceKind: "incremental_sync",
},
{
documentId: "thread-status-doc-other-project",
projectId: "aitoukui-thread",
threadId: "thread-aitoukui-main",
threadDisplayName: "AItoukui 主线程",
folderName: "AItoukui",
deviceId: "mac-studio",
projectGoal: "别的项目目标",
currentPhase: "别的项目阶段",
currentProgress: "别的项目进度",
technicalArchitecture: "别的项目架构",
currentBlockers: "别的项目阻塞",
recommendedNextStep: "别的项目下一步",
keyFiles: ["src/lib/aitoukui-thread.ts"],
keyCommands: ["npm run build"],
updatedAt: "2026-04-05T12:00:00+08:00",
sourceTaskId: "task-other-project",
sourceKind: "incremental_sync",
},
];
state.threadProgressEvents = [
{
eventId: "thread-progress-current-project",
projectId: "audit-collab",
threadId: "thread-audit-chief",
threadDisplayName: "审计对话",
deviceId: "mac-studio",
eventType: "progress_updated",
summary: "当前项目进展摘要",
phase: "当前项目阶段",
blockerDelta: "当前项目阻塞变化",
nextStepDelta: "当前项目下一步变化",
createdAt: "2026-04-05T10:02:00+08:00",
sourceTaskId: "task-current-progress",
},
{
eventId: "thread-progress-other-project",
projectId: "aitoukui-thread",
threadId: "thread-aitoukui-main",
threadDisplayName: "AItoukui 主线程",
deviceId: "mac-studio",
eventType: "progress_updated",
summary: "别的项目进展摘要",
phase: "别的项目阶段",
blockerDelta: "别的项目阻塞变化",
nextStepDelta: "别的项目下一步变化",
createdAt: "2026-04-05T12:01:00+08:00",
sourceTaskId: "task-other-progress",
},
];
await writeState(state);
const reply = await replyToMasterAgentUserMessage({
requestText: "请你看一下当前项目下一步怎么推进",
requestedBy: "Boss 超级管理员",
requestedByAccount: "krisolo",
projectId: "audit-collab",
mode: "enqueue",
});
assert.equal(reply.ok, true);
const queuedTask = (await readState()).masterAgentTasks.find(
(task) =>
task.projectId === "audit-collab" &&
task.requestText === "请你看一下当前项目下一步怎么推进",
);
assert.ok(queuedTask, "expected a current-thread master-agent task to be queued");
assert.ok(queuedTask?.executionPrompt.includes("当前项目目标"));
assert.ok(queuedTask?.executionPrompt.includes("当前项目进展摘要"));
assert.ok(!queuedTask?.executionPrompt.includes("别的项目目标"));
assert.ok(!queuedTask?.executionPrompt.includes("别的项目进展摘要"));
});
test("项目理解同步 prompt 强制线程先基于本地文档和代码汇总,并允许回写版本记录摘要", async () => {
await setup();
const state = await readState();
state.projects.push({
id: "understanding-sync-thread",
name: "项目理解同步线程",
pinned: false,
deviceIds: ["mac-studio"],
preview: "等待同步",
updatedAt: "2026-04-04T18:00:00+08:00",
lastMessageAt: "2026-04-04T18:00:00+08:00",
isGroup: false,
threadMeta: {
projectId: "understanding-sync-thread",
threadId: "thread-understanding-sync",
threadDisplayName: "项目理解同步线程",
folderName: "理解同步",
activityIconCount: 1,
updatedAt: "2026-04-04T18:00:00+08:00",
lastObservedCodexActivityAt: "2026-04-04T18:00:00+08:00",
codexThreadRef: "thread-understanding-sync",
codexFolderRef: "understanding-sync-folder",
},
groupMembers: [],
createdByAgent: true,
collaborationMode: "development",
approvalState: "not_required",
unreadCount: 0,
riskLevel: "low",
messages: [],
goals: [],
versions: [],
});
const project = state.projects.find((item) => item.id === "understanding-sync-thread");
assert.ok(project, "expected seeded understanding-sync-thread project");
project!.versions = [];
project!.threadMeta.lastObservedCodexActivityAt = "2026-04-04T18:00:00+08:00";
await writeState(state);
await updateProjectAgentControls("understanding-sync-thread", {
takeoverEnabled: true,
});
await appendProjectMessage({
projectId: "understanding-sync-thread",
sender: "device",
senderLabel: "项目理解同步线程",
body: "已根据本地开发文档补齐线程状态同步。",
kind: "text",
});
const queuedTask = (await readState()).masterAgentTasks.find(
(task) =>
task.projectId === "master-agent" &&
task.projectUnderstandingTargetProjectId === "understanding-sync-thread",
);
assert.ok(queuedTask, "expected project understanding sync task");
assert.match(queuedTask!.executionPrompt, /先基于当前项目本地可见的开发文档和实际代码进行汇总/);
assert.match(queuedTask!.executionPrompt, /优先检查 README、docs、架构文档、版本记录和最近改动的关键代码文件/);
assert.match(queuedTask!.executionPrompt, /"versionRecord": "一句中文版本记录摘要"/);
await completeMasterAgentTask({
taskId: queuedTask!.taskId,
deviceId: "mac-studio",
status: "completed",
replyBody: JSON.stringify({
projectGoal: "完成审计对话线程状态同步",
currentProgress: "已切到线程状态文档优先",
technicalArchitecture: "Next.js 控制面配合 Android 原生客户端",
currentBlockers: "",
recommendedNextStep: "继续补强版本记录同步",
versionRecord: "项目理解同步已改成先读本地文档和代码,再回写结构化摘要。",
}),
});
const refreshed = await readState();
const refreshedProject = refreshed.projects.find((item) => item.id === "understanding-sync-thread");
assert.ok(refreshedProject, "expected refreshed project");
assert.equal(
refreshedProject!.projectUnderstanding?.projectGoal,
"完成审计对话线程状态同步",
);
assert.equal(refreshedProject!.versions[0]?.summary, "项目理解同步已改成先读本地文档和代码,再回写结构化摘要。");
});
test("主 Agent 总结项目目标和版本记录时不注入 OTA 与设备运行态噪音", async () => {
await setup();
await saveAiAccount({
accountId: "master-codex-primary",
label: "主 GPT",
role: "primary",
provider: "master_codex_node",
displayName: "krisolo · Master Codex Node",
nodeId: "mac-studio",
nodeLabel: "Mac Studio",
enabled: true,
setActive: true,
status: "ready",
loginStatusNote: "主节点可用。",
});
const state = await readState();
const auditProject = state.projects.find((project) => project.id === "audit-collab");
assert.ok(auditProject, "expected seeded audit-collab project");
auditProject!.projectUnderstanding = {
projectGoal: "审计线程目标",
currentProgress: "正在补齐版本记录摘要",
technicalArchitecture: "Next.js 控制面 + Android 原生客户端 + local-agent",
currentBlockers: "",
recommendedNextStep: "继续同步版本记录入口",
sourceTaskId: "task-audit-summary",
updatedAt: "2026-04-05T10:00:00+08:00",
sourceKind: "thread_sync",
};
state.threadStatusDocuments = [
{
documentId: "thread-status-doc-audit-summary",
projectId: "audit-collab",
threadId: "thread-audit-chief",
threadDisplayName: "审计对话",
folderName: "审计群聊",
deviceId: "mac-studio",
projectGoal: "审计线程目标",
currentPhase: "整理项目目标与版本记录",
currentProgress: "版本记录入口正在统一",
technicalArchitecture: "Next.js 控制面 + Android 原生客户端 + local-agent",
currentBlockers: "",
recommendedNextStep: "继续回填版本记录摘要",
keyFiles: ["src/lib/boss-master-agent.ts"],
keyCommands: ["npm run test"],
updatedAt: "2026-04-05T10:01:00+08:00",
sourceTaskId: "task-audit-summary-doc",
sourceKind: "incremental_sync",
},
];
state.threadProgressEvents = [
{
eventId: "thread-progress-event-audit-summary",
projectId: "audit-collab",
threadId: "thread-audit-chief",
threadDisplayName: "审计对话",
deviceId: "mac-studio",
eventType: "progress_updated",
summary: "项目目标和版本记录已开始重新汇总",
phase: "整理项目目标与版本记录",
blockerDelta: "",
nextStepDelta: "同步到会话顶部入口",
createdAt: "2026-04-05T10:02:00+08:00",
sourceTaskId: "task-audit-summary-event",
},
];
state.appLogs = [
{
logId: "app-log-summary-noise",
deviceId: "mac-studio",
category: "sync",
message: "这条日志不应该出现在项目目标总结 prompt 里",
createdAt: "2026-04-05T10:03:00+08:00",
},
];
state.otaUpdates = [
{
releaseId: "ota-summary-noise",
version: "v2.1.0",
currentVersion: "v2.0.0",
channel: "stable",
packageType: "android_shell",
status: "available",
summary: ["这条 OTA 不应该污染项目总结"],
targetScope: "Boss Android 原生客户端",
requiredRole: "highest_admin",
publishedAt: "2026-04-05T10:04:00+08:00",
},
];
await writeState(state);
const requestText = "请总结审计对话当前的项目目标和版本记录";
const reply = await replyToMasterAgentUserMessage({
requestText,
requestedBy: "Boss 超级管理员",
requestedByAccount: "krisolo",
mode: "enqueue",
});
assert.equal(reply.ok, true);
const queuedTask = (await readState()).masterAgentTasks.find(
(task) => task.projectId === "master-agent" && task.requestText === requestText,
);
assert.ok(queuedTask, "expected summary task to be queued");
assert.ok(queuedTask?.executionPrompt.includes("线程状态文档:"));
assert.ok(queuedTask?.executionPrompt.includes("审计线程目标"));
assert.ok(!queuedTask?.executionPrompt.includes("最新 APP 日志:"));
assert.ok(!queuedTask?.executionPrompt.includes("高风险线程:"));
assert.ok(!queuedTask?.executionPrompt.includes("在线设备:"));
assert.ok(!queuedTask?.executionPrompt.includes("认证状态:"));
assert.ok(!queuedTask?.executionPrompt.includes("可用 OTA"));
assert.ok(queuedTask?.executionPrompt.includes("回复风格:像专业职业经理人"));
assert.ok(queuedTask?.executionPrompt.includes("先给结论,再给推进动作"));
assert.ok(queuedTask?.executionPrompt.includes("不要堆背景,不要重复系统状态"));
});
test("主 Agent 处理 OTA 和设备运行态问题时保留相关运行时摘要", async () => {
await setup();
await saveAiAccount({
accountId: "master-codex-primary",
label: "主 GPT",
role: "primary",
provider: "master_codex_node",
displayName: "krisolo · Master Codex Node",
nodeId: "mac-studio",
nodeLabel: "Mac Studio",
enabled: true,
setActive: true,
status: "ready",
loginStatusNote: "主节点可用。",
});
const state = await readState();
state.appLogs = [
{
logId: "app-log-runtime-detail",
deviceId: "mac-studio",
category: "ota",
message: "检测到 Android OTA 可更新",
createdAt: "2026-04-05T11:00:00+08:00",
},
];
state.otaUpdates = [
{
releaseId: "ota-runtime-detail",
version: "v2.2.0",
currentVersion: "v2.1.0",
channel: "stable",
packageType: "android_shell",
status: "available",
summary: ["加入新的设备运行态提示"],
targetScope: "Boss Android 原生客户端",
requiredRole: "highest_admin",
publishedAt: "2026-04-05T11:01:00+08:00",
},
];
await writeState(state);
const requestText = "帮我看一下当前可用 OTA、在线设备状态和最近 APP 日志";
const reply = await replyToMasterAgentUserMessage({
requestText,
requestedBy: "Boss 超级管理员",
requestedByAccount: "krisolo",
mode: "enqueue",
});
assert.equal(reply.ok, true);
const queuedTask = (await readState()).masterAgentTasks.find(
(task) => task.projectId === "master-agent" && task.requestText === requestText,
);
assert.ok(queuedTask, "expected runtime-detail task to be queued");
assert.ok(queuedTask?.executionPrompt.includes("最新 APP 日志:"));
assert.ok(queuedTask?.executionPrompt.includes("在线设备:"));
assert.ok(queuedTask?.executionPrompt.includes("认证状态:"));
assert.ok(queuedTask?.executionPrompt.includes("可用 OTA"));
assert.ok(queuedTask?.executionPrompt.includes("v2.2.0 -> Boss Android 原生客户端"));
});