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"; import { NextRequest } from "next/server"; let runtimeRoot = ""; let postMessageRoute: (typeof import("../src/app/api/v1/projects/[projectId]/messages/route"))["POST"]; let getDispatchPlansRoute: (typeof import("../src/app/api/v1/projects/[projectId]/dispatch-plans/route"))["GET"]; let confirmDispatchPlanRoute: (typeof import("../src/app/api/v1/projects/[projectId]/dispatch-plans/[planId]/confirm/route"))["POST"]; let rejectDispatchPlanRoute: (typeof import("../src/app/api/v1/projects/[projectId]/dispatch-plans/[planId]/reject/route"))["POST"]; let retryDispatchPlanRoute: (typeof import("../src/app/api/v1/projects/[projectId]/dispatch-plans/[planId]/retry/route"))["POST"]; let updateDispatchReminderRoute: (typeof import("../src/app/api/v1/projects/[projectId]/dispatch-reminder/route"))["PATCH"]; let createAuthSession: (typeof import("../src/lib/boss-data"))["createAuthSession"]; let createProjectGroupChat: (typeof import("../src/lib/boss-data"))["createProjectGroupChat"]; let isDispatchableThreadProject: (typeof import("../src/lib/boss-data"))["isDispatchableThreadProject"]; let readState: (typeof import("../src/lib/boss-data"))["readState"]; let writeState: (typeof import("../src/lib/boss-data"))["writeState"]; let AUTH_SESSION_COOKIE = ""; let baseState: Awaited>; async function setup() { if (runtimeRoot) { return; } runtimeRoot = await mkdtemp(path.join(os.tmpdir(), "boss-task4-")); process.env.BOSS_RUNTIME_ROOT = runtimeRoot; process.env.BOSS_STATE_FILE = path.join(runtimeRoot, "boss-state.json"); const [messageModule, plansModule, confirmModule, rejectModule, retryModule, reminderModule, data, auth] = await Promise.all([ import("../src/app/api/v1/projects/[projectId]/messages/route.ts"), import("../src/app/api/v1/projects/[projectId]/dispatch-plans/route.ts"), import("../src/app/api/v1/projects/[projectId]/dispatch-plans/[planId]/confirm/route.ts"), import("../src/app/api/v1/projects/[projectId]/dispatch-plans/[planId]/reject/route.ts"), import("../src/app/api/v1/projects/[projectId]/dispatch-plans/[planId]/retry/route.ts"), import("../src/app/api/v1/projects/[projectId]/dispatch-reminder/route.ts"), import("../src/lib/boss-data.ts"), import("../src/lib/boss-auth.ts"), ]); postMessageRoute = messageModule.POST; getDispatchPlansRoute = plansModule.GET; confirmDispatchPlanRoute = confirmModule.POST; rejectDispatchPlanRoute = rejectModule.POST; retryDispatchPlanRoute = retryModule.POST; updateDispatchReminderRoute = reminderModule.PATCH; createAuthSession = data.createAuthSession; createProjectGroupChat = data.createProjectGroupChat; isDispatchableThreadProject = data.isDispatchableThreadProject; readState = data.readState; writeState = data.writeState; baseState = structuredClone(await readState()); AUTH_SESSION_COOKIE = auth.AUTH_SESSION_COOKIE; } test.after(async () => { if (runtimeRoot) { await rm(runtimeRoot, { recursive: true, force: true }); } }); test.beforeEach(async () => { await setup(); await writeState(structuredClone(baseState)); }); function buildDispatchableThreadProject({ id, projectName, threadDisplayName, body, }: { id: string; projectName: string; threadDisplayName: string; body: string; }) { return { id, name: projectName, pinned: false, systemPinned: false, deviceIds: ["mac-studio"], preview: body, updatedAt: "2026-03-30T10:00:00+08:00", lastMessageAt: "2026-03-30T10:00:00+08:00", isGroup: false, threadMeta: { projectId: id, threadId: `thread-${id}`, threadDisplayName, folderName: "阻塞梳理", activityIconCount: 0, updatedAt: "2026-03-30T10:00:00+08:00", codexThreadRef: `thread-${id}`, codexFolderRef: id, }, groupMembers: [], createdByAgent: true, collaborationMode: "development" as const, approvalState: "not_required" as const, unreadCount: 0, riskLevel: "low" as const, messages: [ { id: `msg-${id}`, sender: "device" as const, senderLabel: "Win GPU / Codex", body, sentAt: "2026-03-30T10:00:00+08:00", kind: "text" as const, }, ], goals: [], versions: [], }; } async function createAuthedRequest(url: string, method: "GET" | "POST" | "PATCH", body?: unknown) { const session = await createAuthSession({ account: "17600003315", role: "highest_admin", displayName: "Boss 超级管理员", loginMethod: "password", }); return new NextRequest(url, { method, headers: { "content-type": "application/json", cookie: `${AUTH_SESSION_COOKIE}=${session.sessionToken}`, }, body: body ? JSON.stringify(body) : undefined, }); } async function ensureTwoSingleThreadProjects() { const state = await readState(); const singles = state.projects.filter((project) => isDispatchableThreadProject(project)); if (singles.length >= 2) { return singles; } const freshProjects = [ buildDispatchableThreadProject({ id: "dispatch-confirm-a", projectName: "北区试产线主线程", threadDisplayName: "北区试产线回归", body: "这里还在等待主 Agent 汇总阻塞点。", }), buildDispatchableThreadProject({ id: "dispatch-confirm-b", projectName: "南区试产线主线程", threadDisplayName: "南区试产线回归", body: "这里还在等待视觉链路复核。", }), ]; await writeState({ ...state, projects: state.projects.concat(freshProjects), }); const nextState = await readState(); return nextState.projects.filter((project) => isDispatchableThreadProject(project)); } async function createDispatchPlanForTest() { await setup(); const memberProjects = await ensureTwoSingleThreadProjects(); const groupProject = await createProjectGroupChat({ sourceProjectId: memberProjects[0].id, memberProjectIds: [memberProjects[1].id], createdBy: "17600003315", }); const response = await postMessageRoute( await createAuthedRequest( `http://127.0.0.1:3000/api/v1/projects/${groupProject.id}/messages`, "POST", { body: "请主 Agent 推荐要先同步的线程" }, ), { params: Promise.resolve({ projectId: groupProject.id }) }, ); assert.equal(response.status, 200); const payload = (await response.json()) as { dispatchPlan: | { planId: string; targets: Array<{ projectId: string }>; orchestrationBackendId?: string; orchestrationBackendLabel?: string; } | null; }; assert.ok(payload.dispatchPlan, "expected seeded dispatch plan"); assert.equal(payload.dispatchPlan?.orchestrationBackendId, "boss-native-orchestrator"); assert.equal(payload.dispatchPlan?.orchestrationBackendLabel, "Boss Native Orchestrator"); return { groupProject, dispatchPlan: payload.dispatchPlan }; } async function createMasterAgentDispatchPlanForTest() { await setup(); const memberProjects = await ensureTwoSingleThreadProjects(); assert.ok(memberProjects.length >= 2, "expected dispatchable single-thread projects"); const response = await postMessageRoute( await createAuthedRequest( "http://127.0.0.1:3000/api/v1/projects/master-agent/messages", "POST", { body: "请操作真实线程,先让南区试产线回归只回复:主Agent确认链路正常" }, ), { params: Promise.resolve({ projectId: "master-agent" }) }, ); assert.equal(response.status, 200); const payload = (await response.json()) as { dispatchPlan: | { planId: string; targets: Array<{ projectId: string }>; orchestrationBackendId?: string; orchestrationBackendLabel?: string; } | null; }; assert.ok(payload.dispatchPlan, "expected master-agent dispatch plan"); return { dispatchPlan: payload.dispatchPlan }; } test("GET /api/v1/projects/[projectId]/dispatch-plans lists the latest group dispatch plans", async () => { const { groupProject, dispatchPlan } = await createDispatchPlanForTest(); const response = await getDispatchPlansRoute( await createAuthedRequest( `http://127.0.0.1:3000/api/v1/projects/${groupProject.id}/dispatch-plans`, "GET", ), { params: Promise.resolve({ projectId: groupProject.id }) }, ); assert.equal(response.status, 200); const payload = (await response.json()) as { ok: boolean; plans: Array<{ planId: string; requestMessageId: string; status: string }>; }; assert.equal(payload.ok, true); assert.equal(payload.plans[0]?.planId, dispatchPlan.planId); assert.equal(payload.plans[0]?.status, "pending_user_confirmation"); }); test("POST /api/v1/projects/[projectId]/dispatch-plans/[planId]/confirm confirms targets, creates executions, and writes a master-agent notice", async () => { const { groupProject, dispatchPlan } = await createDispatchPlanForTest(); const approvedTargetProjectId = dispatchPlan.targets[0]?.projectId; assert.ok(approvedTargetProjectId, "expected a recommended target project"); const response = await confirmDispatchPlanRoute( await createAuthedRequest( `http://127.0.0.1:3000/api/v1/projects/${groupProject.id}/dispatch-plans/${dispatchPlan.planId}/confirm`, "POST", { approvedTargetProjectIds: [approvedTargetProjectId] }, ), { params: Promise.resolve({ projectId: groupProject.id, planId: dispatchPlan.planId }) }, ); assert.equal(response.status, 200); const payload = (await response.json()) as { ok: boolean; plan: { planId: string; status: string; confirmedTargetProjectIds: string[]; orchestrationBackendId?: string; orchestrationBackendLabel?: string; }; executions: Array<{ planId: string; targetProjectId: string; status: string; orchestrationBackendId?: string; orchestrationBackendLabel?: string; }>; notice: { kind: string; body: string } | null; collaborationGate: { isGroup: boolean; collaborationMode: string; requiresMasterAgentApproval: boolean; approvalState: string; }; }; assert.equal(payload.ok, true); assert.equal(payload.plan.planId, dispatchPlan.planId); assert.equal(payload.plan.status, "dispatched"); assert.deepEqual(payload.plan.confirmedTargetProjectIds, [approvedTargetProjectId]); assert.equal(payload.executions.length, 1); assert.equal(payload.executions[0]?.planId, dispatchPlan.planId); assert.equal(payload.executions[0]?.targetProjectId, approvedTargetProjectId); assert.equal(payload.executions[0]?.status, "queued"); assert.ok(payload.notice, "expected a confirmation notice in the response"); assert.equal(payload.notice?.kind, "system_notice"); assert.equal(payload.notice?.body, "已确认下发到 1 个线程:《北区试产线回归》。"); assert.equal(payload.collaborationGate.isGroup, true); assert.equal(payload.collaborationGate.collaborationMode, "development"); assert.equal(payload.collaborationGate.requiresMasterAgentApproval, false); assert.equal(payload.collaborationGate.approvalState, "not_required"); const nextState = await readState(); const notice = nextState.projects .find((project) => project.id === groupProject.id) ?.messages.find( (message) => message.sender === "master" && message.kind === "system_notice" && message.body.includes("已确认下发到 1 个线程"), ); assert.ok(notice, "expected a master-agent notice in the group chat after confirmation"); const confirmedPlan = nextState.dispatchPlans.find((plan) => plan.planId === dispatchPlan.planId); assert.ok(confirmedPlan, "expected confirmed dispatch plan in state"); assert.equal(confirmedPlan?.orchestrationBackendId, "boss-native-orchestrator"); assert.equal(confirmedPlan?.orchestrationBackendLabel, "Boss Native Orchestrator"); const createdExecution = nextState.dispatchExecutions.find((item) => item.planId === dispatchPlan.planId); assert.ok(createdExecution, "expected dispatch execution in state"); assert.equal(createdExecution?.orchestrationBackendId, "boss-native-orchestrator"); assert.equal(createdExecution?.orchestrationBackendLabel, "Boss Native Orchestrator"); const executionTask = nextState.masterAgentTasks.find( (task) => task.taskType === "dispatch_execution" && task.projectId === groupProject.id && task.targetProjectId === approvedTargetProjectId, ); assert.ok(executionTask, "expected queued dispatch execution task"); assert.equal(executionTask?.orchestrationBackendId, "boss-native-orchestrator"); assert.equal(executionTask?.orchestrationBackendLabel, "Boss Native Orchestrator"); }); test("confirming a dispatch plan with rememberLightReminder persists the group reminder preference", async () => { const { groupProject, dispatchPlan } = await createDispatchPlanForTest(); const approvedTargetProjectId = dispatchPlan.targets[0]?.projectId; assert.ok(approvedTargetProjectId, "expected a recommended target project"); const response = await confirmDispatchPlanRoute( await createAuthedRequest( `http://127.0.0.1:3000/api/v1/projects/${groupProject.id}/dispatch-plans/${dispatchPlan.planId}/confirm`, "POST", { approvedTargetProjectIds: [approvedTargetProjectId], rememberLightReminder: true, }, ), { params: Promise.resolve({ projectId: groupProject.id, planId: dispatchPlan.planId }) }, ); assert.equal(response.status, 200); const payload = (await response.json()) as { ok: boolean; collaborationGate: { lightDispatchReminderEnabled?: boolean; }; }; assert.equal(payload.ok, true); assert.equal(payload.collaborationGate.lightDispatchReminderEnabled, true); const nextState = await readState(); const nextGroupProject = nextState.projects.find((project) => project.id === groupProject.id); assert.ok(nextGroupProject, "expected group project to remain present"); assert.equal(nextGroupProject?.lightDispatchReminderEnabled, true); }); test("master-agent dispatch plans can also be confirmed and create queued executions", async () => { const { dispatchPlan } = await createMasterAgentDispatchPlanForTest(); const approvedTargetProjectId = dispatchPlan.targets[0]?.projectId; assert.ok(approvedTargetProjectId, "expected a recommended target project"); const response = await confirmDispatchPlanRoute( await createAuthedRequest( `http://127.0.0.1:3000/api/v1/projects/master-agent/dispatch-plans/${dispatchPlan.planId}/confirm`, "POST", { approvedTargetProjectIds: [approvedTargetProjectId] }, ), { params: Promise.resolve({ projectId: "master-agent", planId: dispatchPlan.planId }) }, ); assert.equal(response.status, 200); const payload = (await response.json()) as { ok: boolean; plan: { status: string; confirmedTargetProjectIds: string[] }; executions: Array<{ targetProjectId: string; status: string }>; notice: { body: string } | null; }; assert.equal(payload.ok, true); assert.equal(payload.plan.status, "dispatched"); assert.deepEqual(payload.plan.confirmedTargetProjectIds, [approvedTargetProjectId]); assert.equal(payload.executions.length, 1); assert.equal(payload.executions[0]?.targetProjectId, approvedTargetProjectId); assert.equal(payload.executions[0]?.status, "queued"); assert.match(payload.notice?.body ?? "", /已确认下发到 1 个线程/); }); test("confirm rejects targets whose device is offline before creating queued executions", async () => { const { groupProject, dispatchPlan } = await createDispatchPlanForTest(); const approvedTargetProjectId = dispatchPlan.targets[0]?.projectId; const targetDeviceId = dispatchPlan.targets[0]?.deviceId; assert.ok(approvedTargetProjectId, "expected a recommended target project"); assert.ok(targetDeviceId, "expected a target device"); const state = await readState(); await writeState({ ...state, devices: state.devices.map((device) => device.id === targetDeviceId ? { ...device, status: "offline" as const, } : device, ), }); const response = await confirmDispatchPlanRoute( await createAuthedRequest( `http://127.0.0.1:3000/api/v1/projects/${groupProject.id}/dispatch-plans/${dispatchPlan.planId}/confirm`, "POST", { approvedTargetProjectIds: [approvedTargetProjectId] }, ), { params: Promise.resolve({ projectId: groupProject.id, planId: dispatchPlan.planId }) }, ); assert.equal(response.status, 400); const payload = (await response.json()) as { ok: boolean; code: string; message: string }; assert.equal(payload.ok, false); assert.equal(payload.code, "DISPATCH_TARGET_DEVICE_OFFLINE"); assert.equal(payload.message, "目标线程所在设备当前不在线,请先让设备上线后再确认下发。"); const nextState = await readState(); const createdExecution = nextState.dispatchExecutions.find((item) => item.planId === dispatchPlan.planId); assert.equal(createdExecution, undefined); }); test("confirming a dispatch plan marks approval_required groups as approved", async () => { const { groupProject, dispatchPlan } = await createDispatchPlanForTest(); const approvedTargetProjectId = dispatchPlan.targets[0]?.projectId; assert.ok(approvedTargetProjectId, "expected a recommended target project"); const state = await readState(); await writeState({ ...state, projects: state.projects.map((project) => project.id === groupProject.id ? { ...project, collaborationMode: "approval_required" as const, approvalState: "pending_user" as const, } : project, ), }); const response = await confirmDispatchPlanRoute( await createAuthedRequest( `http://127.0.0.1:3000/api/v1/projects/${groupProject.id}/dispatch-plans/${dispatchPlan.planId}/confirm`, "POST", { approvedTargetProjectIds: [approvedTargetProjectId] }, ), { params: Promise.resolve({ projectId: groupProject.id, planId: dispatchPlan.planId }) }, ); assert.equal(response.status, 200); const nextState = await readState(); const nextGroupProject = nextState.projects.find((project) => project.id === groupProject.id); assert.ok(nextGroupProject, "expected group project to remain present"); assert.equal(nextGroupProject?.approvalState, "approved"); }); test("rejecting a dispatch plan marks approval_required groups as rejected and writes a system notice", async () => { const { groupProject, dispatchPlan } = await createDispatchPlanForTest(); const state = await readState(); await writeState({ ...state, projects: state.projects.map((project) => project.id === groupProject.id ? { ...project, collaborationMode: "approval_required" as const, approvalState: "pending_user" as const, } : project, ), }); const response = await rejectDispatchPlanRoute( await createAuthedRequest( `http://127.0.0.1:3000/api/v1/projects/${groupProject.id}/dispatch-plans/${dispatchPlan.planId}/reject`, "POST", {}, ), { params: Promise.resolve({ projectId: groupProject.id, planId: dispatchPlan.planId }) }, ); assert.equal(response.status, 200); const payload = (await response.json()) as { ok: boolean; plan: { planId: string; status: string }; notice: { kind: string; body: string }; collaborationGate: { isGroup: boolean; collaborationMode: string; requiresMasterAgentApproval: boolean; approvalState: string; }; }; assert.equal(payload.ok, true); assert.equal(payload.plan.planId, dispatchPlan.planId); assert.equal(payload.plan.status, "rejected"); assert.equal(payload.notice.kind, "system_notice"); assert.equal(payload.notice.body, "已拒绝主 Agent 推荐,本次不会下发到任何线程。"); assert.equal(payload.collaborationGate.isGroup, true); assert.equal(payload.collaborationGate.collaborationMode, "approval_required"); assert.equal(payload.collaborationGate.requiresMasterAgentApproval, true); assert.equal(payload.collaborationGate.approvalState, "rejected"); const nextState = await readState(); const nextGroupProject = nextState.projects.find((project) => project.id === groupProject.id); assert.ok(nextGroupProject, "expected group project to remain present"); assert.equal(nextGroupProject?.approvalState, "rejected"); const notice = nextGroupProject?.messages.find( (message) => message.kind === "system_notice" && message.body.includes("已拒绝主 Agent 推荐"), ); assert.ok(notice, "expected rejection notice in group chat"); }); test("retrying a rejected dispatch plan creates a fresh pending recommendation and resets approval gate", async () => { const { groupProject, dispatchPlan } = await createDispatchPlanForTest(); const state = await readState(); await writeState({ ...state, projects: state.projects.map((project) => project.id === groupProject.id ? { ...project, collaborationMode: "approval_required" as const, approvalState: "pending_user" as const, } : project, ), }); const rejectResponse = await rejectDispatchPlanRoute( await createAuthedRequest( `http://127.0.0.1:3000/api/v1/projects/${groupProject.id}/dispatch-plans/${dispatchPlan.planId}/reject`, "POST", {}, ), { params: Promise.resolve({ projectId: groupProject.id, planId: dispatchPlan.planId }) }, ); assert.equal(rejectResponse.status, 200); const retryResponse = await retryDispatchPlanRoute( await createAuthedRequest( `http://127.0.0.1:3000/api/v1/projects/${groupProject.id}/dispatch-plans/${dispatchPlan.planId}/retry`, "POST", {}, ), { params: Promise.resolve({ projectId: groupProject.id, planId: dispatchPlan.planId }) }, ); assert.equal(retryResponse.status, 200); const retryPayload = (await retryResponse.json()) as { ok: boolean; dispatchPlan: { planId: string; status: string; requestMessageId: string } | null; collaborationGate: { approvalState: string; requiresMasterAgentApproval: boolean; collaborationMode: string; }; }; assert.equal(retryPayload.ok, true); assert.ok(retryPayload.dispatchPlan, "expected a fresh dispatch recommendation"); assert.notEqual(retryPayload.dispatchPlan?.planId, dispatchPlan.planId); assert.equal(retryPayload.dispatchPlan?.status, "pending_user_confirmation"); assert.match(retryPayload.dispatchPlan?.requestMessageId ?? "", /:retry:/); assert.equal(retryPayload.collaborationGate.collaborationMode, "approval_required"); assert.equal(retryPayload.collaborationGate.requiresMasterAgentApproval, true); assert.equal(retryPayload.collaborationGate.approvalState, "pending_user"); const nextState = await readState(); const refreshedPlan = nextState.dispatchPlans.find((plan) => plan.planId === retryPayload.dispatchPlan?.planId); assert.ok(refreshedPlan, "expected retried dispatch plan in state"); const nextGroupProject = nextState.projects.find((project) => project.id === groupProject.id); assert.equal(nextGroupProject?.approvalState, "pending_user"); }); test("PATCH /api/v1/projects/[projectId]/dispatch-reminder updates the per-group light reminder preference", async () => { const { groupProject } = await createDispatchPlanForTest(); const enableResponse = await updateDispatchReminderRoute( await createAuthedRequest( `http://127.0.0.1:3000/api/v1/projects/${groupProject.id}/dispatch-reminder`, "PATCH", { lightDispatchReminderEnabled: true }, ), { params: Promise.resolve({ projectId: groupProject.id }) }, ); assert.equal(enableResponse.status, 200); const enablePayload = (await enableResponse.json()) as { ok: boolean; project: { id: string; lightDispatchReminderEnabled?: boolean; }; }; assert.equal(enablePayload.ok, true); assert.equal(enablePayload.project.id, groupProject.id); assert.equal(enablePayload.project.lightDispatchReminderEnabled, true); const disableResponse = await updateDispatchReminderRoute( await createAuthedRequest( `http://127.0.0.1:3000/api/v1/projects/${groupProject.id}/dispatch-reminder`, "PATCH", { lightDispatchReminderEnabled: false }, ), { params: Promise.resolve({ projectId: groupProject.id }) }, ); assert.equal(disableResponse.status, 200); const disablePayload = (await disableResponse.json()) as { ok: boolean; project: { id: string; lightDispatchReminderEnabled?: boolean; }; collaborationGate: { lightDispatchReminderEnabled?: boolean; }; }; assert.equal(disablePayload.ok, true); assert.equal(disablePayload.project.id, groupProject.id); assert.equal(disablePayload.project.lightDispatchReminderEnabled, false); assert.equal(disablePayload.collaborationGate.lightDispatchReminderEnabled, false); const nextState = await readState(); const nextGroupProject = nextState.projects.find((project) => project.id === groupProject.id); assert.ok(nextGroupProject, "expected group project to remain present"); assert.equal(nextGroupProject?.lightDispatchReminderEnabled, false); });