Files
OmniRoute/tests/unit/conductor-hub-proxy.test.ts
Diego Rodrigues de Sa e Souza 3db785dc41 feat(dashboard): Conductor panel — fleet, tasks and cancel over server-side proxy (PRD RF3) (#8221)
* feat(a2a): conductor bridge core — event mapping with canceled->cancelled

* feat(a2a): incremental SSE parser for conductor bridge

* feat(a2a): conductor bridge connection loop with persisted cursor and backoff

* feat(a2a): start conductor bridge at boot behind CONDUCTOR_HUB_URL

* fix(a2a): conductor bridge parses the hub's real SSE wire format (id/type in frame, data={ts,payload})

* docs(reference): document CONDUCTOR_HUB_URL/TOKEN in ENVIRONMENT.md (env-doc-sync gate)

* feat(a2a): fleet skills derived from the Conductor hub for the agent card

* feat(a2a): agent card announces Conductor fleet skills

* feat(dashboard): server-side hub proxy for the Conductor panel (whitelisted shapes, fail-open)

* feat(dashboard): /api/conductor proxy routes (fleet, task detail, cancel) behind management auth

* feat(dashboard): Conductor panel — fleet live view, task detail and cancel over /api/conductor proxy

---------

Co-authored-by: backryun <bakryun0718@proton.me>
2026-08-12 01:53:14 -03:00

141 lines
4.8 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import {
getFleetSnapshot,
getConductorTaskDetail,
cancelConductorTask,
} from "../../src/lib/conductor/hubProxy.ts";
const RUNNERS = [
{
id: "r_1",
token: "NUNCA-VAZAR",
online: true,
draining: false,
capabilities: { name: "devbox", clis: [{ profile: "claude" }, { profile: "codex" }], skills: [] },
},
];
const TASKS = [
{
id: "t_1",
status: "completed",
mode: "solo",
from: "orchestrator",
repo: { url: "https://git.x/repo", base_ref: "main" },
spec: { prompt: "faz algo" },
assigned_runner: "r_1",
manifest: { summary: "feito", branch: "task/t_1", error: null },
council: null,
created_at: "2026-07-22T00:00:00Z",
updated_at: "2026-07-22T00:01:00Z",
},
{
id: "t_2",
status: "working",
mode: "council-3",
from: "orchestrator",
repo: { url: "https://git.x/repo", base_ref: "main" },
spec: { prompt: "outra" },
assigned_runner: null,
manifest: null,
council: { candidate_task_ids: ["t_2a", "t_2b"] },
created_at: "2026-07-22T00:02:00Z",
updated_at: "2026-07-22T00:02:30Z",
},
];
function fakeHub(routes: Record<string, { status: number; body: unknown }>) {
const calls: { url: string; method: string; auth: string | null }[] = [];
const impl = (async (url: string | URL | Request, init?: RequestInit) => {
const u = String(url);
calls.push({
url: u,
method: init?.method ?? "GET",
auth: (init?.headers as Record<string, string> | undefined)?.authorization ?? null,
});
const hit = Object.entries(routes).find(([path]) => u.includes(path));
if (!hit) return new Response("{}", { status: 404 });
return new Response(JSON.stringify(hit[1].body), { status: hit[1].status });
}) as typeof fetch;
return { impl, calls };
}
test.beforeEach(() => {
process.env.CONDUCTOR_HUB_URL = "http://hub.test:7910";
process.env.CONDUCTOR_HUB_TOKEN = "tok-secreto";
});
test.after(() => {
delete process.env.CONDUCTOR_HUB_URL;
delete process.env.CONDUCTOR_HUB_TOKEN;
});
test("snapshot: runners e tasks sanitizados (whitelist — token do runner NUNCA passa)", async () => {
const { impl, calls } = fakeHub({
"/v1/runners": { status: 200, body: RUNNERS },
"/v1/tasks": { status: 200, body: TASKS },
});
const snap = await getFleetSnapshot({ fetchImpl: impl });
assert.equal(snap.offline, false);
assert.deepEqual(snap.runners, [
{ id: "r_1", name: "devbox", clis: ["claude", "codex"], online: true, draining: false },
]);
assert.equal(snap.tasks.length, 2);
assert.deepEqual(snap.tasks[0], {
id: "t_1",
status: "completed",
mode: "solo",
repo: "https://git.x/repo",
runner: "r_1",
summary: "feito",
branch: "task/t_1",
error: null,
updated_at: "2026-07-22T00:01:00Z",
});
assert.ok(!JSON.stringify(snap).includes("NUNCA-VAZAR"), "token de runner não vaza");
assert.ok(!JSON.stringify(snap).includes("tok-secreto"), "token do hub não vaza");
assert.equal(calls.every((c) => c.auth === "Bearer tok-secreto"), true, "proxy autentica no hub");
});
test("snapshot: hub fora do ar → degradado {offline:true} sem lançar", async () => {
const failing = (async () => {
throw new Error("ECONNREFUSED");
}) as unknown as typeof fetch;
const snap = await getFleetSnapshot({ fetchImpl: failing });
assert.deepEqual(snap, { offline: true, runners: [], tasks: [] });
});
test("snapshot: env ausente → degradado sem fetch", async () => {
delete process.env.CONDUCTOR_HUB_URL;
const { impl, calls } = fakeHub({});
const snap = await getFleetSnapshot({ fetchImpl: impl });
assert.equal(snap.offline, true);
assert.equal(calls.length, 0);
});
test("detalhe: manifest e council passam; spec.prompt vem; campos fora da whitelist não", async () => {
const { impl } = fakeHub({ "/v1/tasks/t_2": { status: 200, body: TASKS[1] } });
const detail = await getConductorTaskDetail("t_2", { fetchImpl: impl });
assert.ok(detail);
assert.equal(detail!.id, "t_2");
assert.equal(detail!.prompt, "outra");
assert.deepEqual(detail!.council, { candidate_task_ids: ["t_2a", "t_2b"] });
assert.equal(detail!.base_ref, "main");
});
test("detalhe: 404 do hub → null", async () => {
const { impl } = fakeHub({});
assert.equal(await getConductorTaskDetail("t_x", { fetchImpl: impl }), null);
});
test("cancelar: POST no hub e repassa o status", async () => {
const { impl, calls } = fakeHub({ "/v1/tasks/t_1/cancel": { status: 200, body: { ok: true } } });
const r = await cancelConductorTask("t_1", { fetchImpl: impl });
assert.deepEqual(r, { ok: true, status: 200 });
assert.equal(calls[0].method, "POST");
const miss = await cancelConductorTask("t_zzz", { fetchImpl: fakeHub({}).impl });
assert.deepEqual(miss, { ok: false, status: 404 });
});