mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-11 01:32:22 +03:00
fix(db,combo): clear the NEW base-reds the 08-06 merge batch introduced
The tip moved while the first sweep PR (#9600) was in review, and three fresh
base-reds landed with it — same classes as before, all reproduced on the pure
tip 9995bc4893:
1. ANOTHER migration collision: #9061 shipped 134_ccr_blocks.sql onto the slot
134_proxy_logs_egress_ip.sql (#9291) has held since 08-04. getMigrationFiles()
throws on collision, so every DB-touching test died at bootstrap again.
Renumbered to 139 (next free slot). No retroactive guard needed this time:
both statements are IF NOT EXISTS, and no DB can have applied it as 134 —
the runner refused to run at all while the collision existed.
2. BROKEN IMPORT killing the combo module graph: #8894 imported
preferAntigravityConnectionsWithStoredProject from
../antigravityProjectPersistence.ts — a module that exists NOWHERE in the
repo (it came from an unmerged sibling branch). Anything importing
quotaStrategies.ts died with ERR_MODULE_NOT_FOUND. Implemented the helper in
the real persistence module (antigravityProjectPersist.ts, #8491) with the
semantics the call site needs — prefer connections that already carry a
stored projectId, never emptying the pool — and pointed the import there.
New regression suite tests/unit/antigravity-prefer-stored-project.test.ts
(5/5), including an import-graph probe that reproduces the break shape.
3. Sibling-test drift from #9106 (gemini-3.1-pro-high now user-callable): its
own suites were updated but provider-models-route.test.ts was not. Expected
discovery list realigned; testFrozen 1784->1787 justified in the baseline
(irreducible +2 after comment compression; gate counts split-newlines).
Also regenerated tests/snapshots/provider/translate-path.json — addition-only:
devin-cli-agentic, raycast, regolo (today's provider merges), zero removals.
image-generation-route 20/20 (was import-dead), provider-models-route 59/59,
antigravity-prefer-stored-project 5/5, provider-translate-path-golden 3/3.
Refs #9298
This commit is contained in:
@@ -371,7 +371,7 @@
|
||||
"tests/unit/model-sync-route.test.ts": 1016,
|
||||
"tests/unit/models-catalog-route.test.ts": 1636,
|
||||
"tests/unit/perplexity-web.test.ts": 1355,
|
||||
"tests/unit/provider-models-route.test.ts": 1784,
|
||||
"tests/unit/provider-models-route.test.ts": 1787,
|
||||
"tests/unit/provider-validation-specialty.test.ts": 2985,
|
||||
"tests/unit/providers-page-utils.test.ts": 1106,
|
||||
"tests/unit/response-sanitizer.test.ts": 1063,
|
||||
@@ -607,5 +607,6 @@
|
||||
"_rebaseline_2026_08_05_9323_agentrouter_waf_retry": "PR #9323 (fix(agentrouter): retry on 400 content-blocked + burst guard) own growth: open-sse/executors/base.ts 1578->1623 (check-file-size.mjs conta via split(\"\\n\").length; wc -l ve 1622). As +45 linhas sao o WAF_RETRY_CONFIG + o burst guard via gateOutboundRequest() para o WAF do agentrouter.org, com comentarios explicando o porque de cada mitigacao e cobertos por tests/unit/base-executor-waf-retry.test.ts e tests/unit/wafRateLimit.test.ts. Crescimento funcional legitimo, nao inchaco.",
|
||||
"_rebaseline_2026_08_05_9529_own_growth": "PR #9529 own growth (base release/v3.8.50 medida EXATAMENTE nos frozen antigos, entao o modo base-relative #8522 nao cobre): open-sse/services/rateLimitManager.ts 1060->1105 (+45: helper applyLimiterSettings() que re-arma o heartbeat do reservoir apos updateSettings — fix do bug Bottleneck 2.19.5 que congelava a fila weighted; TDD em tests/unit/ratelimit-reservoir-refresh.test.ts); tests/integration/chat-pipeline.test.ts 1592->1598 (+6: User-Agent do codex derivado de getCodexClientVersion() em vez de literal pinado — teste-irmao alinhado ao contrato); tests/unit/provider-validation-specialty.test.ts 2980->2985 (+5: cobertura NOVA claude-web 429 -> valid:false, alinhamento #9406); open-sse/translator/response/openai-responses.ts 1174->1204 (+30: buildResponsesReasoningSummaryDelta MOVIDA do leaf pureHelpers.ts para o host — a funcao do #9500 muta stream state e violava o contrato do leaf puro; o LOC total do par host+leaf nao cresceu, o pureHelpers encolheu o mesmo tanto). Crescimento por fix de producao + cobertura adicional + realocacao arquitetural, nao inchaco.",
|
||||
"_rebaseline_2026_08_06_v3850_inherited_drift_reconcile": "Reconciliacao 2026-08-06 do drift ACUMULADO da release/v3.8.50 apos o lote de merges de 08-05/06: 13 arquivos acima do frozen no tip puro 8180b49ce1 (medidos pelo proprio gate). O modo PR base-relative (#8522) deixa PRs inocentes passarem, e os rebaselines individuais dos PRs se perderam nas resolucoes sucessivas de conflito deste hot-file — o drift so aparece no modo absoluto (nightly/local). Crescimentos funcionais dos PRs mergeados: #9024 topology click-nav src/app/(dashboard)/dashboard/HomePageClient.tsx; #9324 OpenRouter enrich src/app/(dashboard)/dashboard/providers/page.tsx; #9329 quota card ordering src/app/(dashboard)/dashboard/usage/components/ProviderLimits/index.tsx; #9193 context-window suffixes src/sse/handlers/chat.ts; #9332 nested Claude server tool ids open-sse/executors/base.ts; #9228 strip orphaned tool outputs open-sse/executors/codex.ts; #9236 nvidia tool-name normalize open-sse/executors/default.ts; #9314 nested tool_call validation open-sse/executors/kiro.ts; #9260 caller identity REST hops open-sse/mcp-server/server.ts; #8934 cache breakpoints tests tests/unit/chatcore-translation-paths.test.ts; #9193 suffix tests tests/unit/combo-routing-engine.test.ts; #9196 reasoning-on-tool-finish tests tests/unit/sse-auth.test.ts; #9163 GPT-5.6 Max reasoning tests tests/unit/translator-openai-to-kiro.test.ts. default.ts e kiro.ts entram no frozen (estavam sem entrada, acima do cap 1000). Atualizacao pos-medicao (a base avancou durante o ciclo do PR): src/sse/handlers/chat.ts 1857->1877 (#9184 affinity EOF evict) e open-sse/executors/default.ts 1027->1042 (#9005 Kimi K3 tool-name backfill).",
|
||||
"_rebaseline_2026_08_06b_v3850_sweepreds_drift": "Segunda reconciliacao de 2026-08-06 (/sweep-reds sobre o tip puro 2ddbbc61a6): 3 arquivos voltaram a passar do frozen apos os merges do mesmo dia, com atribuicao 1:1 por commit. (1) src/app/(dashboard)/dashboard/providers/page.tsx 1928->1944 e (2) open-sse/executors/base.ts 1635->1640, ambos do #9515 (feat(radar): flag-gated signed free-model catalog overlay, commit e7f6b1d130) — o overlay do Radar entra por wiring nos chokepoints ja existentes (a resolucao/verificacao do catalogo assinado mora fora destes dois arquivos); +16 e +5 linhas liquidas nao sao extraiveis sem inventar um leaf por callsite. (3) open-sse/services/accountFallback.ts 1966->1972 do #8704 (commit c4527f97bd), +6 linhas de dados em CREDITS_EXHAUSTED_SIGNALS ('has been exhausted', fixes #8631). src/sse/handlers/chat.ts 1880>1877 tambem estava violando e NAO entra aqui de proposito: e drenado por encolhimento na PR #9598, sem rebaseline. Crescimento proprio DESTA PR: src/lib/db/migrationRunner.ts 1077->1084 (+7) — o guard retroativo em isSchemaAlreadyApplied para os arquivos renumerados 137/138, exigido pela propria mensagem de erro de colisao do runner (ambas as migracoes sao ALTER TABLE ADD COLUMN puro, nao idempotente). Dois `case` + dois `return hasColumn(...)` + 3 linhas de comentario dentro do switch existente; nao extraivel."
|
||||
"_rebaseline_2026_08_06b_v3850_sweepreds_drift": "Segunda reconciliacao de 2026-08-06 (/sweep-reds sobre o tip puro 2ddbbc61a6): 3 arquivos voltaram a passar do frozen apos os merges do mesmo dia, com atribuicao 1:1 por commit. (1) src/app/(dashboard)/dashboard/providers/page.tsx 1928->1944 e (2) open-sse/executors/base.ts 1635->1640, ambos do #9515 (feat(radar): flag-gated signed free-model catalog overlay, commit e7f6b1d130) — o overlay do Radar entra por wiring nos chokepoints ja existentes (a resolucao/verificacao do catalogo assinado mora fora destes dois arquivos); +16 e +5 linhas liquidas nao sao extraiveis sem inventar um leaf por callsite. (3) open-sse/services/accountFallback.ts 1966->1972 do #8704 (commit c4527f97bd), +6 linhas de dados em CREDITS_EXHAUSTED_SIGNALS ('has been exhausted', fixes #8631). src/sse/handlers/chat.ts 1880>1877 tambem estava violando e NAO entra aqui de proposito: e drenado por encolhimento na PR #9598, sem rebaseline. Crescimento proprio DESTA PR: src/lib/db/migrationRunner.ts 1077->1084 (+7) — o guard retroativo em isSchemaAlreadyApplied para os arquivos renumerados 137/138, exigido pela propria mensagem de erro de colisao do runner (ambas as migracoes sao ALTER TABLE ADD COLUMN puro, nao idempotente). Dois `case` + dois `return hasColumn(...)` + 3 linhas de comentario dentro do switch existente; nao extraivel.",
|
||||
"_rebaseline_2026_08_06c_v3850_sweepreds_pr2": "Segunda PR do /sweep-reds (fix/release-v3.8.50-basereds-0806b): tests/unit/provider-models-route.test.ts 1784->1787 (medido pelo gate, que conta split(\"\\n\").length) (+2 apos compressao de comentarios) — alinhamento de contrato forcado por dois merges do dia: #9106 tornou gemini-3.1-pro-high user-callable (a entry do alias entra na lista esperada do teste de discovery-retry, +1 linha de dado + 1 de comentario) e ff012ff420 adicionou onboardUser como bootstrap hop (exclusao no mock, ja comprimida a 1 linha). Nao ha o que encolher sem apagar o comentario que explica o porque."
|
||||
}
|
||||
|
||||
@@ -22,6 +22,43 @@ import { updateProviderConnection } from "@/lib/db/providers";
|
||||
* Best-effort / non-fatal by design: a persistence failure must never block
|
||||
* the in-flight request, which already has the discovered id in hand.
|
||||
*/
|
||||
/**
|
||||
* Selection-side companion of the persistence write path (#8894): given a pool
|
||||
* of Antigravity/AGY connections, prefer the ones that already carry a stored
|
||||
* projectId — they can serve a request without the `loadCodeAssist` discovery
|
||||
* round-trip. "Prefer", not "require": when NO connection has a stored project
|
||||
* the pool is returned unchanged, so a fresh install never empties its
|
||||
* candidate list.
|
||||
*
|
||||
* Sync on purpose (called inside the quota-strategy connection expansion, which
|
||||
* builds candidate lists without awaiting per-connection work). Tolerates
|
||||
* `providerSpecificData` arriving either parsed or as the raw DB JSON string.
|
||||
*/
|
||||
export function preferAntigravityConnectionsWithStoredProject<T extends Record<string, unknown>>(
|
||||
connections: T[]
|
||||
): T[] {
|
||||
if (!Array.isArray(connections) || connections.length === 0) return connections;
|
||||
const hasStoredProject = (connection: T): boolean => {
|
||||
if (typeof connection.projectId === "string" && connection.projectId) return true;
|
||||
let psd = connection.providerSpecificData;
|
||||
if (typeof psd === "string") {
|
||||
try {
|
||||
psd = JSON.parse(psd);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return Boolean(
|
||||
psd &&
|
||||
typeof psd === "object" &&
|
||||
typeof (psd as Record<string, unknown>).projectId === "string" &&
|
||||
(psd as Record<string, unknown>).projectId
|
||||
);
|
||||
};
|
||||
const withStoredProject = connections.filter(hasStoredProject);
|
||||
return withStoredProject.length > 0 ? withStoredProject : connections;
|
||||
}
|
||||
|
||||
export async function persistDiscoveredAntigravityProjectId(
|
||||
connectionId: string | undefined | null,
|
||||
discoveredProjectId: string | undefined | null,
|
||||
|
||||
@@ -45,7 +45,7 @@ import {
|
||||
type QuotaFetchCacheConfig,
|
||||
} from "./quotaScoring.ts";
|
||||
import { rankByHeadroom, type HeadroomSaturation } from "./headroomRanking.ts";
|
||||
import { preferAntigravityConnectionsWithStoredProject } from "../antigravityProjectPersistence.ts";
|
||||
import { preferAntigravityConnectionsWithStoredProject } from "../antigravityProjectPersist.ts";
|
||||
import { isQuotaExhaustedForRequest } from "../../../src/domain/quotaCache.ts";
|
||||
|
||||
const RESET_AWARE_CONNECTION_CACHE_TTL_MS = 30_000;
|
||||
|
||||
@@ -1488,6 +1488,29 @@
|
||||
"stream": "devin://acp/stdio"
|
||||
}
|
||||
},
|
||||
"devin-cli-agentic": {
|
||||
"format": "claude",
|
||||
"headers": {
|
||||
"apiKey": {
|
||||
"Accept": "text/event-stream",
|
||||
"Authorization": "Bearer <TOK>",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"nonStream": {
|
||||
"Authorization": "Bearer <TOK>",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"oauth": {
|
||||
"Accept": "text/event-stream",
|
||||
"Authorization": "Bearer <TOK>",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"nonStream": "devin://acp/stdio",
|
||||
"stream": "devin://acp/stdio"
|
||||
}
|
||||
},
|
||||
"dgrid": {
|
||||
"format": "openai",
|
||||
"headers": {
|
||||
@@ -4274,6 +4297,52 @@
|
||||
"stream": "https://chat.qwen.ai/api/v2/chat/completions"
|
||||
}
|
||||
},
|
||||
"raycast": {
|
||||
"format": "openai",
|
||||
"headers": {
|
||||
"apiKey": {
|
||||
"Accept": "text/event-stream",
|
||||
"Authorization": "Bearer <TOK>",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"nonStream": {
|
||||
"Authorization": "Bearer <TOK>",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"oauth": {
|
||||
"Accept": "text/event-stream",
|
||||
"Authorization": "Bearer <TOK>",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"nonStream": "https://backend.raycast.com/api/v1/ai",
|
||||
"stream": "https://backend.raycast.com/api/v1/ai"
|
||||
}
|
||||
},
|
||||
"regolo": {
|
||||
"format": "openai",
|
||||
"headers": {
|
||||
"apiKey": {
|
||||
"Accept": "text/event-stream",
|
||||
"Authorization": "Bearer <TOK>",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"nonStream": {
|
||||
"Authorization": "Bearer <TOK>",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"oauth": {
|
||||
"Accept": "text/event-stream",
|
||||
"Authorization": "Bearer <TOK>",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"nonStream": "https://api.regolo.ai",
|
||||
"stream": "https://api.regolo.ai"
|
||||
}
|
||||
},
|
||||
"reka": {
|
||||
"format": "openai",
|
||||
"headers": {
|
||||
|
||||
52
tests/unit/antigravity-prefer-stored-project.test.ts
Normal file
52
tests/unit/antigravity-prefer-stored-project.test.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Regression guard for the #8894 import break: quotaStrategies.ts imported
|
||||
* `preferAntigravityConnectionsWithStoredProject` from a module that never
|
||||
* landed (`antigravityProjectPersistence.ts`), killing the whole combo module
|
||||
* graph with ERR_MODULE_NOT_FOUND on the release tip. The helper now lives in
|
||||
* the real persistence module (`antigravityProjectPersist.ts`); these tests pin
|
||||
* its selection semantics.
|
||||
*
|
||||
* Run: node --import tsx/esm --test tests/unit/antigravity-prefer-stored-project.test.ts
|
||||
*/
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import { preferAntigravityConnectionsWithStoredProject } from "../../open-sse/services/antigravityProjectPersist.ts";
|
||||
|
||||
const withProject = { id: "a", projectId: "proj-1" };
|
||||
const withNestedProject = { id: "b", providerSpecificData: { projectId: "proj-2" } };
|
||||
const withStringPsd = { id: "c", providerSpecificData: '{"projectId":"proj-3"}' };
|
||||
const withoutProject = { id: "d", projectId: null, providerSpecificData: {} };
|
||||
const withBrokenPsd = { id: "e", providerSpecificData: "{not json" };
|
||||
|
||||
test("prefers connections that already carry a stored projectId", () => {
|
||||
const pool = [withoutProject, withProject, withNestedProject];
|
||||
assert.deepEqual(
|
||||
preferAntigravityConnectionsWithStoredProject(pool).map((c) => c.id),
|
||||
["a", "b"]
|
||||
);
|
||||
});
|
||||
|
||||
test("reads projectId from a raw JSON-string providerSpecificData", () => {
|
||||
const pool = [withoutProject, withStringPsd];
|
||||
assert.deepEqual(
|
||||
preferAntigravityConnectionsWithStoredProject(pool).map((c) => c.id),
|
||||
["c"]
|
||||
);
|
||||
});
|
||||
|
||||
test("never empties the pool: no stored project anywhere → unchanged", () => {
|
||||
const pool = [withoutProject, withBrokenPsd];
|
||||
assert.deepEqual(preferAntigravityConnectionsWithStoredProject(pool), pool);
|
||||
});
|
||||
|
||||
test("empty input passes through", () => {
|
||||
assert.deepEqual(preferAntigravityConnectionsWithStoredProject([]), []);
|
||||
});
|
||||
|
||||
test("the quota-strategy module graph resolves (the #8894 break shape)", async () => {
|
||||
// Importing quotaStrategies transitively exercises the fixed import path; the
|
||||
// pre-fix tip died here with ERR_MODULE_NOT_FOUND before any test could run.
|
||||
const mod = await import("../../open-sse/services/combo/quotaStrategies.ts");
|
||||
assert.ok(mod, "quotaStrategies must be importable");
|
||||
});
|
||||
@@ -934,14 +934,8 @@ test("provider models route retries Antigravity discovery endpoints before retur
|
||||
// After PR #2219, the discovery flow calls loadCodeAssist first as a project
|
||||
// bootstrap; treat all bootstrap calls as non-fatal failures so the test
|
||||
// exercises the discovery retry path.
|
||||
// `onboardUser` joined loadCodeAssist as a bootstrap hop (ff012ff420: fall back
|
||||
// to onboardUser when loadCodeAssist fails). It must be excluded here too —
|
||||
// otherwise it consumes the single 503 below and discovery never retries,
|
||||
// which is a mock-ordering artifact, not a routing change.
|
||||
if (
|
||||
urlString.includes("/v1internal:loadCodeAssist") ||
|
||||
urlString.includes("/v1internal:onboardUser")
|
||||
) {
|
||||
// onboardUser is a bootstrap hop too (ff012ff420) — else it eats the single 503 below.
|
||||
if (urlString.includes(":loadCodeAssist") || urlString.includes(":onboardUser")) {
|
||||
return new Response("nope", { status: 503 });
|
||||
}
|
||||
seenUrls.push(urlString);
|
||||
@@ -990,6 +984,8 @@ test("provider models route retries Antigravity discovery endpoints before retur
|
||||
"https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels",
|
||||
]);
|
||||
assert.deepEqual(body.models, [
|
||||
// #9106: both alias ids are user-callable now, so the upstream echo survives the filter.
|
||||
{ id: "gemini-3.1-pro-high", name: "Gemini 3.1 Pro (High)" },
|
||||
{ id: "gemini-pro-agent", name: "Gemini 3.1 Pro (High)" },
|
||||
{ id: "gemini-3.6-flash-high", name: "Gemini 3.6 Flash (High)" },
|
||||
{ id: "gemini-3.6-flash-medium", name: "Gemini 3.6 Flash (Medium)" },
|
||||
|
||||
Reference in New Issue
Block a user