feat: ship enterprise control and desktop governance
This commit is contained in:
@@ -103,7 +103,7 @@ function buildDispatchableThreadProject({
|
||||
|
||||
async function createAuthedRequest(projectId: string, body: { body: string; kind?: string }) {
|
||||
const session = await createAuthSession({
|
||||
account: "17600003315",
|
||||
account: "krisolo",
|
||||
role: "highest_admin",
|
||||
displayName: "Boss 超级管理员",
|
||||
loginMethod: "password",
|
||||
@@ -156,7 +156,7 @@ test("POST /api/v1/projects/[projectId]/messages returns a dispatch plan for gro
|
||||
|
||||
const groupProject = await createIndependentGroupChat({
|
||||
memberProjectIds: [memberProjects[0].id, memberProjects[1].id],
|
||||
createdBy: "17600003315",
|
||||
createdBy: "krisolo",
|
||||
});
|
||||
|
||||
const response = await POST(await createAuthedRequest(groupProject.id, { body: "请大家汇总今天的阻塞点" }), {
|
||||
@@ -275,6 +275,57 @@ test("POST /api/v1/projects/master-agent/messages returns a dispatch plan for th
|
||||
assert.ok(queuedDispatchTask, "expected master-agent thread-op request to enqueue a dispatch recommendation task");
|
||||
});
|
||||
|
||||
test("POST /api/v1/projects/master-agent/messages routes named project summary sync to the target thread understanding task", async () => {
|
||||
await setup();
|
||||
const [primaryProject] = await ensureTwoSingleThreadProjects();
|
||||
assert.ok(primaryProject, "expected seeded single-thread project");
|
||||
|
||||
const response = await POST(
|
||||
await createAuthedRequest("master-agent", {
|
||||
body: "请同步一下北区试产线回归当前项目目标和版本记录",
|
||||
}),
|
||||
{ params: Promise.resolve({ projectId: "master-agent" }) },
|
||||
);
|
||||
assert.equal(response.status, 200);
|
||||
|
||||
const payload = (await response.json()) as {
|
||||
ok: boolean;
|
||||
message: { id: string; body: string };
|
||||
replyMessage?: { body: string };
|
||||
task?: { taskId: string; taskType: string; status: string } | null;
|
||||
dispatchPlan: null | { planId: string };
|
||||
masterReply?: { ok: boolean; masterReplyState?: string };
|
||||
};
|
||||
|
||||
assert.equal(payload.ok, true);
|
||||
assert.equal(payload.dispatchPlan, null);
|
||||
assert.equal(payload.masterReply?.masterReplyState, "queued");
|
||||
assert.ok(payload.replyMessage?.body.includes("北区试产线回归"));
|
||||
assert.ok(payload.replyMessage?.body.includes("项目目标"));
|
||||
assert.ok(payload.replyMessage?.body.includes("版本记录"));
|
||||
assert.ok(!/OTA|MVP|设备在线|运行时/.test(payload.replyMessage?.body ?? ""));
|
||||
|
||||
const nextState = await readState();
|
||||
const syncTask = nextState.masterAgentTasks.find(
|
||||
(task) =>
|
||||
task.projectId === "master-agent" &&
|
||||
task.projectUnderstandingTargetProjectId === primaryProject.id &&
|
||||
task.requestText.includes(primaryProject.name),
|
||||
);
|
||||
assert.ok(syncTask, "expected target project understanding sync task");
|
||||
assert.equal(payload.task?.taskId, syncTask?.taskId);
|
||||
assert.match(syncTask!.executionPrompt, /只输出 JSON/);
|
||||
assert.match(syncTask!.executionPrompt, /不要把全局 OTA 可用状态/);
|
||||
|
||||
const genericDispatchTask = nextState.masterAgentTasks.find(
|
||||
(task) =>
|
||||
task.projectId === "master-agent" &&
|
||||
task.requestMessageId === payload.message.id &&
|
||||
task.taskType === "group_dispatch_plan",
|
||||
);
|
||||
assert.equal(genericDispatchTask, undefined, "summary sync should not create a generic dispatch plan");
|
||||
});
|
||||
|
||||
test("POST /api/v1/projects/[projectId]/messages marks approval_required groups as pending user approval", async () => {
|
||||
await setup();
|
||||
const memberProjects = await ensureTwoSingleThreadProjects();
|
||||
@@ -282,7 +333,7 @@ test("POST /api/v1/projects/[projectId]/messages marks approval_required groups
|
||||
|
||||
const groupProject = await createIndependentGroupChat({
|
||||
memberProjectIds: [memberProjects[0].id, memberProjects[1].id],
|
||||
createdBy: "17600003315",
|
||||
createdBy: "krisolo",
|
||||
});
|
||||
|
||||
const state = await readState();
|
||||
@@ -343,7 +394,7 @@ test("POST /api/v1/projects/[projectId]/messages blocks new approval_required re
|
||||
|
||||
const groupProject = await createIndependentGroupChat({
|
||||
memberProjectIds: [memberProjects[0].id, memberProjects[1].id],
|
||||
createdBy: "17600003315",
|
||||
createdBy: "krisolo",
|
||||
});
|
||||
|
||||
const state = await readState();
|
||||
@@ -413,7 +464,7 @@ test("POST /api/v1/projects/[projectId]/messages keeps message success when grou
|
||||
|
||||
const groupProject = await createIndependentGroupChat({
|
||||
memberProjectIds: [memberProjects[0].id, memberProjects[1].id],
|
||||
createdBy: "17600003315",
|
||||
createdBy: "krisolo",
|
||||
});
|
||||
|
||||
const state = await readState();
|
||||
@@ -495,7 +546,7 @@ test("POST /api/v1/projects/[projectId]/messages excludes master-agent from grou
|
||||
|
||||
const groupProject = await createIndependentGroupChat({
|
||||
memberProjectIds: [memberProjects[0].id, memberProjects[1].id],
|
||||
createdBy: "17600003315",
|
||||
createdBy: "krisolo",
|
||||
});
|
||||
|
||||
const state = await readState();
|
||||
@@ -552,7 +603,7 @@ test("createIndependentGroupChat rejects non-thread members like master-agent",
|
||||
() =>
|
||||
createIndependentGroupChat({
|
||||
memberProjectIds: ["master-agent", realThread.id],
|
||||
createdBy: "17600003315",
|
||||
createdBy: "krisolo",
|
||||
}),
|
||||
/GROUP_CHAT_MEMBER_NOT_THREAD/,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user