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 data: typeof import("../src/lib/boss-data"); let completeTaskRoute: typeof import("../src/app/api/v1/master-agent/tasks/[taskId]/complete/route"); let decisionRoute: typeof import("../src/app/api/v1/dialog-guard/interventions/[interventionId]/decision/route"); let events: typeof import("../src/lib/boss-events"); let authCookie = ""; let baseState: Awaited>; async function setup() { if (runtimeRoot) return; runtimeRoot = await mkdtemp(path.join(os.tmpdir(), "boss-dialog-guard-backend-")); process.env.BOSS_RUNTIME_ROOT = runtimeRoot; process.env.BOSS_STATE_FILE = path.join(runtimeRoot, "boss-state.json"); const [dataModule, completeRouteModule, decisionRouteModule, eventsModule, authModule] = await Promise.all([ import("../src/lib/boss-data.ts"), import("../src/app/api/v1/master-agent/tasks/[taskId]/complete/route.ts"), import("../src/app/api/v1/dialog-guard/interventions/[interventionId]/decision/route.ts"), import("../src/lib/boss-events.ts"), import("../src/lib/boss-auth.ts"), ]); data = dataModule; completeTaskRoute = completeRouteModule; decisionRoute = decisionRouteModule; events = eventsModule; authCookie = authModule.AUTH_SESSION_COOKIE; baseState = structuredClone(await data.readState()); } test.after(async () => { if (runtimeRoot) { await rm(runtimeRoot, { recursive: true, force: true }); } }); test.beforeEach(async () => { await setup(); const state = structuredClone(baseState); state.masterAgentTasks = []; state.permissionAuditLogs = []; state.dialogGuardInterventions = []; await data.writeState(state); }); function deviceRequest(taskId: string, body: Record) { return new NextRequest( `http://127.0.0.1:3000/api/v1/master-agent/tasks/${taskId}/complete`, { method: "POST", headers: { "content-type": "application/json", "x-boss-device-token": "boss-mac-studio-token", }, body: JSON.stringify(body), }, ); } async function authedDecisionRequest(interventionId: string, body: Record) { const session = await data.createAuthSession({ account: "krisolo", role: "highest_admin", displayName: "Boss 超级管理员", loginMethod: "password", }); return new NextRequest( `http://127.0.0.1:3000/api/v1/dialog-guard/interventions/${interventionId}/decision`, { method: "POST", headers: { "content-type": "application/json", cookie: `${authCookie}=${session.sessionToken}`, }, body: JSON.stringify(body), }, ); } async function queueDesktopTask() { const [requestMessage] = await data.appendProjectMessages({ projectId: "master-agent", messages: [ { senderLabel: "Boss 超级管理员", body: "打开微信发送一句测试消息", kind: "text", }, ], }); return data.queueMasterAgentTask({ projectId: "master-agent", taskType: "desktop_control", requestMessageId: requestMessage.id, requestText: "打开微信发送一句测试消息", executionPrompt: "打开微信发送一句测试消息", requestedBy: "Boss 超级管理员", requestedByAccount: "krisolo", deviceId: "mac-studio", accountId: "openai-master", accountLabel: "gpt-5.4-mini", intentCategory: "desktop_control", runtimeKind: "computer-use-runtime", riskLevel: "medium", confirmationPolicy: "light_confirm", }); } test("needs_user_action task complete creates pending dialog intervention audit log and realtime event", async () => { await setup(); const task = await queueDesktopTask(); const seenEvents: Array<{ event: string; payload: { interventionId?: string; projectId?: string; appName?: string; taskId?: string; status?: string; }; }> = []; const unsubscribe = events.subscribeBossEvents((event, payload) => { seenEvents.push({ event, payload }); }); try { const response = await completeTaskRoute.POST( deviceRequest(task.taskId, { deviceId: "mac-studio", status: "needs_user_action", kind: "dialog_intervention_required", requestId: "runtime-request-001", dialogId: "dialog-wechat-send-confirm", appName: "微信", platform: "darwin", risk: "high", summary: "微信即将发送外部可见消息,需要用户确认。", recommendedAction: "allow_once", availableActions: ["allow_once", "deny", "cancel_task"], }), { params: Promise.resolve({ taskId: task.taskId }) }, ); assert.equal(response.status, 200); const payload = await response.json(); assert.equal(payload.ok, true); assert.equal(payload.task.status, "needs_user_action"); const state = await data.readState(); const intervention = state.dialogGuardInterventions.at(0); assert.ok(intervention, "expected dialog intervention to be persisted"); assert.equal(intervention.taskId, task.taskId); assert.equal(intervention.dialogId, "dialog-wechat-send-confirm"); assert.equal(intervention.requestId, "runtime-request-001"); assert.equal(intervention.deviceId, "mac-studio"); assert.equal(intervention.projectId, "master-agent"); assert.equal(intervention.appName, "微信"); assert.equal(intervention.platform, "darwin"); assert.equal(intervention.risk, "high"); assert.equal(intervention.status, "pending"); assert.deepEqual(intervention.availableActions, ["allow_once", "deny", "cancel_task"]); assert.equal( state.permissionAuditLogs.some( (log) => log.action === "dialog_guard.intervention_required" && log.deviceId === "mac-studio" && log.projectId === "master-agent" && log.requestId === "runtime-request-001", ), true, ); assert.equal( seenEvents.some( (item) => item.event === "desktop.dialog_guard.intervention_required" && item.payload.interventionId === intervention.interventionId && item.payload.projectId === "master-agent" && item.payload.appName === "微信" && item.payload.taskId === task.taskId && item.payload.status === "pending", ), true, ); } finally { unsubscribe(); } }); test("decision route resolves pending intervention writes audit log and emits resolved event", async () => { await setup(); const task = await queueDesktopTask(); await completeTaskRoute.POST( deviceRequest(task.taskId, { deviceId: "mac-studio", status: "needs_user_action", kind: "dialog_intervention_required", requestId: "runtime-request-002", dialogId: "dialog-open-file", appName: "Finder", platform: "darwin", risk: "medium", summary: "Finder 要打开一个本地文件。", recommendedAction: "allow_once", availableActions: ["allow_once", "deny", "handled_on_device"], }), { params: Promise.resolve({ taskId: task.taskId }) }, ); const pending = (await data.readState()).dialogGuardInterventions.at(0); assert.ok(pending, "expected setup to create a pending intervention"); const seenEvents: Array<{ event: string; payload: { interventionId?: string; projectId?: string; decision?: string; status?: string; }; }> = []; const unsubscribe = events.subscribeBossEvents((event, payload) => { seenEvents.push({ event, payload }); }); try { const response = await decisionRoute.POST( await authedDecisionRequest(pending.interventionId, { decision: "allow_once", note: "本次允许。", }), { params: Promise.resolve({ interventionId: pending.interventionId }) }, ); assert.equal(response.status, 200); const payload = await response.json(); assert.equal(payload.ok, true); assert.equal(payload.intervention.status, "resolved"); assert.equal(payload.intervention.decision, "allow_once"); const state = await data.readState(); const resolved = state.dialogGuardInterventions.find( (item) => item.interventionId === pending.interventionId, ); assert.equal(resolved?.status, "resolved"); assert.equal(resolved?.decision, "allow_once"); assert.ok(resolved?.resolvedAt); assert.equal( state.permissionAuditLogs.some( (log) => log.action === "dialog_guard.intervention_resolved" && log.actorAccount === "krisolo" && log.deviceId === "mac-studio" && log.projectId === "master-agent" && log.requestId === "runtime-request-002", ), true, ); assert.equal( seenEvents.some( (item) => item.event === "desktop.dialog_guard.intervention_resolved" && item.payload.interventionId === pending.interventionId && item.payload.projectId === "master-agent" && item.payload.decision === "allow_once" && item.payload.status === "resolved", ), true, ); } finally { unsubscribe(); } });