mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-25 16:42:16 +03:00
Landed with the design call resolved per the owner's pick — **option 1**: the synced store is now endpoint-agnostic (persistDiscoveredModels and managedModelImport no longer drop non-chat models at write time), and chat selectability moved to read time (auto-pool expansion in autoStrategy applies filterChatSelectableModels; the models-route projection already had its chatOnly filter). Your discovery test now passes end-to-end (3/3): /api/show capabilities persist per connection and image/embedding requests route through the advertising host. Reconciliation notes: conflicted areas merged onto the current tip (adobe discovery import, requestedModel preflight signature, resolvedProvider fast-path coexists with the synced-route override — explicit resolution wins); carried base-red drains (#10055 memoization, #11071 test variants) dropped as already-landed; the managed-model-import exclusion test was propagated to the new contract (image/video models persist; the read filter still hides them from chat pickers — pinned by a new assertion). Full battery: 205/206 focused (the one red is a confirmed periodic-timer timing flake on the loaded devbox — 20/20 isolated), autoCombo vitest 30/30, combo suites 46/46, gates + typecheck clean. Thank you @yourspraveen — the capability probe + routing design was right; it just needed the store contract opened up. Fixes #11087.
94 lines
3.5 KiB
JavaScript
94 lines
3.5 KiB
JavaScript
#!/usr/bin/env node
|
|
// Gera o export estável do catálogo OmniRoute consumido pelo OmniRoute Radar
|
|
// (`RADAR_EXPORT_URL` → `${DATA_DIR}/export-omniroute.json` no servidor privado).
|
|
//
|
|
// Por que existe: o servidor Radar (1 GB RAM na Akamai) NUNCA clona nem instala
|
|
// o OmniRoute; ele só baixa este JSON de uma URL estável. Antes o export vinha
|
|
// do snapshot gravado no deploy, preso à máquina do operador. Este script roda
|
|
// no CI do OmniRoute (que tem os módulos de catálogo + tsx), emite o export com
|
|
// PROVENIÊNCIA e o workflow o publica como asset de release de URL fixa.
|
|
//
|
|
// Contrato do consumidor (`src/feed/exportSource.ts` no radar-server): exige
|
|
// `budgets[]` não-vazio e lê `geradoEm`; chaves extras são ignoradas, então
|
|
// `totais`, `registry` e `provenance` viajam junto sem quebrar retrocompat.
|
|
//
|
|
// Uso (precisa de tsx, pois lê .ts):
|
|
// node --import tsx/esm scripts/release/radar-export.mjs [saída.json]
|
|
|
|
import { execFileSync } from "node:child_process";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
const REPO = path.resolve(DIR, "../.."); // …/OmniRoute
|
|
const SAIDA = process.argv[2] || path.join(REPO, "export-omniroute.json");
|
|
|
|
const { FREE_MODEL_BUDGETS } = await import(
|
|
path.join(REPO, "open-sse/config/freeModelCatalog.data.ts")
|
|
);
|
|
const { computeFreeModelTotals } = await import(
|
|
path.join(REPO, "open-sse/config/freeModelCatalog.ts")
|
|
);
|
|
const { REGISTRY } = await import(path.join(REPO, "open-sse/config/providerRegistry.ts"));
|
|
|
|
/**
|
|
* Proveniência: quem/quando/de-qual-commit gerou o export. Cada campo é `null`
|
|
* quando a origem é desconhecida — NUNCA inventamos um valor (D16: desconhecido
|
|
* permanece `null`). No CI o GitHub popula as variáveis; localmente caímos no
|
|
* `git` e, sem repositório, em `null`.
|
|
*/
|
|
function firstEnv(...names) {
|
|
for (const name of names) {
|
|
const value = process.env[name]?.trim();
|
|
if (value) return value;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function gitHead() {
|
|
try {
|
|
return execFileSync("git", ["-C", REPO, "rev-parse", "HEAD"], {
|
|
encoding: "utf8",
|
|
stdio: ["ignore", "pipe", "ignore"],
|
|
}).trim() || null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function buildProvenance(geradoEm) {
|
|
const sourceCommit = firstEnv("GITHUB_SHA") ?? gitHead();
|
|
const sourceRef = firstEnv("GITHUB_REF_NAME", "GITHUB_REF");
|
|
const server = firstEnv("GITHUB_SERVER_URL");
|
|
const repository = firstEnv("GITHUB_REPOSITORY");
|
|
const runId = firstEnv("GITHUB_RUN_ID");
|
|
const runUrl = server && repository && runId ? `${server}/${repository}/actions/runs/${runId}` : null;
|
|
return {
|
|
generatedAt: geradoEm,
|
|
generator: "scripts/release/radar-export.mjs",
|
|
generatedBy: firstEnv("GITHUB_ACTIONS") ? "github-actions" : "manual",
|
|
sourceCommit,
|
|
sourceRef,
|
|
runUrl,
|
|
};
|
|
}
|
|
|
|
const geradoEm = new Date().toISOString();
|
|
const dados = {
|
|
geradoEm,
|
|
budgets: FREE_MODEL_BUDGETS,
|
|
totais: computeFreeModelTotals(),
|
|
// Só as chaves: o consumidor apenas pergunta "sabemos rotear este provider?".
|
|
registry: Object.keys(REGISTRY).sort(),
|
|
provenance: buildProvenance(geradoEm),
|
|
};
|
|
|
|
fs.mkdirSync(path.dirname(path.resolve(SAIDA)), { recursive: true });
|
|
fs.writeFileSync(SAIDA, JSON.stringify(dados));
|
|
console.log(
|
|
`catálogo exportado → ${path.basename(SAIDA)}: ` +
|
|
`${dados.budgets.length} modelos, ${dados.registry.length} providers no registry` +
|
|
` (commit ${dados.provenance.sourceCommit ?? "desconhecido"})`
|
|
);
|