mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-01 21:02:12 +03:00
* feat(homolog): scaffolding da suíte de homologação E2E (deps + npm run homolog) * feat(homolog): L0 avaliador de paridade de deploy (TDD) * feat(homolog): L1a ciclo de vida de API key efêmera (login admin -> create -> revoke) * feat(homolog): L1b suite httpYac de API (models, chat, auth de management, health) * feat(homolog): L1c checker SSE de streaming real (TDD no parser) * feat(homolog): L2 smoke de providers reais via promptfoo gerado do catálogo * feat(homolog): L4a Playwright homolog config + login storageState * feat(homolog): L4b smoke de todas as rotas do dashboard (descoberta via fs) * feat(homolog): L4c fluxo criar/revogar API key pela UI * fix(homolog): resiliencia real-environment — stream:false no smoke promptfoo, retry de socket keep-alive, key efemera com sufixo unico * feat(homolog): L5 orquestrador npm run homolog + relatorio CTRF unificado * docs(homolog): guia de operacao da suite + fragment de changelog + allowlist env-doc-sync * fix(homolog): paraleliza o sweep de rotas do dashboard (fullyParallel + 8 workers) * fix(homolog): isola outputs crus em homolog-report/raw para nao quebrar o ctrf merge * fix(homolog): outputDir absoluto do reporter CTRF da UI (path relativo escapava do worktree) * chore(quality): allowlist the 5 homolog-suite devDependencies (ctrf-io trio, httpyac, promptfoo) after registry verification * chore(quality): register the homolog Playwright suite as a test-discovery collector (run.mjs -> tests/homolog/ui)
53 lines
2.0 KiB
JavaScript
53 lines
2.0 KiB
JavaScript
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { pickSmokeModels } from "./lib/providerTiers.mjs";
|
|
|
|
const baseUrl = process.env.HOMOLOG_BASE_URL;
|
|
const critical = (process.env.HOMOLOG_CRITICAL_PROVIDERS || "").split(",").filter(Boolean);
|
|
|
|
const res = await fetch(`${baseUrl}/v1/models`, {
|
|
headers: { Authorization: `Bearer ${process.env.HOMOLOG_API_KEY}` },
|
|
});
|
|
if (!res.ok) throw new Error(`/v1/models HTTP ${res.status}`);
|
|
const catalog = (await res.json()).data;
|
|
|
|
const picks = pickSmokeModels(catalog, critical);
|
|
const missing = picks.filter((p) => !p.model);
|
|
const providers = picks
|
|
.filter((p) => p.model)
|
|
.map((p) => ({
|
|
id: `openai:chat:${p.model}`,
|
|
label: p.provider,
|
|
config: {
|
|
apiBaseUrl: `${baseUrl}/v1`,
|
|
apiKeyEnvar: "HOMOLOG_API_KEY",
|
|
max_tokens: 5,
|
|
temperature: 0,
|
|
// OmniRoute streama por default quando "stream" é omitido (streamDefaultMode
|
|
// legacy) — o parser JSON do promptfoo precisa da resposta non-stream.
|
|
passthrough: { stream: false, max_tokens: 5 },
|
|
},
|
|
}));
|
|
|
|
const config = {
|
|
description: "OmniRoute homolog — smoke real 1 request/provider crítico",
|
|
prompts: ["Reply with exactly: OK"],
|
|
providers,
|
|
// O smoke valida o WIRING do provider (respondeu sem erro), não o comportamento
|
|
// do modelo: com max_tokens=5, modelos de reasoning podem gastar o budget antes
|
|
// de emitir o "OK" literal — icontains seria falso-positivo de quebra.
|
|
tests: [{ assert: [{ type: "javascript", value: "typeof output === 'string'" }] }],
|
|
};
|
|
fs.mkdirSync("homolog-report/raw", { recursive: true });
|
|
fs.writeFileSync(
|
|
path.join("homolog-report", "promptfooconfig.yaml"),
|
|
JSON.stringify(config, null, 2) // promptfoo aceita JSON como config YAML-compatível
|
|
);
|
|
fs.writeFileSync(
|
|
path.join("homolog-report", "raw", "provider-misses.json"),
|
|
JSON.stringify(missing, null, 2)
|
|
);
|
|
console.log(
|
|
`[gen-promptfoo] ${providers.length} providers no smoke, ${missing.length} misses de catálogo`
|
|
);
|