docs: add master-agent prompts and memory plan

This commit is contained in:
kris
2026-04-01 03:36:09 +08:00
parent 4312b248a7
commit 9000a9f185

View File

@@ -0,0 +1,998 @@
# 主 Agent 提示词与记忆分层 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 为主 Agent 建立分层提示词与用户级记忆体系,并在 Web 后台和原生 Android 聊天页提供完整的查看、编辑、自动沉淀和执行接入能力。
**Architecture:** 文件型状态中新增管理员全局主提示词、用户私有主提示词和用户记忆实体;`master-agent` 执行链统一合成全局提示词、用户提示词、当前对话附加提示词与相关记忆。Web 后台提供管理员全局主提示词编辑页Android `master-agent` 聊天页右上角三点菜单新增 `提示词``记忆` 两个入口,对应独立原生页面完成前台管理。
**Tech Stack:** Next.js App Router, TypeScript, file-backed state store, Android AppCompat/Java, node:test, Gradle unit tests
---
### Task 1: 为状态模型补齐主 Agent 提示词与用户记忆结构
**Files:**
- Modify: `/Users/kris/code/boss/src/lib/boss-data.ts`
- Modify: `/Users/kris/code/boss/src/lib/boss-projections.ts`
- Test: `/Users/kris/code/boss/tests/master-agent-prompts-memory-state.test.ts`
- [ ] **Step 1: 写失败测试,覆盖全局提示词、用户提示词、用户记忆的读写**
```ts
import test from "node:test";
import assert from "node:assert/strict";
import {
getMasterAgentPromptPolicy,
updateMasterAgentPromptPolicy,
getUserMasterPrompt,
updateUserMasterPrompt,
listUserMasterMemories,
createUserMasterMemory,
updateUserMasterMemory,
archiveUserMasterMemory,
} from "@/lib/boss-data";
test("主 Agent 提示词与用户记忆可读写", async () => {
await updateMasterAgentPromptPolicy({
globalPrompt: "全局主提示词",
updatedBy: "17600003315",
});
await updateUserMasterPrompt("17600003315", "用户私有主提示词");
const created = await createUserMasterMemory({
account: "17600003315",
scope: "project",
projectId: "master-agent",
title: "项目进度",
content: "当前主链优先打通聊天闭环。",
memoryType: "project_progress",
tags: ["聊天", "主链"],
});
await updateUserMasterMemory(created.memoryId, "17600003315", {
content: "当前主链优先打通主 Agent 聊天闭环。",
tags: ["聊天", "主Agent"],
});
const policy = await getMasterAgentPromptPolicy();
const userPrompt = await getUserMasterPrompt("17600003315");
const memories = await listUserMasterMemories("17600003315", {
includeArchived: false,
});
assert.equal(policy?.globalPrompt, "全局主提示词");
assert.equal(userPrompt?.content, "用户私有主提示词");
assert.equal(memories.length, 1);
assert.equal(memories[0]?.content, "当前主链优先打通主 Agent 聊天闭环。");
assert.deepEqual(memories[0]?.tags, ["聊天", "主Agent"]);
await archiveUserMasterMemory(created.memoryId, "17600003315");
const visible = await listUserMasterMemories("17600003315", { includeArchived: false });
const all = await listUserMasterMemories("17600003315", { includeArchived: true });
assert.equal(visible.length, 0);
assert.equal(all[0]?.archived, true);
});
```
- [ ] **Step 2: 跑测试确认当前失败**
Run:
```bash
cd /Users/kris/code/boss
npx --yes tsx --test tests/master-agent-prompts-memory-state.test.ts
```
Expected:
```text
FAIL ... getMasterAgentPromptPolicy is not a function
```
- [ ] **Step 3: 在状态模型中新增提示词与记忆结构**
```ts
export interface MasterAgentPromptPolicy {
globalPrompt: string;
updatedAt: string;
updatedBy?: string;
}
export interface UserMasterPrompt {
account: string;
content: string;
updatedAt: string;
}
export type MasterMemoryScope = "global" | "project";
export type MasterMemoryType =
| "user_preference"
| "project_progress"
| "decision"
| "risk"
| "blocking_issue"
| "research_note"
| "workflow_rule";
export interface MasterAgentMemory {
memoryId: string;
account: string;
scope: MasterMemoryScope;
projectId?: string;
title: string;
content: string;
memoryType: MasterMemoryType;
tags: string[];
sourceMessageId?: string;
createdAt: string;
updatedAt: string;
lastUsedAt?: string;
archived: boolean;
}
```
- [ ] **Step 4: 增加状态读写 helper**
```ts
export async function getMasterAgentPromptPolicy() {
const state = await readState();
return state.masterAgentPromptPolicy ?? null;
}
export async function updateMasterAgentPromptPolicy(input: {
globalPrompt: string;
updatedBy?: string;
}) {
return withStateLock(async (state) => {
state.masterAgentPromptPolicy = {
globalPrompt: input.globalPrompt.trim(),
updatedBy: input.updatedBy,
updatedAt: new Date().toISOString(),
};
return state.masterAgentPromptPolicy;
});
}
export async function getUserMasterPrompt(account: string) {
const state = await readState();
return state.userMasterPrompts.find((item) => item.account === account) ?? null;
}
export async function updateUserMasterPrompt(account: string, content: string) {
return withStateLock(async (state) => {
const existing = state.userMasterPrompts.find((item) => item.account === account);
const next = {
account,
content: content.trim(),
updatedAt: new Date().toISOString(),
};
if (existing) Object.assign(existing, next);
else state.userMasterPrompts.unshift(next);
return next;
});
}
```
- [ ] **Step 5: 增加用户记忆 CRUD helper**
```ts
export async function createUserMasterMemory(input: {
account: string;
scope: MasterMemoryScope;
projectId?: string;
title: string;
content: string;
memoryType: MasterMemoryType;
tags?: string[];
sourceMessageId?: string;
}) {
return withStateLock(async (state) => {
const now = new Date().toISOString();
const memory: MasterAgentMemory = {
memoryId: createStableId("memory"),
account: input.account,
scope: input.scope,
projectId: input.scope === "project" ? input.projectId : undefined,
title: input.title.trim(),
content: input.content.trim(),
memoryType: input.memoryType,
tags: normalizeTags(input.tags ?? []),
sourceMessageId: input.sourceMessageId,
createdAt: now,
updatedAt: now,
lastUsedAt: now,
archived: false,
};
state.masterAgentMemories.unshift(memory);
return memory;
});
}
```
- [ ] **Step 6: 再跑测试确认通过**
Run:
```bash
cd /Users/kris/code/boss
npx --yes tsx --test tests/master-agent-prompts-memory-state.test.ts
```
Expected:
```text
# tests 1
# pass 1
```
- [ ] **Step 7: Commit**
```bash
cd /Users/kris/code/boss
git add tests/master-agent-prompts-memory-state.test.ts src/lib/boss-data.ts src/lib/boss-projections.ts
git commit -m "feat: add master-agent prompt and memory state"
```
### Task 2: 接入主 Agent 执行链,真正合成三层提示词与用户记忆
**Files:**
- Modify: `/Users/kris/code/boss/src/lib/boss-master-agent.ts`
- Test: `/Users/kris/code/boss/tests/master-agent-prompt-assembly.test.ts`
- [ ] **Step 1: 写失败测试,覆盖提示词和记忆的执行合成顺序**
```ts
import test from "node:test";
import assert from "node:assert/strict";
import {
updateMasterAgentPromptPolicy,
updateUserMasterPrompt,
updateProjectAgentControls,
createUserMasterMemory,
} from "@/lib/boss-data";
import { buildMasterAgentExecutionEnvelopeForTesting } from "@/lib/boss-master-agent";
test("主 Agent 执行上下文按全局提示词 -> 用户提示词 -> 对话提示词 -> 相关记忆拼装", async () => {
await updateMasterAgentPromptPolicy({
globalPrompt: "全局规则:回复务必中文。",
updatedBy: "17600003315",
});
await updateUserMasterPrompt("17600003315", "用户规则:尽量直接给下一步。");
await updateProjectAgentControls("master-agent", {
promptOverride: "当前对话:优先聚焦主 Agent 聊天链。",
});
await createUserMasterMemory({
account: "17600003315",
scope: "global",
title: "长期偏好",
content: "用户偏好微信式交互。",
memoryType: "user_preference",
tags: ["UI"],
});
await createUserMasterMemory({
account: "17600003315",
scope: "project",
projectId: "master-agent",
title: "当前主链",
content: "当前优先打通主 Agent 聊天体验。",
memoryType: "project_progress",
tags: ["聊天"],
});
const digest = await buildMasterAgentExecutionEnvelopeForTesting({
projectId: "master-agent",
account: "17600003315",
requestText: "下一步做什么?",
});
assert.match(digest, /全局规则:回复务必中文/);
assert.match(digest, /用户规则:尽量直接给下一步/);
assert.match(digest, /当前对话:优先聚焦主 Agent 聊天链/);
assert.match(digest, /用户偏好微信式交互/);
assert.match(digest, /当前优先打通主 Agent 聊天体验/);
});
```
- [ ] **Step 2: 跑测试确认当前失败**
Run:
```bash
cd /Users/kris/code/boss
npx --yes tsx --test tests/master-agent-prompt-assembly.test.ts
```
Expected:
```text
FAIL ... buildMasterAgentExecutionEnvelopeForTesting is not a function
```
- [ ] **Step 3: 在 `boss-master-agent.ts` 中增加提示词/记忆解析函数**
```ts
async function resolveMasterAgentPromptLayers(account: string, projectId: string) {
const [policy, userPrompt, controls, memories] = await Promise.all([
getMasterAgentPromptPolicy(),
getUserMasterPrompt(account),
getProjectAgentControls(projectId),
listUserMasterMemories(account, {
includeArchived: false,
projectId,
}),
]);
return {
globalPrompt: policy?.globalPrompt?.trim() || "",
userPrompt: userPrompt?.content?.trim() || "",
conversationPrompt: controls?.promptOverride?.trim() || "",
memories,
};
}
```
- [ ] **Step 4: 实现最终 prompt/记忆组合**
```ts
function buildPromptAssembly(input: {
globalPrompt: string;
userPrompt: string;
conversationPrompt: string;
memories: MasterAgentMemory[];
}) {
const sections = [
input.globalPrompt && `【管理员全局主提示词】\n${input.globalPrompt}`,
input.userPrompt && `【用户私有主提示词】\n${input.userPrompt}`,
input.conversationPrompt && `【当前对话附加提示词】\n${input.conversationPrompt}`,
input.memories.length
? `【记忆】\n${input.memories.map((item) => `- ${item.title}${item.content}`).join("\n")}`
: "",
].filter(Boolean);
return sections.join("\n\n");
}
```
- [ ] **Step 5: 把组合结果接到 OpenAI / Master Node 执行路径**
```ts
const promptLayers = await resolveMasterAgentPromptLayers(params.requestedByAccount ?? "", "master-agent");
const assembledPrompt = buildPromptAssembly(promptLayers);
const instructions = [
buildMasterAgentInstructions(),
assembledPrompt,
].filter(Boolean).join("\n\n");
```
- [ ] **Step 6: 再跑测试确认通过**
Run:
```bash
cd /Users/kris/code/boss
npx --yes tsx --test tests/master-agent-prompt-assembly.test.ts
```
Expected:
```text
# tests 1
# pass 1
```
- [ ] **Step 7: Commit**
```bash
cd /Users/kris/code/boss
git add tests/master-agent-prompt-assembly.test.ts src/lib/boss-master-agent.ts
git commit -m "feat: apply layered prompts and memories to master-agent"
```
### Task 3: 加入自动记忆沉淀、项目/用户分流与基础去重
**Files:**
- Modify: `/Users/kris/code/boss/src/lib/boss-master-agent.ts`
- Modify: `/Users/kris/code/boss/src/lib/boss-data.ts`
- Test: `/Users/kris/code/boss/tests/master-agent-memory-ingestion.test.ts`
- [ ] **Step 1: 写失败测试,覆盖项目记忆和用户记忆自动分流**
```ts
import test from "node:test";
import assert from "node:assert/strict";
import { ingestMasterAgentMemoriesForTesting } from "@/lib/boss-master-agent";
import { listUserMasterMemories } from "@/lib/boss-data";
test("自动记忆沉淀会按项目进度与用户偏好分流", async () => {
await ingestMasterAgentMemoriesForTesting({
account: "17600003315",
projectId: "master-agent",
userMessage: "我更喜欢微信式交互,这个项目当前重点是主 Agent 聊天主链。",
replyText: "收到。",
});
const memories = await listUserMasterMemories("17600003315", { includeArchived: false });
assert.ok(memories.some((item) => item.scope === "global" && /微信式交互/.test(item.content)));
assert.ok(memories.some((item) => item.scope === "project" && item.projectId === "master-agent" && /主 Agent 聊天主链/.test(item.content)));
});
```
- [ ] **Step 2: 跑测试确认当前失败**
Run:
```bash
cd /Users/kris/code/boss
npx --yes tsx --test tests/master-agent-memory-ingestion.test.ts
```
Expected:
```text
FAIL ... ingestMasterAgentMemoriesForTesting is not a function
```
- [ ] **Step 3: 实现基础自动分类规则**
```ts
function inferMemoryCandidates(input: { userMessage: string; projectId: string }) {
const candidates = [];
if (/微信式交互|中文回复|直接给下一步/.test(input.userMessage)) {
candidates.push({
scope: "global",
memoryType: "user_preference",
title: "用户偏好",
content: input.userMessage,
});
}
if (/项目|主链|阻塞|进度|决策/.test(input.userMessage)) {
candidates.push({
scope: "project",
projectId: input.projectId,
memoryType: "project_progress",
title: "项目进度",
content: input.userMessage,
});
}
return candidates;
}
```
- [ ] **Step 4: 实现基础去重/合并**
```ts
function isSimilarMemory(existing: MasterAgentMemory, incoming: {
scope: MasterMemoryScope;
projectId?: string;
title: string;
memoryType: MasterMemoryType;
}) {
return (
existing.scope === incoming.scope &&
(existing.projectId || "") === (incoming.projectId || "") &&
existing.memoryType === incoming.memoryType &&
existing.title === incoming.title
);
}
```
- [ ] **Step 5: 在主 Agent 回复完成链路里接自动沉淀**
```ts
if (params.requestedByAccount) {
await maybeIngestMasterAgentMemories({
account: params.requestedByAccount,
projectId: "master-agent",
userMessage: params.requestText,
replyText: generated.content,
sourceMessageId: params.requestMessageId,
});
}
```
- [ ] **Step 6: 再跑测试确认通过**
Run:
```bash
cd /Users/kris/code/boss
npx --yes tsx --test tests/master-agent-memory-ingestion.test.ts
```
Expected:
```text
# tests 1
# pass 1
```
- [ ] **Step 7: Commit**
```bash
cd /Users/kris/code/boss
git add tests/master-agent-memory-ingestion.test.ts src/lib/boss-master-agent.ts src/lib/boss-data.ts
git commit -m "feat: auto-ingest master-agent memories"
```
### Task 4: 新增管理员全局主提示词 Web 后台接口与页面
**Files:**
- Create: `/Users/kris/code/boss/src/app/api/v1/master-agent/prompt-policy/route.ts`
- Create: `/Users/kris/code/boss/src/app/me/ops/master-agent/page.tsx`
- Test: `/Users/kris/code/boss/tests/master-agent-prompt-policy-route.test.ts`
- [ ] **Step 1: 写失败测试,覆盖管理员可读写全局主提示词**
```ts
import test from "node:test";
import assert from "node:assert/strict";
import { NextRequest } from "next/server";
import { GET, POST } from "@/app/api/v1/master-agent/prompt-policy/route";
test("管理员可读写全局主提示词", async () => {
const post = await POST(new NextRequest("http://127.0.0.1:3000/api/v1/master-agent/prompt-policy", {
method: "POST",
headers: {
"content-type": "application/json",
cookie: await createAdminCookieForTesting(),
},
body: JSON.stringify({ globalPrompt: "全局主提示词" }),
}));
assert.equal(post.status, 200);
const get = await GET(new NextRequest("http://127.0.0.1:3000/api/v1/master-agent/prompt-policy", {
headers: { cookie: await createAdminCookieForTesting() },
}));
const payload = await get.json();
assert.equal(payload.policy.globalPrompt, "全局主提示词");
});
```
- [ ] **Step 2: 跑测试确认当前失败**
Run:
```bash
cd /Users/kris/code/boss
npx --yes tsx --test tests/master-agent-prompt-policy-route.test.ts
```
Expected:
```text
FAIL ... Cannot find module ... prompt-policy/route
```
- [ ] **Step 3: 实现路由**
```ts
export async function GET(request: NextRequest) {
const session = await requireRequestSession(request);
if (!session) return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 });
if (session.role !== "highest_admin") {
return NextResponse.json({ ok: false, message: "FORBIDDEN" }, { status: 403 });
}
const policy = await getMasterAgentPromptPolicy();
return NextResponse.json({ ok: true, policy });
}
```
- [ ] **Step 4: 实现 Web 后台页面**
```tsx
export default async function MasterAgentPromptPolicyPage() {
const policy = await getMasterAgentPromptPolicy();
return (
<main className="mx-auto max-w-3xl p-6">
<h1 className="text-xl font-semibold"> Agent 全局主提示词</h1>
<p className="mt-2 text-sm text-slate-500">这层提示词对所有用户生效,且不可被覆盖。</p>
<PromptPolicyEditor initialPrompt={policy?.globalPrompt ?? ""} />
</main>
);
}
```
- [ ] **Step 5: 再跑测试确认通过**
Run:
```bash
cd /Users/kris/code/boss
npx --yes tsx --test tests/master-agent-prompt-policy-route.test.ts
```
Expected:
```text
# tests 1
# pass 1
```
- [ ] **Step 6: Commit**
```bash
cd /Users/kris/code/boss
git add src/app/api/v1/master-agent/prompt-policy/route.ts src/app/me/ops/master-agent/page.tsx tests/master-agent-prompt-policy-route.test.ts
git commit -m "feat: add master-agent global prompt policy"
```
### Task 5: 新增用户提示词与记忆 API
**Files:**
- Create: `/Users/kris/code/boss/src/app/api/v1/master-agent/user-prompt/route.ts`
- Create: `/Users/kris/code/boss/src/app/api/v1/master-agent/memories/route.ts`
- Create: `/Users/kris/code/boss/src/app/api/v1/master-agent/memories/[memoryId]/route.ts`
- Test: `/Users/kris/code/boss/tests/master-agent-memory-routes.test.ts`
- [ ] **Step 1: 写失败测试,覆盖用户私有提示词与记忆 CRUD**
```ts
import test from "node:test";
import assert from "node:assert/strict";
test("用户可更新私有提示词并维护主 Agent 记忆", async () => {
const cookie = await createAdminCookieForTesting();
const promptResponse = await postUserPrompt(cookie, "请始终用中文直接回复");
assert.equal(promptResponse.status, 200);
const created = await postMemory(cookie, {
scope: "global",
title: "用户偏好",
content: "偏好微信式交互",
memoryType: "user_preference",
});
assert.equal(created.status, 200);
});
```
- [ ] **Step 2: 跑测试确认当前失败**
Run:
```bash
cd /Users/kris/code/boss
npx --yes tsx --test tests/master-agent-memory-routes.test.ts
```
Expected:
```text
FAIL ... Cannot find module ... /user-prompt/route
```
- [ ] **Step 3: 实现用户私有提示词路由**
```ts
export async function POST(request: NextRequest) {
const session = await requireRequestSession(request);
if (!session) return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 });
const body = await request.json();
const prompt = await updateUserMasterPrompt(session.account, String(body.content ?? ""));
return NextResponse.json({ ok: true, prompt });
}
```
- [ ] **Step 4: 实现记忆列表与新增路由**
```ts
export async function GET(request: NextRequest) {
const session = await requireRequestSession(request);
if (!session) return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 });
const { searchParams } = new URL(request.url);
const projectId = searchParams.get("projectId") ?? undefined;
const includeArchived = searchParams.get("includeArchived") === "true";
const memories = await listUserMasterMemories(session.account, { projectId, includeArchived });
return NextResponse.json({ ok: true, memories });
}
```
- [ ] **Step 5: 实现单条记忆编辑与删除路由**
```ts
export async function POST(request: NextRequest, context: { params: Promise<{ memoryId: string }> }) {
const session = await requireRequestSession(request);
if (!session) return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 });
const { memoryId } = await context.params;
const body = await request.json();
const memory = await updateUserMasterMemory(memoryId, session.account, body);
return NextResponse.json({ ok: true, memory });
}
```
- [ ] **Step 6: 再跑测试确认通过**
Run:
```bash
cd /Users/kris/code/boss
npx --yes tsx --test tests/master-agent-memory-routes.test.ts
```
Expected:
```text
# tests 1
# pass 1
```
- [ ] **Step 7: Commit**
```bash
cd /Users/kris/code/boss
git add src/app/api/v1/master-agent/user-prompt/route.ts src/app/api/v1/master-agent/memories/route.ts src/app/api/v1/master-agent/memories/[memoryId]/route.ts tests/master-agent-memory-routes.test.ts
git commit -m "feat: add master-agent prompt and memory routes"
```
### Task 6: Android 三点菜单新增提示词与记忆入口,并实现原生提示词页
**Files:**
- Modify: `/Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java`
- Modify: `/Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/BossApiClient.java`
- Create: `/Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/MasterAgentPromptActivity.java`
- Test: `/Users/kris/code/boss/android/app/src/test/java/com/hyzq/boss/ProjectDetailActivityMasterAgentMenuTest.java`
- Test: `/Users/kris/code/boss/android/app/src/test/java/com/hyzq/boss/MasterAgentPromptActivityTest.java`
- [ ] **Step 1: 写失败测试,覆盖三点菜单新增项**
```java
@Test
public void masterAgentMenuShowsPromptAndMemoryEntries() {
ProjectDetailActivity activity = Robolectric.buildActivity(ProjectDetailActivity.class).setup().get();
ReflectionHelpers.setField(activity, "projectId", "master-agent");
ReflectionHelpers.callInstanceMethod(activity, "showMasterAgentMoreMenu");
AlertDialog dialog = ShadowAlertDialog.getLatestAlertDialog();
ListView listView = dialog.getListView();
assertMenuItem(listView, 0, "提示词");
assertMenuItem(listView, 1, "记忆");
assertMenuItem(listView, 2, "模型");
}
```
- [ ] **Step 2: 跑测试确认当前失败**
Run:
```bash
cd /Users/kris/code/boss/android
./gradlew testDebugUnitTest --tests com.hyzq.boss.ProjectDetailActivityMasterAgentMenuTest --no-daemon
```
Expected:
```text
FAIL ... expected 提示词
```
- [ ] **Step 3: 扩展 Android API 客户端**
```java
public ApiResponse getMasterAgentPromptPolicy() throws IOException, JSONException {
return requestWithRestore("GET", "/api/v1/master-agent/prompt-policy", null);
}
public ApiResponse getUserMasterPrompt() throws IOException, JSONException {
return requestWithRestore("GET", "/api/v1/master-agent/user-prompt", null);
}
public ApiResponse updateUserMasterPrompt(String content) throws IOException, JSONException {
JSONObject payload = new JSONObject().put("content", content);
return requestWithRestore("POST", "/api/v1/master-agent/user-prompt", payload);
}
```
- [ ] **Step 4: 把聊天页三点菜单扩成提示词/记忆/模型/推理强度/会话信息/刷新**
```java
new AlertDialog.Builder(this)
.setItems(new CharSequence[]{"提示词", "记忆", "模型", "推理强度", "会话信息", "刷新"}, (dialog, which) -> {
if (which == 0) openMasterAgentPrompt();
else if (which == 1) openMasterAgentMemories();
else if (which == 2) showMasterAgentModelPicker();
else if (which == 3) showMasterAgentReasoningPicker();
else if (which == 4) openConversationInfo();
else reload(true);
})
.show();
```
- [ ] **Step 5: 实现原生提示词页**
```java
public class MasterAgentPromptActivity extends BossScreenActivity {
// 显示管理员全局主提示词(只读)
// 显示我的主提示词(可编辑)
// 显示当前对话附加提示词(可编辑)
// 显示“查看组合结果”
}
```
- [ ] **Step 6: 再跑 Android 单测确认通过**
Run:
```bash
cd /Users/kris/code/boss/android
./gradlew testDebugUnitTest --tests com.hyzq.boss.ProjectDetailActivityMasterAgentMenuTest --tests com.hyzq.boss.MasterAgentPromptActivityTest --no-daemon
```
Expected:
```text
BUILD SUCCESSFUL
```
- [ ] **Step 7: Commit**
```bash
cd /Users/kris/code/boss
git add android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java android/app/src/main/java/com/hyzq/boss/BossApiClient.java android/app/src/main/java/com/hyzq/boss/MasterAgentPromptActivity.java android/app/src/test/java/com/hyzq/boss/ProjectDetailActivityMasterAgentMenuTest.java android/app/src/test/java/com/hyzq/boss/MasterAgentPromptActivityTest.java
git commit -m "feat: add master-agent prompt editor on android"
```
### Task 7: 实现原生记忆页,支持新增/编辑/删除
**Files:**
- Modify: `/Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/BossApiClient.java`
- Create: `/Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/MasterAgentMemoriesActivity.java`
- Test: `/Users/kris/code/boss/android/app/src/test/java/com/hyzq/boss/MasterAgentMemoriesActivityTest.java`
- [ ] **Step 1: 写失败测试,覆盖记忆页的新增、编辑、删除入口**
```java
@Test
public void memoriesScreenShowsAddEditDeleteActions() {
MasterAgentMemoriesActivity activity = Robolectric.buildActivity(MasterAgentMemoriesActivity.class).setup().get();
LinearLayout root = activity.findViewById(R.id.screen_content_container);
assertTrue(viewTreeContainsText(root, "新增记忆"));
}
```
- [ ] **Step 2: 跑测试确认当前失败**
Run:
```bash
cd /Users/kris/code/boss/android
./gradlew testDebugUnitTest --tests com.hyzq.boss.MasterAgentMemoriesActivityTest --no-daemon
```
Expected:
```text
FAIL ... MasterAgentMemoriesActivity not found
```
- [ ] **Step 3: 扩展 Android API 客户端接记忆路由**
```java
public ApiResponse listMasterAgentMemories(@Nullable String projectId) throws IOException, JSONException {
String path = "/api/v1/master-agent/memories";
if (projectId != null && !projectId.isEmpty()) {
path += "?projectId=" + Uri.encode(projectId);
}
return requestWithRestore("GET", path, null);
}
```
- [ ] **Step 4: 实现原生记忆页**
```java
public class MasterAgentMemoriesActivity extends BossScreenActivity {
// section 1: 项目记忆
// section 2: 我的通用记忆
// 每条卡片支持编辑/删除
// 顶部提供新增记忆
}
```
- [ ] **Step 5: 实现新增/编辑/删除对话框**
```java
private void showMemoryEditor(@Nullable JSONObject memory) {
// title + content + scope + memoryType + tags
}
```
- [ ] **Step 6: 再跑 Android 单测确认通过**
Run:
```bash
cd /Users/kris/code/boss/android
./gradlew testDebugUnitTest --tests com.hyzq.boss.MasterAgentMemoriesActivityTest --no-daemon
```
Expected:
```text
BUILD SUCCESSFUL
```
- [ ] **Step 7: Commit**
```bash
cd /Users/kris/code/boss
git add android/app/src/main/java/com/hyzq/boss/BossApiClient.java android/app/src/main/java/com/hyzq/boss/MasterAgentMemoriesActivity.java android/app/src/test/java/com/hyzq/boss/MasterAgentMemoriesActivityTest.java
git commit -m "feat: add master-agent memories screen on android"
```
### Task 8: 同步 Web 前台、Android Manifest、文档并做总验证
**Files:**
- Modify: `/Users/kris/code/boss/android/app/src/main/AndroidManifest.xml`
- Modify: `/Users/kris/code/boss/README.md`
- Modify: `/Users/kris/code/boss/docs/architecture/current_runtime_and_deploy_status_cn.md`
- Modify: `/Users/kris/code/boss/docs/architecture/api_and_service_inventory_cn.md`
- [ ] **Step 1: 在 Android Manifest 注册新增页面**
```xml
<activity android:name=".MasterAgentPromptActivity" android:exported="false" />
<activity android:name=".MasterAgentMemoriesActivity" android:exported="false" />
```
- [ ] **Step 2: 同步 README 和架构文档**
```md
- 主 Agent 聊天页右上角当前已新增 `提示词 / 记忆 / 模型 / 推理强度 / 会话信息 / 刷新`
- 管理员全局主提示词当前由 Web 后台配置,用户端只读
- 用户记忆当前分为项目记忆和用户通用记忆,并支持自动沉淀与手动管理
```
- [ ] **Step 3: 跑 Node 测试**
Run:
```bash
cd /Users/kris/code/boss
npx --yes tsx --test tests/master-agent-prompts-memory-state.test.ts tests/master-agent-prompt-assembly.test.ts tests/master-agent-memory-ingestion.test.ts tests/master-agent-prompt-policy-route.test.ts tests/master-agent-memory-routes.test.ts tests/master-agent-chat-controls.test.ts tests/master-agent-message-queue.test.ts
```
Expected:
```text
all tests pass
```
- [ ] **Step 4: 跑 Android 单测**
Run:
```bash
cd /Users/kris/code/boss/android
./gradlew testDebugUnitTest --tests com.hyzq.boss.ProjectDetailActivityMasterAgentMenuTest --tests com.hyzq.boss.MasterAgentPromptActivityTest --tests com.hyzq.boss.MasterAgentMemoriesActivityTest --tests com.hyzq.boss.AiAccountsActivityTest --no-daemon
```
Expected:
```text
BUILD SUCCESSFUL
```
- [ ] **Step 5: 跑 lint 和 build**
Run:
```bash
cd /Users/kris/code/boss
npm run lint
npm run build
```
Expected:
```text
lint 通过
build 通过
```
- [ ] **Step 6: Commit**
```bash
cd /Users/kris/code/boss
git add android/app/src/main/AndroidManifest.xml README.md docs/architecture/current_runtime_and_deploy_status_cn.md docs/architecture/api_and_service_inventory_cn.md
git commit -m "docs: sync master-agent prompts and memories runtime"
```