feat: finish master-agent prompt and memory runtime
This commit is contained in:
@@ -171,6 +171,66 @@ test("master-agent 对话控制路由可读写并回显到项目详情", async (
|
||||
assert.equal(projectPayload.agentControls?.reasoningEffortOverride, "medium");
|
||||
});
|
||||
|
||||
test("master-agent 对话控制按当前账号隔离,不会串到其他用户", async () => {
|
||||
await setup();
|
||||
|
||||
const adminSession = await createAuthSession({
|
||||
account: "17600003315",
|
||||
role: "highest_admin",
|
||||
displayName: "Boss 超级管理员",
|
||||
loginMethod: "password",
|
||||
});
|
||||
const memberSession = await createAuthSession({
|
||||
account: "18800001111",
|
||||
role: "member",
|
||||
displayName: "普通成员",
|
||||
loginMethod: "password",
|
||||
});
|
||||
|
||||
const adminHeaders = {
|
||||
"content-type": "application/json",
|
||||
cookie: `${AUTH_SESSION_COOKIE}=${adminSession.sessionToken}`,
|
||||
};
|
||||
const memberHeaders = {
|
||||
"content-type": "application/json",
|
||||
cookie: `${AUTH_SESSION_COOKIE}=${memberSession.sessionToken}`,
|
||||
};
|
||||
|
||||
await postAgentControlsRoute(
|
||||
new NextRequest("http://127.0.0.1:3000/api/v1/projects/master-agent/agent-controls", {
|
||||
method: "POST",
|
||||
headers: adminHeaders,
|
||||
body: JSON.stringify({
|
||||
modelOverride: "gpt-5.4",
|
||||
reasoningEffortOverride: "high",
|
||||
}),
|
||||
}),
|
||||
{ params: Promise.resolve({ projectId: "master-agent" }) },
|
||||
);
|
||||
|
||||
const adminGet = await getAgentControlsRoute(
|
||||
new NextRequest("http://127.0.0.1:3000/api/v1/projects/master-agent/agent-controls", {
|
||||
method: "GET",
|
||||
headers: adminHeaders,
|
||||
}),
|
||||
{ params: Promise.resolve({ projectId: "master-agent" }) },
|
||||
);
|
||||
const memberGet = await getAgentControlsRoute(
|
||||
new NextRequest("http://127.0.0.1:3000/api/v1/projects/master-agent/agent-controls", {
|
||||
method: "GET",
|
||||
headers: memberHeaders,
|
||||
}),
|
||||
{ params: Promise.resolve({ projectId: "master-agent" }) },
|
||||
);
|
||||
|
||||
const adminPayload = (await adminGet.json()) as { controls: { modelOverride?: string; reasoningEffortOverride?: string } | null };
|
||||
const memberPayload = (await memberGet.json()) as { controls: { modelOverride?: string; reasoningEffortOverride?: string } | null };
|
||||
|
||||
assert.equal(adminPayload.controls?.modelOverride, "gpt-5.4");
|
||||
assert.equal(adminPayload.controls?.reasoningEffortOverride, "high");
|
||||
assert.equal(memberPayload.controls, null);
|
||||
});
|
||||
|
||||
test("master-agent 对话控制路由单字段更新不会清掉另一字段", async () => {
|
||||
await setup();
|
||||
|
||||
@@ -297,7 +357,7 @@ test("非 master-agent 项目详情不应回传 agentControls 字段", async ()
|
||||
assert.equal(Object.prototype.hasOwnProperty.call(payload, "agentControls"), false);
|
||||
});
|
||||
|
||||
test("master-agent 对话控制 POST 仅允许 highest_admin 修改", async () => {
|
||||
test("master-agent 对话控制 POST 允许当前用户修改自己的 master-agent 会话配置", async () => {
|
||||
await setup();
|
||||
|
||||
const session = await createAuthSession({
|
||||
@@ -322,14 +382,19 @@ test("master-agent 对话控制 POST 仅允许 highest_admin 修改", async () =
|
||||
{ params: Promise.resolve({ projectId: "master-agent" }) },
|
||||
);
|
||||
|
||||
assert.equal(response.status, 403);
|
||||
assert.equal(response.status, 200);
|
||||
|
||||
const payload = (await response.json()) as { ok: boolean; message: string };
|
||||
assert.equal(payload.ok, false);
|
||||
assert.equal(payload.message, "FORBIDDEN");
|
||||
const payload = (await response.json()) as {
|
||||
ok: boolean;
|
||||
controls: { modelOverride?: string; reasoningEffortOverride?: string } | null;
|
||||
};
|
||||
assert.equal(payload.ok, true);
|
||||
assert.equal(payload.controls?.modelOverride, "gpt-5.4");
|
||||
assert.equal(payload.controls?.reasoningEffortOverride, "low");
|
||||
|
||||
const controls = await getProjectAgentControls("master-agent");
|
||||
assert.equal(controls, null);
|
||||
const controls = await getProjectAgentControls("master-agent", "viewer-0001");
|
||||
assert.equal(controls?.modelOverride, "gpt-5.4");
|
||||
assert.equal(controls?.reasoningEffortOverride, "low");
|
||||
});
|
||||
|
||||
test("master-agent 对话控制 POST 会稳定拒绝非法 modelOverride", async () => {
|
||||
|
||||
@@ -12,6 +12,8 @@ let getMasterAgentPromptPolicyRoute: typeof import("../src/app/api/v1/master-age
|
||||
let getUserMasterPromptRoute: typeof import("../src/app/api/v1/master-agent/prompt/route");
|
||||
let getUserMasterMemoriesRoute: typeof import("../src/app/api/v1/master-agent/memories/route");
|
||||
let patchUserMasterMemoryRoute: typeof import("../src/app/api/v1/master-agent/memories/[memoryId]/route");
|
||||
let getProjectMemoriesRoute: typeof import("../src/app/api/v1/projects/[projectId]/memories/route");
|
||||
let getPromptProfileRoute: typeof import("../src/app/api/v1/projects/[projectId]/prompt-profile/route");
|
||||
|
||||
async function setup() {
|
||||
if (runtimeRoot) return;
|
||||
@@ -20,13 +22,15 @@ async function setup() {
|
||||
process.env.BOSS_RUNTIME_ROOT = runtimeRoot;
|
||||
process.env.BOSS_STATE_FILE = path.join(runtimeRoot, "boss-state.json");
|
||||
|
||||
const [data, auth, promptPolicyRoute, userPromptRoute, memoriesRoute, memoryRoute] = await Promise.all([
|
||||
const [data, auth, promptPolicyRoute, userPromptRoute, memoriesRoute, memoryRoute, projectMemoriesRoute, promptProfileRoute] = await Promise.all([
|
||||
import("../src/lib/boss-data.ts"),
|
||||
import("../src/lib/boss-auth.ts"),
|
||||
import("../src/app/api/v1/master-agent/prompt-policy/route.ts"),
|
||||
import("../src/app/api/v1/master-agent/prompt/route.ts"),
|
||||
import("../src/app/api/v1/master-agent/memories/route.ts"),
|
||||
import("../src/app/api/v1/master-agent/memories/[memoryId]/route.ts"),
|
||||
import("../src/app/api/v1/projects/[projectId]/memories/route.ts"),
|
||||
import("../src/app/api/v1/projects/[projectId]/prompt-profile/route.ts"),
|
||||
]);
|
||||
|
||||
createAuthSession = data.createAuthSession;
|
||||
@@ -35,6 +39,8 @@ async function setup() {
|
||||
getUserMasterPromptRoute = userPromptRoute;
|
||||
getUserMasterMemoriesRoute = memoriesRoute;
|
||||
patchUserMasterMemoryRoute = memoryRoute;
|
||||
getProjectMemoriesRoute = projectMemoriesRoute.GET;
|
||||
getPromptProfileRoute = promptProfileRoute.POST;
|
||||
}
|
||||
|
||||
async function createAuthedRequest(account = "17600003315", role: "member" | "admin" | "highest_admin" = "highest_admin") {
|
||||
@@ -129,3 +135,81 @@ test("master-agent prompt and memory routes support admin prompt, user prompt, a
|
||||
);
|
||||
assert.equal(patchResponse.status, 200);
|
||||
});
|
||||
|
||||
test("master-agent 记忆页会返回当前用户所有项目记忆", async () => {
|
||||
await setup();
|
||||
const adminRequest = await createAuthedRequest();
|
||||
|
||||
await getUserMasterMemoriesRoute.POST(
|
||||
new NextRequest("http://127.0.0.1:3000/api/v1/master-agent/memories", {
|
||||
method: "POST",
|
||||
headers: adminRequest.headers,
|
||||
body: JSON.stringify({
|
||||
scope: "project",
|
||||
projectId: "boss-console",
|
||||
title: "Boss 进度",
|
||||
content: "Boss 项目聊天主链已接通。",
|
||||
memoryType: "project_progress",
|
||||
}),
|
||||
}),
|
||||
);
|
||||
await getUserMasterMemoriesRoute.POST(
|
||||
new NextRequest("http://127.0.0.1:3000/api/v1/master-agent/memories", {
|
||||
method: "POST",
|
||||
headers: adminRequest.headers,
|
||||
body: JSON.stringify({
|
||||
scope: "project",
|
||||
projectId: "wenshenapp",
|
||||
title: "纹身项目进度",
|
||||
content: "wenshenapp 当前只保留一个主线程。",
|
||||
memoryType: "project_progress",
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
const response = await getProjectMemoriesRoute(
|
||||
new NextRequest("http://127.0.0.1:3000/api/v1/projects/master-agent/memories", {
|
||||
method: "GET",
|
||||
headers: adminRequest.headers,
|
||||
}),
|
||||
{ params: Promise.resolve({ projectId: "master-agent" }) },
|
||||
);
|
||||
|
||||
assert.equal(response.status, 200);
|
||||
const payload = (await response.json()) as {
|
||||
ok: boolean;
|
||||
memories: { project: Array<{ projectId?: string }> };
|
||||
};
|
||||
assert.equal(payload.ok, true);
|
||||
assert.deepEqual(
|
||||
payload.memories.project.map((memory) => memory.projectId).sort(),
|
||||
["boss-console", "master-agent", "wenshenapp"].sort(),
|
||||
);
|
||||
});
|
||||
|
||||
test("prompt-profile 写入当前对话提示词时按当前账号隔离", async () => {
|
||||
await setup();
|
||||
|
||||
const memberRequest = await createAuthedRequest("18800001111", "member");
|
||||
|
||||
const response = await getPromptProfileRoute(
|
||||
new NextRequest("http://127.0.0.1:3000/api/v1/projects/master-agent/prompt-profile", {
|
||||
method: "POST",
|
||||
headers: memberRequest.headers,
|
||||
body: JSON.stringify({
|
||||
promptOverride: "成员自己的当前对话提示词",
|
||||
}),
|
||||
}),
|
||||
{ params: Promise.resolve({ projectId: "master-agent" }) },
|
||||
);
|
||||
|
||||
assert.equal(response.status, 200);
|
||||
const payload = (await response.json()) as {
|
||||
ok: boolean;
|
||||
projectPromptOverride: string | null;
|
||||
account: string;
|
||||
};
|
||||
assert.equal(payload.ok, true);
|
||||
assert.equal(payload.account, "18800001111");
|
||||
assert.equal(payload.projectPromptOverride, "成员自己的当前对话提示词");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user