feat: let master-agent dispatch real threads

This commit is contained in:
kris
2026-04-03 05:29:38 +08:00
parent ad7dd94d95
commit 354c8b1f0b
12 changed files with 495 additions and 21 deletions

View File

@@ -166,6 +166,34 @@ async function createDispatchPlanForTest() {
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();
@@ -271,6 +299,74 @@ test("POST /api/v1/projects/[projectId]/dispatch-plans/[planId]/confirm confirms
assert.equal(executionTask?.orchestrationBackendLabel, "Boss Native Orchestrator");
});
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;