Compare commits

..

74 Commits

Author SHA1 Message Date
diegosouzapw
4fee959ad2 fix(video): preserve safe continuation and handoffs 2026-08-27 03:29:50 -03:00
diegosouzapw
d62ecb5d98 test(video): prove safe continuation and handoff gaps 2026-08-27 03:18:39 -03:00
diegosouzapw
ab60b95e31 fix(video): redact executor diagnostics 2026-08-27 03:07:06 -03:00
diegosouzapw
6d209a9128 test(video): cover GLM fallback diagnostic retention 2026-08-27 03:02:28 -03:00
diegosouzapw
62b1835bb5 test(video): prove executor diagnostics redaction gaps 2026-08-27 02:58:06 -03:00
diegosouzapw
23832ba1e9 security(video): bypass response-derived caches 2026-08-27 02:44:46 -03:00
diegosouzapw
11e501f099 Merge remote cache-retention RED commit 2026-08-27 02:38:37 -03:00
diegosouzapw
747ae10e62 test(video): expose response-derived cache retention 2026-08-27 02:36:42 -03:00
diegosouzapw
64b78df100 test(video): expose response-derived cache retention 2026-08-27 02:35:27 -03:00
diegosouzapw
ff70ea7633 security(video): propagate stream retention context 2026-08-27 02:27:14 -03:00
diegosouzapw
6b36696d95 test(video): expose streaming finalization leak 2026-08-27 02:24:25 -03:00
diegosouzapw
d62c0f2688 fix(video): preserve operational model lockouts 2026-08-27 02:20:04 -03:00
diegosouzapw
b945e3c80e test(video): preserve daily quota lockout semantics 2026-08-27 02:17:21 -03:00
diegosouzapw
132ad5f16d security(video): fail closed on malformed transcript cues 2026-08-27 02:13:51 -03:00
diegosouzapw
6475be13c7 test(video): expose malformed serialized cue leak 2026-08-27 02:09:24 -03:00
diegosouzapw
f47f63df83 Merge release/v3.8.51 into security/video-transcript-redaction 2026-08-27 02:05:33 -03:00
Diego Rodrigues de Sa e Souza
2acbfc6fa6 Merge pull request #11751 from diegosouzapw/test/v3851-tiered-rotation-timeout
test(auto-combo): tolerate full-suite rotation load
2026-08-27 02:02:24 -03:00
diegosouzapw
ad3e293f9f test(auto-combo): tolerate full-suite rotation load 2026-08-27 01:41:30 -03:00
diegosouzapw
c467c3232b Merge remote-tracking branch 'origin/release/v3.8.51' into security/video-transcript-redaction 2026-08-27 01:20:11 -03:00
Diego Rodrigues de Sa e Souza
c9f11d86b5 Merge pull request #11733 from diegosouzapw/chore/v3851-prune-stale-eslint-suppressions-2
chore(lint): drain remaining release base-reds
2026-08-27 01:15:48 -03:00
diegosouzapw
21ed68d8ac test: drain inherited quality snapshot reds 2026-08-27 00:43:57 -03:00
diegosouzapw
d35b3f9779 chore(quality): rebaseline measured CLI bundle growth 2026-08-27 00:11:28 -03:00
diegosouzapw
9587e07b69 fix(ui): fall back from invalid AnySearch icon alias 2026-08-27 00:05:47 -03:00
diegosouzapw
12cc6ca834 test(ui): reproduce invalid AnySearch icon alias 2026-08-27 00:01:12 -03:00
diegosouzapw
4f11b2ae3d docs: sync provider catalog count 2026-08-26 23:20:31 -03:00
diegosouzapw
b4e76a7ed9 docs(skills): sync omni-inference search fallback 2026-08-26 23:08:56 -03:00
diegosouzapw
4d519c406a docs(video): define transcript retention trust boundary 2026-08-26 23:01:16 -03:00
diegosouzapw
b85d0abb0b fix(test): capture hook result after render 2026-08-26 22:45:24 -03:00
diegosouzapw
1325047d56 chore(lint): prune two stale base suppressions 2026-08-26 22:42:38 -03:00
diegosouzapw
6fee356aa2 test(video): retain structured fusion log details 2026-08-26 22:10:21 -03:00
diegosouzapw
e77b386619 security(video): close transcript retention boundaries 2026-08-26 22:02:13 -03:00
diegosouzapw
8893816d0c test(video): defend server-owned plugin sensitivity 2026-08-26 21:58:53 -03:00
diegosouzapw
71765435fb test(video): exercise proxy fast-fail boundary 2026-08-26 21:52:31 -03:00
diegosouzapw
e385778bcf test(video): expose proxy fast-fail log retention 2026-08-26 21:49:04 -03:00
diegosouzapw
fb8897e926 test(video): expose quota-model transcript retention 2026-08-26 21:34:41 -03:00
diegosouzapw
a9f98fcb48 test(video): expose guardrail log retention paths 2026-08-26 21:30:08 -03:00
diegosouzapw
6dab0df038 test(video): cover terminal and plugin-context retention 2026-08-26 21:24:41 -03:00
diegosouzapw
2ac715aa9c test(video): expose retained combo and plugin error paths 2026-08-26 21:22:23 -03:00
diegosouzapw
86e48e3c9a test(video): cover nested carrier chains 2026-08-26 21:11:10 -03:00
diegosouzapw
5fbf218139 test(video): cover round-robin transcript error logs 2026-08-26 21:09:00 -03:00
diegosouzapw
0095f3b38f test(video): prove application logs omit transcript echoes 2026-08-26 21:07:55 -03:00
Diego Rodrigues de Sa e Souza
2e8326d531 fix(db): dedupe lazy-decrypt-view failure logging across sync cycles (#11500) (#11678) 2026-08-26 20:50:15 -03:00
Diego Rodrigues de Sa e Souza
7133585d1d fix(combos): use the routing-alias prefix, not raw providerId, when serializing combo model steps (#11433) (#11670) 2026-08-26 20:50:09 -03:00
Diego Rodrigues de Sa e Souza
bcda889f84 fix(sse): keep each functionCall's own thoughtSignature on parallel Gemini tool-call turns (#11510) (#11669) 2026-08-26 20:50:02 -03:00
Diego Rodrigues de Sa e Souza
91ecb6be9c fix(sse): cap streaming headers-wait timeout to a client-realistic ceiling (#11526) (#11668) 2026-08-26 20:49:55 -03:00
Diego Rodrigues de Sa e Souza
e02f11984f fix(kie): correct 12 more mismatched KIE Market model ids (#11296) (#11667) 2026-08-26 20:49:48 -03:00
Diego Rodrigues de Sa e Souza
ca4df9bef8 fix(combo): attach combo diagnostics to round-robin and runtime-unit retry-limit 503s (#11462) (#11665) 2026-08-26 20:49:42 -03:00
Diego Rodrigues de Sa e Souza
0ce2b83005 fix(dashboard): skip full /sync-models catalog fetch when caller opts out (#11324) (#11664) 2026-08-26 20:49:34 -03:00
Diego Rodrigues de Sa e Souza
124f4cf761 fix(docker): re-derive build memory budget from measured per-process RSS (#7518) (#11663) 2026-08-26 20:49:27 -03:00
diegosouzapw
dabf8dd580 test(video): expose residual transcript retention paths 2026-08-26 20:47:09 -03:00
Xiangzhe
d92088c5dc docs(video): document transcript log-protection contract 2026-08-26 19:05:50 -03:00
Xiangzhe
20bd2c067c security(video): fail closed on hostile log payloads 2026-08-26 19:01:30 -03:00
Xiangzhe
1ed8f4ad4a test(video): prove fail-closed transcript inspection 2026-08-26 18:59:04 -03:00
Xiangzhe
f2f2fab636 security(video): redact transcript content across persistence and streams 2026-08-26 18:54:18 -03:00
Xiangzhe
b76aa02875 test(video): prove transcript retention across log sinks 2026-08-26 18:29:29 -03:00
Abhishek Sharma
4977f1adcf fix(opencode-plugin): stop a rounded free budget rendering as 1000K instead of 1M (#11684)
Merged via /merge-batch (2026-08-26, v3.8.51). Conflito trivial no package.json (lista de testes, mesclada com #11660). Também atualizei um teste pré-existente que documentava explicitamente o bug ("characterises the 999_999 rounding wart... Not this PR's bug to fix") — este PR é exatamente esse futuro fix, então virei a asserção para o comportamento correto (1M em vez de 1000K). Validado: 16/16 testes passando. Obrigado pela contribuição.
2026-08-26 17:58:35 -03:00
Xxx91n
99044ed044 feat(search): add fallback-only AnySearch provider (webSearch + webFetch) (#11690)
Merged via /merge-batch (2026-08-26, v3.8.51). Encontrei e corrigi algumas lacunas ao validar: (1) o tipo do provider em handleWebFetch (MCP) não incluía anysearch-search, (2) a lista FETCH_PROVIDERS do dashboard (/api/search/providers) não tinha a entrada anysearch-search apesar dela ser webSearch+webFetch, (3) contagens desatualizadas em search-registry/search-route/context7-provider/search-providers-catalog (19→20 search, +1 fetch). Enviei tudo para seu branch antes do merge. Validado: 113/113 testes relacionados passando, typecheck limpo. Obrigado pela contribuição — provider bem completo.
2026-08-26 17:54:57 -03:00
Rhian Batista
68aa69bc21 fix(ddgw): normaliza system no upstream da release v3.8.51 (#11692)
Merged via /merge-batch (2026-08-26, v3.8.51). Draft avaliada normalmente (diretiva padrão do dono) — passou na validação combinada. Obrigado pela contribuição.
2026-08-26 17:41:28 -03:00
小妍儿 ✨
14278e301c fix(models): gate the Codex-native catalog loop on prefix mode (#11632) (#11662)
Merged via /merge-batch (2026-08-26, v3.8.51). Draft avaliada normalmente (diretiva padrão do dono) — passou na validação combinada: typecheck/complexity/file-size/changelog verdes, testes focados passando. Obrigado pela contribuição.
2026-08-26 17:41:24 -03:00
Webman
38bc925187 test(chatcore): move fixtures off models the lifecycle guard now rejects (#11675)
Merged via /merge-batch (2026-08-26, v3.8.51). Boarded no worktree combinado; validação única passou. Obrigado pela contribuição.
2026-08-26 17:41:15 -03:00
Webman
8946ce71eb docs: sync canonical provider count 354 -> 356 (#11673)
Merged via /merge-batch (2026-08-26, v3.8.51). Boarded no worktree combinado; validação única: typecheck/complexity/cognitive-complexity/file-size/changelog verdes, lint nos mesmos 228 achados pré-existentes confirmados contra o tip puro, testes focados passando. Obrigado pela contribuição.
2026-08-26 17:40:54 -03:00
Webman
c8f3bc888e test(providers): update count-derived assertions for v3.8.51 additions (#11674)
Merged via /merge-batch (2026-08-26, v3.8.51). Boarded no worktree combinado; validação única: typecheck/complexity/cognitive-complexity/file-size/changelog verdes, lint nos mesmos 228 achados pré-existentes confirmados contra o tip puro, testes focados passando. Obrigado pela contribuição.
2026-08-26 17:40:50 -03:00
Diego Rodrigues de Sa e Souza
955c7bbf42 fix(security): compare the OIDC state cookie in constant time (#11646)
Merged via /merge-batch (2026-08-26, v3.8.51). Boarded no worktree combinado; validação única: typecheck/complexity/cognitive-complexity/file-size/changelog verdes, lint nos mesmos 228 achados pré-existentes confirmados contra o tip puro, testes focados passando. Obrigado pela contribuição.
2026-08-26 17:40:45 -03:00
Diego Rodrigues de Sa e Souza
ff25849530 fix(security): namespace the dedup hash by the calling API key (#11649)
Merged via /merge-batch (2026-08-26, v3.8.51). Boarded no worktree combinado; validação única: typecheck/complexity/cognitive-complexity/file-size/changelog verdes, lint nos mesmos 228 achados pré-existentes confirmados contra o tip puro, testes focados passando. Obrigado pela contribuição.
2026-08-26 17:40:41 -03:00
KaspaPulse
756b47fdd7 fix(dashboard): project Codex routing quota in account pools (#11666)
Merged via /merge-batch (2026-08-26, v3.8.51). Boarded no worktree combinado; validação única: typecheck/complexity/cognitive-complexity/file-size/changelog verdes, lint nos mesmos 228 achados pré-existentes confirmados contra o tip puro, testes focados passando. Obrigado pela contribuição.
2026-08-26 17:40:37 -03:00
Bob.Hou
e69f2109aa chore(search): drop unreachable credential sweep after #11642 (#11687)
Merged via /merge-batch (2026-08-26, v3.8.51). Boarded no worktree combinado; validação única: typecheck/complexity/cognitive-complexity/file-size/changelog verdes, lint nos mesmos 228 achados pré-existentes confirmados contra o tip puro, testes focados passando. Obrigado pela contribuição.
2026-08-26 17:40:32 -03:00
f9td56dbgh-hub
bda83c1d39 test: add unit tests for formatFreeBudget in opencode-plugin (#11660)
Merged via /merge-batch (2026-08-26, v3.8.51). Boarded no worktree combinado; validação única: typecheck/complexity/cognitive-complexity/file-size/changelog verdes, lint nos mesmos 228 achados pré-existentes confirmados contra o tip puro, testes focados passando. Obrigado pela contribuição.
2026-08-26 17:40:28 -03:00
Webman
67f4e5201d fix(sse): import httpClientAbortGuard with explicit .mjs extension (#11671)
Merged via /merge-batch (2026-08-26, v3.8.51). Boarded no worktree combinado; validação única: typecheck/complexity/cognitive-complexity/file-size/changelog verdes, lint nos mesmos 228 achados pré-existentes confirmados contra o tip puro, testes focados passando. Obrigado pela contribuição.
2026-08-26 17:40:22 -03:00
Webman
e95a25512d fix(resilience): restore expired-connection retry-budget probe in health sweep (#11672)
Merged via /merge-batch (2026-08-26, v3.8.51). Boarded no worktree combinado; validação única: typecheck/complexity/cognitive-complexity/file-size/changelog verdes, lint nos mesmos 228 achados pré-existentes confirmados contra o tip puro, testes focados passando. Obrigado pela contribuição.
2026-08-26 17:40:14 -03:00
Webman
146897d9bd test(gamification): pin aggregate level to #11604 XP-derived semantics (#11676)
Merged via /merge-batch (2026-08-26, v3.8.51). Boarded no worktree combinado; validação única: typecheck/complexity/cognitive-complexity/file-size/changelog verdes, lint nos mesmos 228 achados pré-existentes confirmados contra o tip puro, testes focados passando. Obrigado pela contribuição.
2026-08-26 17:40:02 -03:00
Webman
f75bd75389 test(sse): bump hard-lease inventory count for #11495 sweep query (#11677)
Merged via /merge-batch (2026-08-26, v3.8.51). Boarded no worktree combinado; validação única: typecheck/complexity/cognitive-complexity/file-size/changelog verdes, lint nos mesmos 228 achados pré-existentes confirmados contra o tip puro, testes focados passando. Obrigado pela contribuição.
2026-08-26 17:39:57 -03:00
Bob.Hou
42a13fedef fix(search): properly resolve configured search connection in /v1/responses pipeline (#11524) (#11642)
Merged via /merge-batch (2026-08-26, v3.8.51). O fix de produção já estava coberto por #11565 (mesma issue #11524, mergeada mais cedo hoje) — o conflito era só de comentários, mantido o texto já validado. Seu valor real: o novo teste de regressão do pipeline /v1/responses, que não existia ainda. Também corrigi 2 issues de lint introduzidas pelo novo teste (params `init` não usados renomeados para `_init`, contagem de supressão `no-explicit-any` ajustada) e o cap de tamanho do arquivo de teste (rebaseline). Validado: 55/55 testes de busca passando. Obrigado pela contribuição.
2026-08-26 13:43:58 -03:00
Bob.Hou
242c451298 fix(authz): trust cf-connecting-ip for via-proxy detection when peer is Cloudflare edge (#11514) (#11643)
Merged via /merge-batch (2026-08-26, v3.8.51). Validado: typecheck/complexity/file-size/changelog verdes, 18/18 testes de authz passando (com o isolamento correto de DATA_DIR — meu primeiro run isolado falhou por eu não ter carregado tests/_setup/isolateDataDir.ts, não é bug seu). Obrigado pela contribuição.
2026-08-26 13:39:29 -03:00
Webman
6e62aad32e chore(lint): prune stale ESLint suppressions (base-red #11449) (#11644)
Merged via /merge-batch (2026-08-26, v3.8.51). Validado.
2026-08-26 13:39:26 -03:00
238 changed files with 8450 additions and 769 deletions

View File

@@ -23,7 +23,7 @@
"scripts": {
"build": "tsup",
"clean": "rm -rf dist",
"test": "node --import tsx/esm --test tests/scaffold.test.ts tests/auth.test.ts tests/options-schema.test.ts tests/multi-instance.test.ts tests/fetch-interceptor.test.ts tests/provider.test.ts tests/gemini-sanitize.test.ts tests/combos.test.ts tests/config-shim.test.ts tests/features.test.ts tests/feature-defaults.test.ts tests/usable-combo.test.ts tests/disk-snapshot-perms.test.ts tests/fork-features.test.ts tests/auto-combo-context.test.ts tests/provider-id-routing.test.ts tests/management-read-token.test.ts tests/auto-sync.test.ts tests/model-allowlist.test.ts tests/log-level.test.ts tests/effort-tier-variants.test.ts",
"test": "node --import tsx/esm --test tests/scaffold.test.ts tests/auth.test.ts tests/options-schema.test.ts tests/multi-instance.test.ts tests/fetch-interceptor.test.ts tests/provider.test.ts tests/gemini-sanitize.test.ts tests/combos.test.ts tests/config-shim.test.ts tests/features.test.ts tests/feature-defaults.test.ts tests/usable-combo.test.ts tests/disk-snapshot-perms.test.ts tests/fork-features.test.ts tests/auto-combo-context.test.ts tests/provider-id-routing.test.ts tests/management-read-token.test.ts tests/auto-sync.test.ts tests/model-allowlist.test.ts tests/log-level.test.ts tests/effort-tier-variants.test.ts tests/naming.test.ts tests/free-budget-magnitude.test.ts",
"prepublishOnly": "npm run clean && npm run build && npm test"
},
"keywords": [

View File

@@ -23,27 +23,11 @@ const ALIAS_UPPER_MAX_CHARS = 5;
// ── Auto Combo Types ─────────────────────────────────────────────────────
export type AutoVariant =
| "coding"
| "fast"
| "cheap"
| "offline"
| "smart"
| "lkgp";
export type AutoVariant = "coding" | "fast" | "cheap" | "offline" | "smart" | "lkgp";
export const AUTO_VARIANTS: AutoVariant[] = [
"coding",
"fast",
"cheap",
"offline",
"smart",
"lkgp",
];
export const AUTO_VARIANTS: AutoVariant[] = ["coding", "fast", "cheap", "offline", "smart", "lkgp"];
export const AUTO_VARIANT_DESCRIPTIONS: Record<
AutoVariant | "default",
string
> = {
export const AUTO_VARIANT_DESCRIPTIONS: Record<AutoVariant | "default", string> = {
default: "Best provider via scoring",
coding: "Quality-first for code tasks",
fast: "Latency-optimized routing",
@@ -83,24 +67,15 @@ function titleCaseAlias(alias: string): string {
* 3. Neither → undefined.
*/
export function shortProviderLabel(
enrichment:
| { providerDisplayName?: string; providerAlias?: string }
| undefined,
enrichment: { providerDisplayName?: string; providerAlias?: string } | undefined
): string | undefined {
if (!enrichment) return undefined;
const raw =
typeof enrichment.providerDisplayName === "string"
? enrichment.providerDisplayName.trim()
: "";
typeof enrichment.providerDisplayName === "string" ? enrichment.providerDisplayName.trim() : "";
if (raw.length > 0 && raw.length <= PROVIDER_LABEL_MAX_CHARS) return raw;
const alias =
typeof enrichment.providerAlias === "string"
? enrichment.providerAlias.trim()
: "";
const alias = typeof enrichment.providerAlias === "string" ? enrichment.providerAlias.trim() : "";
if (alias.length > 0) {
return alias.length <= ALIAS_UPPER_MAX_CHARS
? alias.toUpperCase()
: titleCaseAlias(alias);
return alias.length <= ALIAS_UPPER_MAX_CHARS ? alias.toUpperCase() : titleCaseAlias(alias);
}
// Long displayName with no alias to fall back on: keep the long label
// rather than dropping the provider prefix entirely.
@@ -131,10 +106,33 @@ export function normaliseFreeLabel(name: string): string {
// ── Free Budget Formatting ────────────────────────────────────────────────
/** Scales, largest first, so the unit is chosen by descending magnitude. */
const TOKEN_UNITS = [
[1e9, "B"],
[1e6, "M"],
[1e3, "K"],
] as const;
/**
* Format a token count as a short magnitude string: `25M`, `1.5K`, `999`.
*
* The unit has to be picked from the value that will actually be *printed*,
* not from the raw input. `toFixed(1)` rounds to the nearest tenth, so at the
* K scale 999_950 and above render as `1000.0` — and by then the M branch has
* already been skipped, producing `1000K` for a number that is `1M`. The same
* carry turns just under a billion into `1000M`. When the rounded value reaches
* the next scale, re-render at that scale instead.
*/
function fmtTokens(n: number): string {
if (n >= 1e9) return (n / 1e9).toFixed(1).replace(/\.0$/, "") + "B";
if (n >= 1e6) return (n / 1e6).toFixed(1).replace(/\.0$/, "") + "M";
if (n >= 1e3) return (n / 1e3).toFixed(1).replace(/\.0$/, "") + "K";
for (let i = 0; i < TOKEN_UNITS.length; i++) {
const [scale, suffix] = TOKEN_UNITS[i]!;
if (n < scale) continue;
const value = Number((n / scale).toFixed(1));
// `Number()` also drops a trailing `.0`, which the previous regex did.
if (value < 1000 || i === 0) return `${value}${suffix}`;
const [nextScale, nextSuffix] = TOKEN_UNITS[i - 1]!;
return `${Number((n / nextScale).toFixed(1))}${nextSuffix}`;
}
return String(n);
}
@@ -184,15 +182,11 @@ export function formatFreeBudget(params: {
*/
export function formatAutoComboName(
variant: AutoVariant | undefined,
candidateCount?: number,
candidateCount?: number
): string {
const label = variant
? variant.charAt(0).toUpperCase() + variant.slice(1)
: "Default";
const label = variant ? variant.charAt(0).toUpperCase() + variant.slice(1) : "Default";
const count =
typeof candidateCount === "number" && candidateCount > 0
? ` (${candidateCount}p)`
: "";
typeof candidateCount === "number" && candidateCount > 0 ? ` (${candidateCount}p)` : "";
return `Auto: ${label}${count}`;
}

View File

@@ -0,0 +1,78 @@
/**
* Magnitude-crossover regression for the free-budget suffix
* (`formatFreeBudget` -> `fmtTokens` in @omniroute/opencode-plugin/src/naming.ts).
*
* `fmtTokens` picked its unit from the raw input and then rounded with
* `toFixed(1)`. Rounding can carry a value into the next magnitude *after* that
* branch has been skipped, so 999_950..999_999 rendered as "1000K" rather than
* "1M", and just under a billion rendered as "1000M" rather than "1B".
*
* These budgets are not always round numbers: `monthlyTokens` is derived from the
* remote Radar feed (`tokensPerMonth`) and can be replaced wholesale by a
* user-local override, so the crossover band is reachable with real data.
*
* Kept in its own file rather than added to naming.test.ts so this does not
* collide with the coverage being added for `formatFreeBudget` in #11660.
*/
import { test } from "node:test";
import assert from "node:assert/strict";
import { formatFreeBudget } from "../src/naming.js";
/** `recurring-daily` is the shortest path from a token count to a rendered suffix. */
const daily = (monthlyTokens: number) =>
formatFreeBudget({ freeType: "recurring-daily", monthlyTokens }).replace(" tokens/day", "");
test("fmtTokens: a rounded K value that reaches 1000 is promoted to M", () => {
// 999_950 is the true boundary, not 999_999: toFixed(1) rounds to the nearest
// tenth, so 999.95K is the first value that carries to "1000.0".
assert.equal(daily(999_950), "1M");
assert.equal(daily(999_999), "1M");
});
test("fmtTokens: a rounded M value that reaches 1000 is promoted to B", () => {
assert.equal(daily(999_950_000), "1B");
assert.equal(daily(999_999_999), "1B");
});
test("fmtTokens: values just below the rounding boundary keep their own unit", () => {
// The promotion must not fire early — 999.9K still rounds to 999.9, not 1000.
assert.equal(daily(999_949), "999.9K");
assert.equal(daily(999_499), "999.5K");
assert.equal(daily(999_499_999), "999.5M");
});
test("fmtTokens: ordinary magnitudes are unchanged", () => {
assert.equal(daily(0), "0");
assert.equal(daily(999), "999");
assert.equal(daily(1_000), "1K");
assert.equal(daily(1_500), "1.5K");
assert.equal(daily(1_000_000), "1M");
assert.equal(daily(1_500_000), "1.5M");
assert.equal(daily(25_000_000), "25M");
assert.equal(daily(1_234_567), "1.2M");
assert.equal(daily(1_000_000_000), "1B");
assert.equal(daily(2_500_000_000), "2.5B");
});
test("fmtTokens: B is the top unit, so a carry there has nowhere to go", () => {
// Deliberately pinned: promoting past B would need a unit that does not exist,
// so "1000B" is the intended output rather than an oversight.
assert.equal(daily(999_999_999_999), "1000B");
});
test("formatFreeBudget: the promotion applies to every token-bearing branch", () => {
assert.equal(
formatFreeBudget({ freeType: "recurring-monthly", monthlyTokens: 999_999 }),
"1M tokens/month"
);
assert.equal(
formatFreeBudget({ freeType: "recurring-credit", creditTokens: 999_999 }),
"1M credits"
);
assert.equal(
formatFreeBudget({ freeType: "one-time-initial", creditTokens: 999_999 }),
"1M credits (one-time)"
);
});

View File

@@ -0,0 +1,81 @@
/**
* Tests for `formatFreeBudget` (@omniroute/opencode-plugin/src/naming.ts):
* formats a free-tier model's budget info into a short human-readable
* suffix, branching on `freeType`.
*/
import { test } from "node:test";
import assert from "node:assert/strict";
import { formatFreeBudget, type FreeModelFreeType } from "../src/naming.js";
test("formatFreeBudget: recurring-daily formats tokens/day", () => {
assert.equal(
formatFreeBudget({ freeType: "recurring-daily", monthlyTokens: 25_000_000 }),
"25M tokens/day"
);
});
test("formatFreeBudget: recurring-monthly formats tokens/month", () => {
assert.equal(
formatFreeBudget({ freeType: "recurring-monthly", monthlyTokens: 1_000_000 }),
"1M tokens/month"
);
});
test("formatFreeBudget: recurring-credit formats credits", () => {
assert.equal(
formatFreeBudget({ freeType: "recurring-credit", creditTokens: 10_000_000 }),
"10M credits"
);
});
test("formatFreeBudget: one-time-initial formats credits with (one-time) suffix", () => {
assert.equal(
formatFreeBudget({ freeType: "one-time-initial", creditTokens: 1_000_000 }),
"1M credits (one-time)"
);
});
test("formatFreeBudget: keyless has no token/credit args", () => {
assert.equal(formatFreeBudget({ freeType: "keyless" }), "(keyless)");
});
test("formatFreeBudget: discontinued has no token/credit args", () => {
assert.equal(formatFreeBudget({ freeType: "discontinued" }), "(discontinued)");
});
test("formatFreeBudget: missing token/credit counts default to 0", () => {
assert.equal(
formatFreeBudget({ freeType: "recurring-daily" }),
"0 tokens/day"
);
});
test("formatFreeBudget: unrecognised freeType falls through to the default branch", () => {
// `freeType` is populated from catalog data at runtime, so a value the
// build doesn't know about is reachable even though TypeScript treats the
// `default:` arm as dead code for a well-typed caller.
assert.equal(
formatFreeBudget({ freeType: "some-future-type" as FreeModelFreeType }),
""
);
});
test("formatFreeBudget: sub-1K token count is not abbreviated", () => {
assert.equal(
formatFreeBudget({ freeType: "recurring-daily", monthlyTokens: 500 }),
"500 tokens/day"
);
});
test("formatFreeBudget: the 999_999 rounding wart is fixed — promotes to 1M", () => {
// `toFixed(1)` rounds 999999/1e3 up to "1000.0" before the `>= 1e6` threshold
// check has a chance to apply. fmtTokens now promotes a rounded-up "1000" in
// any unit to the next unit up, so this correctly reads "1M" instead of the
// old "1000K" wart.
assert.equal(
formatFreeBudget({ freeType: "recurring-daily", monthlyTokens: 999_999 }),
"1M tokens/day"
);
});

View File

@@ -46,7 +46,7 @@ Repository map and Reference Documentation sections below.
## Project at a Glance
**OmniRoute** — unified AI proxy/router. One endpoint, 354 LLM providers, auto-fallback.
**OmniRoute** — unified AI proxy/router. One endpoint, 357 LLM providers, auto-fallback.
| Layer | Location | Purpose |
| ------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

View File

@@ -7,7 +7,7 @@
# 🚀 OmniRoute — The Free AI Gateway
<img src="./docs/diagrams/readme-hero.svg" width="100%" alt="OmniRoute — Never stop coding. Every AI tool → 353 providers — 90+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot & Antigravity into FREE Claude / GPT / Gemini with auto-fallback. RTK + Caveman stacked compression saves 1595% tokens (~89% avg) — never hit limits. 353 AI providers · 90+ free tiers · ~1.51B free tokens/mo · 19 routing strategies · $0 to start."/>
<img src="./docs/diagrams/readme-hero.svg" width="100%" alt="OmniRoute — Never stop coding. Every AI tool → 357 providers — 90+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot & Antigravity into FREE Claude / GPT / Gemini with auto-fallback. RTK + Caveman stacked compression saves 1595% tokens (~89% avg) — never hit limits. 357 AI providers · 90+ free tiers · ~1.51B free tokens/mo · 19 routing strategies · $0 to start."/>
</div>
@@ -210,7 +210,7 @@ curl http://localhost:20128/v1/chat/completions \
</div>
<img src="./docs/diagrams/promise-pillars.svg" width="100%" alt="The Promise — One endpoint and 353 providers. Automatic fallback keeps routing while another healthy target is available. Six pillars: resilient fallback across 353 providers · up to 95% token savings on eligible workloads · $0 to start with 90+ free tiers and 56 recurring/keyless free-forever providers · 35 CLI/agent integrations through one config · OpenAI, Claude, Gemini and Responses API compatibility at /v1 · production controls including circuit breakers, TLS stealth, MCP 110 tools, A2A, memory, guardrails, evals and 39,000+ static test declarations across 5,100+ tracked test files."/>
<img src="./docs/diagrams/promise-pillars.svg" width="100%" alt="The Promise — One endpoint and 357 providers. Automatic fallback keeps routing while another healthy target is available. Six pillars: resilient fallback across 357 providers · up to 95% token savings on eligible workloads · $0 to start with 90+ free tiers and 56 recurring/keyless free-forever providers · 35 CLI/agent integrations through one config · OpenAI, Claude, Gemini and Responses API compatibility at /v1 · production controls including circuit breakers, TLS stealth, MCP 110 tools, A2A, memory, guardrails, evals and 39,000+ static test declarations across 5,100+ tracked test files."/>
<br/>
<br/>
@@ -461,7 +461,7 @@ All **19** strategies — mix & match per combo step:
</div>
<img src="./docs/diagrams/comparison-table.svg" width="100%" alt="What sets OmniRoute apart — a dated feature snapshot vs 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute: 353 providers, 90+ free tiers built in, 19 routing strategies, 12-engine token compression, built-in MCP server with 110 tools, A2A agent protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, Desktop/Termux/PWA and 43 i18n UI locales. OmniRoute is MIT-licensed and self-hostable. Competitor capabilities and counts may change; see the linked methodology."/>
<img src="./docs/diagrams/comparison-table.svg" width="100%" alt="What sets OmniRoute apart — a dated feature snapshot vs 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute: 357 providers, 90+ free tiers built in, 19 routing strategies, 12-engine token compression, built-in MCP server with 110 tools, A2A agent protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, Desktop/Termux/PWA and 43 i18n UI locales. OmniRoute is MIT-licensed and self-hostable. Competitor capabilities and counts may change; see the linked methodology."/>
<sub>📊 Full methodology &amp; per-feature detail vs 9router, OpenRouter, CLIProxyAPI &amp; LiteLLM → [`docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md`](docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md)</sub>
@@ -559,7 +559,7 @@ the current catalog at **[radar.omniroute.online/planos](https://radar.omniroute
- **🖼️ New endpoints** — `/v1/ocr` (Mistral OCR) and `/v1/audio/translations` (Whisper-style) round out the media surface. → [API Reference](docs/reference/API_REFERENCE.md)
- **🎨 Image / video / audio generation** — one API for media: xAI Grok Imagine & Novita AI video, ComfyUI, Freepik, Adobe Firefly, Microsoft Designer, Segmind, EdgeTTS. → [API Reference](docs/reference/API_REFERENCE.md)
- **🌍 Deployment & ops** — reverse-proxy `basePath`, browser-language auto-detect, per-key device tracking, root-less MITM trust, zh-TW localization. → [Environment](docs/reference/ENVIRONMENT.md)
- **🤝 More providers & agents** — Cursor Cloud Agent, Grok Build (xAI) with browser + OAuth login, Ollama first-class card, Claude Opus 5 & Sonnet 5, Kimi official partnership (Code/Web/Moonshot), Zed, Requesty, SenseNova, Yuanbao, Agnes AI… and a refreshed **353-provider catalog**. → [Providers](docs/reference/PROVIDER_REFERENCE.md)
- **🤝 More providers & agents** — Cursor Cloud Agent, Grok Build (xAI) with browser + OAuth login, Ollama first-class card, Claude Opus 5 & Sonnet 5, Kimi official partnership (Code/Web/Moonshot), Zed, Requesty, SenseNova, Yuanbao, Agnes AI… and a refreshed **357-provider catalog**. → [Providers](docs/reference/PROVIDER_REFERENCE.md)
- **📡 Routing transparency** — every response carries an `X-OmniRoute-Decision` header naming the strategy/provider/latency that served it, a new `cache-optimized` combo strategy + Auto-Combo `cacheAffinity` factor route repeat requests back to the connection holding the cached prefix, and a read-only `/v1/auto-combo/{channel}/candidates` endpoint exposes an `auto/*` channel's live candidate pool. → [Auto-Combo](docs/routing/AUTO-COMBO.md)
- **⚡ Local performance & infra** — one-click local Redis, Cloudflare Workers / Deno Deploy relay deployers, Bifrost & Mux as supervised embedded services. → [Embedded Services](docs/frameworks/EMBEDDED-SERVICES.md)
@@ -642,7 +642,7 @@ of your shell history. → [CLI Integrations](docs/guides/CLI-INTEGRATIONS.md)
<div align="center">
## 🌐 353 AI Providers — 154 Catalog-Marked Free
## 🌐 357 AI Providers — 154 Catalog-Marked Free
</div>

View File

@@ -0,0 +1 @@
- **feat(search):** Add AnySearch free web search + URL extract (webFetch) with typed results, credential validation, REST routing, and MCP selection - fallback-only

View File

@@ -0,0 +1 @@
- **fix(kie):** correct 12 more KIE Market catalog ids that were sent to `createTask` unchanged but diverge from KIE's documented upstream `model` values — GPT Image 2 T2I/I2I (drops the `gpt/` prefix), GPT Image 1.5 T2I/I2I (`gpt-image/` namespace), Seedream 5.0 Lite T2I/I2I (drops the `.0`), all 4 Flux 2 variants (`flux-2/` namespace, generic variant renamed `flex`), and Wan 2.7 Image / Image Pro (dash instead of dot) — each verified individually against the literal example request published on docs.kie.ai. `#11326`'s "everything else already matches" claim was wrong a second time (#11296); `z-image/4.0-*`/`z-image/4.5-*` and `flux/kontext` remain open, documented as unresolved in `KIE_MARKET_UPSTREAM_MODEL_IDS`'s comment pending further verification.

View File

@@ -0,0 +1 @@
- **fix(dashboard):** `useApiKeySave.handleSaveApiKey` no longer forces a full upstream `/models` catalog sync on every non-curated provider connection save — callers can now pass `skipModelSync: true` to opt out, so a workflow that only wants to add one manual model no longer floods the provider's available-models list with hundreds/thousands of synced entries. The flag is a client-side intent signal only and is stripped before the connection payload is POSTed to `/api/providers`; default behavior (full sync on save) is unchanged when the flag is omitted (#11324)

View File

@@ -0,0 +1 @@
- **fix(combos):** the combo builder's precision-select, global-model-search, and manual-entry flows now serialize a model step's `model` string using the provider's already-computed routing-alias prefix (e.g. `oc/`) instead of rebuilding it from the raw canonical `providerId`, fixing the no-auth "OpenCode Free" provider (`opencode`) being routed to the unrelated paid "OpenCode Zen" provider (`opencode-zen`) because `opencode` doubles as a manual routing-prefix override ([#11433](https://github.com/diegosouzapw/OmniRoute/issues/11433)).

View File

@@ -0,0 +1 @@
- fix(ui): let AnySearch use the normal provider-icon fallback when LobeHub has no matching icon (#11449)

View File

@@ -0,0 +1 @@
- **fix(combo):** attach the same combo-diagnostics trace (`poolSize`/`attemptOrder`/`excluded`/`terminalReason`, plus `x-omniroute-combo-*` headers) to the round-robin strategy's and the nested pipeline/fusion runtime-unit loop's "Maximum combo retry limit reached" 503 that the priority-strategy path already attaches for the identical terminal condition — previously those two paths returned a bare, contextless 503 ([#11462](https://github.com/diegosouzapw/OmniRoute/issues/11462)).

View File

@@ -0,0 +1 @@
- **fix(db):** dedupe the raw `[Encryption] Decryption failed...` log line emitted by the lazy-decrypt views (`createLazyRowProxy`/`createLazyConnectionView`), which power `getProviderConnections()` and were re-triggering that line on every CredentialHealth/model-sync cycle for the same corrupt or stale-key credential — a fresh Proxy over a fresh row on every cycle meant the per-proxy memoization never suppressed it, unlike the dedup `decryptConnectionFields()` already had since [#9927](https://github.com/diegosouzapw/OmniRoute/issues/9927). Now shares that dedupe tracking so the line logs at most once per credential ([#11500](https://github.com/diegosouzapw/OmniRoute/issues/11500)).

View File

@@ -0,0 +1 @@
- **fix(sse):** stop dropping resolved `thoughtSignature` values on parallel (multi tool-call) turns sent to Gemini 3.x — the claude→gemini and openai→gemini translators previously kept the signature only on the *first* function call of a message, causing Gemini to reject subsequent calls in the same turn with HTTP 400 "Function call is missing a thought_signature"; each function call now keeps its own resolved signature ([#11510](https://github.com/diegosouzapw/OmniRoute/issues/11510)).

View File

@@ -0,0 +1 @@
- **fix(sse):** cap the upstream headers-wait phase for STREAMING requests to a client-realistic ceiling (110s, under Codex's own ~120s hard client-abort window) instead of the flat 10-minute `FETCH_TIMEOUT_MS` default — that default was 5x longer than the body-phase readiness watchdog's own adaptive bound, so a request whose upstream never returned any response at all (not even headers, e.g. a stalled NVIDIA target behind a tool-heavy Responses→Chat translation) kept the client connection alive on keepalives only, guaranteeing the client's own patience ran out first with an opaque 499 instead of OmniRoute detecting and failing the stall fast. Non-streaming requests are unaffected — they keep the existing flat default (`open-sse/utils/fetchStartTimeoutPolicy.ts`) (#11526)

View File

@@ -0,0 +1 @@
- **sse:** fix LiveWS/embed-WS servers crashing at startup under the Node/tsx runtime — `liveServer.ts`, `embedWsProxy.ts` and `apiBridgeServer.ts` imported `@/shared/utils/httpClientAbortGuard` without the `.mjs` extension, so the client-abort crash guard added by [#11556](https://github.com/diegosouzapw/OmniRoute/pull/11556) was unreachable and every dependent test failed with `ERR_MODULE_NOT_FOUND` ([#11556](https://github.com/diegosouzapw/OmniRoute/pull/11556)).

View File

@@ -0,0 +1 @@
- **resilience:** restore the expired-connection retry-budget probe in the token-health sweep — the `!isGitHubAccessTokenOnlyConnection` carve-out reintroduced by #11608 contradicted the boundary pinned by #11592, so a GitHub connection parked at `expired` with retry budget remaining was never probed and could never self-heal ([#11592](https://github.com/diegosouzapw/OmniRoute/pull/11592)).

View File

@@ -0,0 +1 @@
- **test(gamification):** pin the aggregate profile level to the XP-derived semantics of #11604`getAggregateXp()` now derives `currentLevel` from the summed XP (`calculateLevel(sum)`), not `MAX(stored current_level)`, and the #3484 fixture levels are aligned with the XP curve ([#11604](https://github.com/diegosouzapw/OmniRoute/pull/11604)).

View File

@@ -0,0 +1 @@
- **test(chatcore):** move Codex/Claude combo fixtures off models the lifecycle guard now rejects — `gpt-5.1-codex`/`gpt-5-codex` are vendor-retired (snapshot, #11626) and `claude-3-5-sonnet-20241022` is shut down, so native-passthrough and combo-fallback tests switched to `gpt-5.6-sol` and `claude-sonnet-4.6` ([#11626](https://github.com/diegosouzapw/OmniRoute/pull/11626)).

View File

@@ -0,0 +1 @@
- **fix(security):** Video Bridge transcript text is now omitted from OmniRoute-owned retained request, response, usage, error, stream, continuation, handoff, and Memory surfaces while the live bridge request remains intact. Server-generated descriptions are matched by bounded SHA-256/length identities emitted only by a successful Video Bridge rewrite; ordinary fields named `transcript` and caller-forged description prose remain untouched. Traversal is cycle-safe and bounded, and hostile getters, proxies, or budget overflow fail closed to a constant omission marker instead of leaking content or breaking the request. Custom plugins and guardrails remain privileged processors of the live payload and must secure any sinks they create themselves. ([#11658](https://github.com/diegosouzapw/OmniRoute/issues/11658))

View File

@@ -0,0 +1 @@
- fix(opencode-plugin): stop a free-tier budget that rounds up across a magnitude from rendering as `1000K`/`1000M` in the model picker — `fmtTokens` chose its unit from the raw token count and then rounded with `toFixed(1)`, so 999,950999,999 printed as `1000K` rather than `1M` and just under a billion printed as `1000M` rather than `1B` ([#11684](https://github.com/diegosouzapw/OmniRoute/pull/11684))

View File

@@ -0,0 +1 @@
- **docs:** sync the canonical provider count 354 → 356 across `README.md`, `AGENTS.md`, `llm.txt` (+ 42 i18n mirrors), the four README SVG diagrams, `docs/reference/PROVIDER_REFERENCE.md` (regenerated) and the `package.json` description after Opper (#11629) and 1min.ai (#11631) boarded the catalog — closes the `check:docs-counts-sync` strict drifts that kept `release/v3.8.51` red ([#11449](https://github.com/diegosouzapw/OmniRoute/issues/11449)).

View File

@@ -0,0 +1 @@
- **test(providers):** update count-derived assertions after the v3.8.51 provider additions — `APIKEY_PROVIDERS` 233 → 235 (Opper #11629 + 1min.ai #11631), reserved-prefix REGISTRY walk 395 → 398, `WEB_FETCH_PROVIDERS` now includes `nimble-search` (#11620), and the provider translate-path golden snapshot regenerated ([#11449](https://github.com/diegosouzapw/OmniRoute/issues/11449)).

View File

@@ -0,0 +1 @@
- **test(sse):** bump the hard-lease connection-query inventory for `src/lib/tokenHealthCheck.ts` to 2 — the verify-only web-cookie sweep added by #11495 split the single `getProviderConnections` call into oauth + cookie variants, which the frozen inventory had not tracked ([#11495](https://github.com/diegosouzapw/OmniRoute/pull/11495)).

View File

@@ -0,0 +1 @@
- **test(opencode-plugin):** add unit test coverage for `formatFreeBudget()` naming helper ([#11660](https://github.com/diegosouzapw/OmniRoute/pull/11660)) — thanks @f9td56dbgh-hub

View File

@@ -2790,11 +2790,6 @@
"count": 3
}
},
"src/mitm/dns/dnsConfig.ts": {
"@typescript-eslint/no-unused-vars": {
"count": 1
}
},
"src/mitm/dns/provision.ts": {
"@typescript-eslint/no-unused-vars": {
"count": 1
@@ -2926,11 +2921,6 @@
"count": 1
}
},
"src/shared/middleware/chatBodyAdmission.ts": {
"@typescript-eslint/no-unused-vars": {
"count": 1
}
},
"src/shared/services/apiKeyResolver.ts": {
"no-restricted-imports": {
"count": 1
@@ -3440,10 +3430,10 @@
},
"tests/integration/skills-pipeline.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 14
"count": 15
},
"@typescript-eslint/no-unused-vars": {
"count": 2
"count": 1
}
},
"tests/integration/traffic-inspector-error-sanitization.test.ts": {
@@ -3690,11 +3680,6 @@
"count": 15
}
},
"tests/unit/authz/probe-9033-repro.test.ts": {
"@typescript-eslint/no-unused-vars": {
"count": 1
}
},
"tests/unit/autoCombo/tieredRotation.test.ts": {
"@typescript-eslint/no-unused-vars": {
"count": 3

View File

@@ -229,7 +229,8 @@
"tests/unit/vscode-token-routes.test.ts": 1633,
"tests/unit/executor-antigravity.test.ts": 1427,
"tests/unit/guardrails/videoBridgeResultCache.test.ts": 1040,
"_rebaseline_2026_08_24_video_bridge_fu01_fu03_fu04_result_cache_tests": "PRs #11362 (FU-01 cache hardening) + #11382 (FU-03 visual dedup policy identity) + #11383 (FU-04 focused analysis mode) own test growth: videoBridgeResultCache.test.ts <1000->1040, +40 (sum of three stacked PRs boarded together in the same merge-batch, each adding its own cache-identity assertions on the shared result-cache seam). Owner pre-authorized rebaseline for legitimate PR growth (2026-08-19 directive)."
"_rebaseline_2026_08_24_video_bridge_fu01_fu03_fu04_result_cache_tests": "PRs #11362 (FU-01 cache hardening) + #11382 (FU-03 visual dedup policy identity) + #11383 (FU-04 focused analysis mode) own test growth: videoBridgeResultCache.test.ts <1000->1040, +40 (sum of three stacked PRs boarded together in the same merge-batch, each adding its own cache-identity assertions on the shared result-cache seam). Owner pre-authorized rebaseline for legitimate PR growth (2026-08-19 directive).",
"tests/integration/skills-pipeline.test.ts": 1010
},
"_rebaseline_2026_06_09": "Re-baseline consciente pre-release v3.8.19: 9 arquivos cresceram durante o ciclo (features mergeadas: RequestLoggerV2 +281 request-logger rework, stream +101, combo +73, chatCore +45, catalog +32 fable-5/catalog-flag, callLogs +4, accountFallback +2, usageHistory novo 840) + core.ts +7 (fix resetAllDbModuleState, PR 3536). A catraca segue valendo destes valores — proximo crescimento falha. Decisao: encolher (esp. RequestLoggerV2/chatCore) e a issue #3501 ficam para o ciclo seguinte.",
"_rebaseline_2026_06_11_phase1f": "Phase 1f (#3501): ProviderDetailPageClient.tsx 4948→4062 (-886 LOC); 3 novos hooks extraídos. useProviderConnections.ts=954 acima do cap=800 — justificado: extração direta do god-component (zero lógica nova), própria redução do cliente supera o custo. useProviderSettings.ts=263 e useProviderModels.ts=154 já abaixo do cap.",
@@ -652,5 +653,6 @@
"_rebaseline_2026_08_20_imageregistry_1034": "imageRegistry.ts 1033->1034: +1 line drift between #10842 (cursor image provider, froze at 1033) and its actual merged state on release (measured 1034) — trivial rebaseline, not a new feature.",
"_rebaseline_2026_08_25_11146_subscription_first_auto": "PR #11146 (@yourspraveen, subscription-first auto groupings auto/subscription+auto/thrifty): open-sse/services/autoCombo/virtualFactory.ts is a NEW file in this PR landing at 1128 lines (+2 margin) — two opt-in flat auto ids built on the established auto/best-free pattern (connectionBillingCatalog + subscriptionLadder pure functions). Frozen at merge size per owner-authorized rebaseline directive (2026-08-19, merge-batch Step 4); no further growth without split rationale.",
"_rebaseline_2026_08_26_mergebatch_v3851_batch1": "/merge-batch 2026-08-26 (v3.8.51): three legitimate growths from this batch. #11448 src/app/api/providers/[id]/test/route.ts 1237->1262 (auto-test-on-create wiring). #11495 src/sse/services/auth.ts 3346->3376 (web-cookie health-sweep verify-only path). #11561 src/lib/cloudflaredTunnel.ts new named-tunnel mode, lands at 1078 (+78 over the 1000 new-file cap) for the CLOUDFLARED_CONFIG named-tunnel flow (login->create->route dns config parsing + readiness detection). Owner-authorized rebaseline per merge-batch Step 4 (2026-08-19 directive); no further growth without split rationale.",
"_rebaseline_2026_08_26_mergebatch_v3851_batch2": "/merge-batch 2026-08-26 (v3.8.51) batch 2: three legitimate growths. #11083 src/shared/components/RequestLoggerDetail.tsx new-file cap, lands at 1018 (+18 over 1000) — copy-all button for request detail modal. #11631 src/shared/constants/providers/apikey/gateways.ts 1321->1330 (1min.ai gateway entry). #11628 src/sse/services/auth.ts 3376->3432 (credential-health isolation from model failures). Owner-authorized rebaseline per merge-batch Step 4 (2026-08-19 directive); no further growth without split rationale."
"_rebaseline_2026_08_26_mergebatch_v3851_batch2": "/merge-batch 2026-08-26 (v3.8.51) batch 2: three legitimate growths. #11083 src/shared/components/RequestLoggerDetail.tsx new-file cap, lands at 1018 (+18 over 1000) — copy-all button for request detail modal. #11631 src/shared/constants/providers/apikey/gateways.ts 1321->1330 (1min.ai gateway entry). #11628 src/sse/services/auth.ts 3376->3432 (credential-health isolation from model failures). Owner-authorized rebaseline per merge-batch Step 4 (2026-08-19 directive); no further growth without split rationale.",
"_rebaseline_2026_08_26_mergebatch_v3851_batch5": "/merge-batch 2026-08-26 (v3.8.51) batch 5: #11642 tests/integration/skills-pipeline.test.ts new regression test for the configured-provider-over-fallback search selection (#11524), lands at 1010 lines (+10 over the 1000 new-file testCap). Owner-authorized rebaseline per merge-batch Step 4 (2026-08-19 directive); no further growth without split rationale."
}

View File

@@ -188,14 +188,15 @@
"dedicatedGate": true
},
"bundleSize": {
"value": 8461,
"value": 8653,
"direction": "down",
"dedicatedGate": true,
"_rebaseline_2026_07_07_v3846_release_close": "5601->6534 (+933). v3.8.46 release close: gzip of the 4 bin/*.mjs entrypoints (size-limit + @size-limit/file) grew from this cycle's feature/fix merges pulled transitively into the CLI entrypoints (new providers, combo pipeline strategy #6396, effort/thinking standardization #6241, catalog cache-invalidation #6408). Measured 6534 locally via `check:bundle-size --ratchet` (deterministic gzip, matches CI). Legitimate cycle growth; shrink is separate debt.",
"_rebaseline_2026_07_19_7808_codeql_alias_resolver_hook": "6534->6762 (+228). PR #7808 (CodeQL js/incomplete-url-substring-sanitization fix): the ESM loader hook source moved out of the inline `HOOK_SOURCE` template literal in bin/aliasResolver.mjs into a real file bin/aliasResolverHook.mjs, loaded via pathToFileURL() instead of a dynamically-built `data:text/javascript,...` URL. The new file is now counted by size-limit as a 5th bin/*.mjs entrypoint. Net +228 = the hook's gzip size (previously hidden inside aliasResolver.mjs because the template literal was compressed away). Security-driven; no shrink opportunity.",
"_rebaseline_2026_07_28_v3849_release_preflight": "6762 -> 7666 (+904). Fechamento do ciclo v3.8.49: gzip dos entrypoints bin/*.mjs (size-limit + @size-limit/file) cresceu com o que os merges do ciclo puxam transitivamente para o CLI (novos provedores — 271->290, seletor de protocolo por conexão #8861, catálogos de busca #8814, resiliência). Crescimento legítimo de ciclo, medido localmente com `npm run check:bundle-size` = 7666 (gzip determinístico, bate com o CI). Encolher é dívida separada.",
"_rebaseline_2026_08_09_v3850_release_close": "7666 -> 8045 (+379 gzip bytes, +4.9%). Release v3.8.50 close reconciliation measured twice with the real size-limit + @size-limit/file path on tip e0ce95c592. Per-entry measurements remain below their absolute budgets: omniroute.mjs 4380/15000, mcp-server.mjs 1195/5000, nodeRuntimeSupport.mjs 887/8000, reset-password.mjs 1583/6000. The growth accumulated through legitimate CLI/runtime work in this cycle, including global-install ESM alias resolution, Termux cache preparation, and MCP stdio startup hardening; no entrypoint is near its absolute ceiling. The direction:down ratchet stays blocking from this exact measured tip.",
"_rebaseline_2026_08_24_ci_green_gates_f95b03d7": "8045 -> 8461 (+416 gzip bytes, +5.2%). CI run 32786966560 (release PR #8875, tip f95b03d7) measured bundleSize=8461 via check:bundle-size --ratchet, above the 8045 baseline left at the v3.8.50 close. The growth comes from the post-freeze back-merge cycle landing in the CLI entrypoints (Synthetic + Kilo Gateway providers, kilo-gateway routing surface). Re-baseline per the gate's own instruction (legitimate cycle growth); shrinking the entrypoints remains separate debt; direction:down ratchet stays blocking from this measured tip."
"_rebaseline_2026_08_24_ci_green_gates_f95b03d7": "8045 -> 8461 (+416 gzip bytes, +5.2%). CI run 32786966560 (release PR #8875, tip f95b03d7) measured bundleSize=8461 via check:bundle-size --ratchet, above the 8045 baseline left at the v3.8.50 close. The growth comes from the post-freeze back-merge cycle landing in the CLI entrypoints (Synthetic + Kilo Gateway providers, kilo-gateway routing surface). Re-baseline per the gate's own instruction (legitimate cycle growth); shrinking the entrypoints remains separate debt; direction:down ratchet stays blocking from this measured tip.",
"_rebaseline_2026_08_27_v3851_volatile_env_warning_11437": "8461 -> 8653 (+192 gzip bytes, +2.3%). Exact paired size-limit measurements on the VPS compared f95b03d709 with release/v3.8.51: only bin/omniroute.mjs changed, 4700 -> 4892; the other three entries remained 1195/983/1583. The growth originates in 943b9aaa84 (#11437), which warns users before a package-local .env is lost on the next global install. The CLI entry remains 4892/15000 bytes (32.6% of its absolute budget). Legitimate bug-fix growth; shrinking stays separate debt and direction:down remains blocking from this measured tip."
},
"openapiBreaking": {
"value": 4,

View File

@@ -1,4 +1,4 @@
<svg viewBox="0 0 1200 350" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Animated terminal demoing the OmniRoute CLI: omniroute providers list (354 providers registered, anthropic, codex, glm, kimi shown active), omniroute combo list (always-on priority, cost-saver, fusion-panel, context-relay) and omniroute health (healthy, 18412 requests in 24h, p95 412ms, circuit breakers 24 closed, 1 half-open, 0 open), cycling over 85 top-level commands: providers, oauth, keys, combo, nodes, models, cache, compression, cost, usage, quota, health, resilience, telemetry, logs, audit, mcp, a2a, cloud, memory, skills, eval, doctor, repl, tunnel, backup, sync, webhooks, policy, pricing, translator, simulate and more.">
<svg viewBox="0 0 1200 350" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Animated terminal demoing the OmniRoute CLI: omniroute providers list (357 providers registered, anthropic, codex, glm, kimi shown active), omniroute combo list (always-on priority, cost-saver, fusion-panel, context-relay) and omniroute health (healthy, 18412 requests in 24h, p95 412ms, circuit breakers 24 closed, 1 half-open, 0 open), cycling over 85 top-level commands: providers, oauth, keys, combo, nodes, models, cache, compression, cost, usage, quota, health, resilience, telemetry, logs, audit, mcp, a2a, cloud, memory, skills, eval, doctor, repl, tunnel, backup, sync, webhooks, policy, pricing, translator, simulate and more.">
<desc>Compact animated terminal cycling three real OmniRoute CLI commands with a typewriter effect and a scrolling subcommand ticker; the first frame shows the completed providers-list screen.</desc>
<defs><clipPath id="tickerClip"><rect x="12" y="304" width="1176" height="40"/></clipPath><clipPath id="tw0"><rect x="64" y="46" height="26" width="0"><animate attributeName="width" calcMode="discrete" values="0;31;61;92;122;153;184;214;245;245" keyTimes="0;0.012;0.018;0.024;0.030;0.036;0.042;0.048;0.054;1" dur="18s" repeatCount="indefinite"/></rect></clipPath><clipPath id="tw1"><rect x="64" y="46" height="26" width="0"><animate attributeName="width" calcMode="discrete" values="0;26;51;76;102;128;153;178;204;204" keyTimes="0;0.348;0.351;0.357;0.363;0.369;0.375;0.381;0.387;1" dur="18s" repeatCount="indefinite"/></rect></clipPath><clipPath id="tw2"><rect x="64" y="46" height="26" width="0"><animate attributeName="width" calcMode="discrete" values="0;20;41;61;82;102;122;143;163;163" keyTimes="0;0.678;0.684;0.690;0.696;0.702;0.708;0.714;0.720;1" dur="18s" repeatCount="indefinite"/></rect></clipPath></defs>
<rect width="1200" height="350" fill="#0d1117"/>

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,4 +1,4 @@
<svg viewBox="0 0 1200 780" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Comparison table: OmniRoute versus 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute is the only one with the full set: 354 providers, 90+ free providers built-in, 19 routing strategies, 12-engine token compression, a built-in MCP server with 110 tools, A2A protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, desktop/Termux/PWA, 43 UI locales and 100% MIT self-hosted. 9router has free providers, RTK compression and translation but no MCP, A2A, memory, guardrails, cloud agents or stealth. OpenRouter is a hosted SaaS with 400+ models, guardrails and a hosted MCP but is not self-hosted and lacks A2A, memory, cloud agents and stealth. CLIProxyAPI is a light OAuth proxy with two routing strategies. LiteLLM has 100+ providers, A2A and extensive guardrails but no memory, compression, free tier, stealth or cloud agents.">
<svg viewBox="0 0 1200 780" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Comparison table: OmniRoute versus 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute is the only one with the full set: 357 providers, 90+ free providers built-in, 19 routing strategies, 12-engine token compression, a built-in MCP server with 110 tools, A2A protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, desktop/Termux/PWA, 43 UI locales and 100% MIT self-hosted. 9router has free providers, RTK compression and translation but no MCP, A2A, memory, guardrails, cloud agents or stealth. OpenRouter is a hosted SaaS with 400+ models, guardrails and a hosted MCP but is not self-hosted and lacks A2A, memory, cloud agents and stealth. CLIProxyAPI is a light OAuth proxy with two routing strategies. LiteLLM has 100+ providers, A2A and extensive guardrails but no memory, compression, free tier, stealth or cloud agents.">
<desc>Static-header comparison table where each capability row fades in top to bottom; the OmniRoute column is highlighted and shows a check or a leading value in every row, while competitors show a mix of checks, partials and crosses.</desc>
<defs>
<pattern id="gC" width="32" height="32" patternUnits="userSpaceOnUse"><path d="M 32 0 L 0 0 0 32" fill="none" stroke="#ffffff" stroke-opacity="0.05" stroke-width="1"/></pattern>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -1,4 +1,4 @@
<svg viewBox="0 0 1200 540" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="The OmniRoute promise: one endpoint and 354 providers. Six pillars. Resilient fallback: automatic routing continues while another healthy target is available. Save up to 95 percent of eligible tokens: RTK plus Caveman stacked compression averages about 89 percent on tool-heavy sessions. Zero dollars to start: 90+ providers with a free tier and 56 recurring or keyless free-forever providers. Every tool works: 35 CLI and agent integration records, including Claude Code, Codex, Cursor, Cline, Copilot and Antigravity, through one config. One endpoint: OpenAI, Claude, Gemini and Responses API translation at /v1. Production controls: circuit breakers, TLS stealth, MCP with 110 tools, A2A, memory, guardrails, evals, and 39,000+ static test declarations across 5,100+ tracked test files.">
<svg viewBox="0 0 1200 540" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="The OmniRoute promise: one endpoint and 357 providers. Six pillars. Resilient fallback: automatic routing continues while another healthy target is available. Save up to 95 percent of eligible tokens: RTK plus Caveman stacked compression averages about 89 percent on tool-heavy sessions. Zero dollars to start: 90+ providers with a free tier and 56 recurring or keyless free-forever providers. Every tool works: 35 CLI and agent integration records, including Claude Code, Codex, Cursor, Cline, Copilot and Antigravity, through one config. One endpoint: OpenAI, Claude, Gemini and Responses API translation at /v1. Production controls: circuit breakers, TLS stealth, MCP with 110 tools, A2A, memory, guardrails, evals, and 39,000+ static test declarations across 5,100+ tracked test files.">
<desc>Animated promise card: six pillar tiles fade in in reading order, then a soft colored border highlight sweeps from tile to tile in a continuous cycle.</desc>
<defs>
<pattern id="gridPaperP" width="32" height="32" patternUnits="userSpaceOnUse">
@@ -21,7 +21,7 @@
<line x1="150" y1="53" x2="1160" y2="53" stroke="#232b38" stroke-width="1.5"/>
</g>
<g>
<text x="40" y="100" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="23" font-weight="600" fill="#c9d1d9">One endpoint. <tspan fill="#a78bfa" font-weight="800">354 providers.</tspan> Never stop building — OmniRoute picks <tspan fill="#7ee787" font-weight="700">the cheapest one that works</tspan>.</text>
<text x="40" y="100" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="23" font-weight="600" fill="#c9d1d9">One endpoint. <tspan fill="#a78bfa" font-weight="800">357 providers.</tspan> Never stop building — OmniRoute picks <tspan fill="#7ee787" font-weight="700">the cheapest one that works</tspan>.</text>
</g>
<g font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif">
@@ -38,7 +38,7 @@
<line x1="3.9" y1="3.9" x2="18.1" y2="18.1"/>
</g>
<text x="102" y="170" font-size="18" font-weight="800" fill="#74b9ff">Never hit limits</text>
<text x="66" y="204" font-size="13.5" fill="#a1a1aa">Auto-fallback across 354 providers in</text>
<text x="66" y="204" font-size="13.5" fill="#a1a1aa">Auto-fallback across 357 providers in</text>
<text x="66" y="226" font-size="13.5" fill="#a1a1aa">milliseconds. Quota out? The next provider</text>
<text x="66" y="248" font-size="13.5" fill="#a1a1aa">takes over while a healthy target remains.</text>
</g>

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -1,4 +1,4 @@
<svg viewBox="0 0 1200 548" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="OmniRoute hero: Never stop coding. Every AI tool to 354 providers — 90+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot and Antigravity into free Claude, GPT and Gemini with auto-fallback. RTK + Caveman stacked compression saves 15 to 95 percent of tokens — about 89 percent average on tool-heavy sessions — so you never hit limits. Stats: 354 AI providers, 90+ free tiers, about 1.51B free tokens per month, 15 to 95 percent token savings, 19 routing strategies, zero dollars to start.">
<svg viewBox="0 0 1200 548" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="OmniRoute hero: Never stop coding. Every AI tool to 357 providers — 90+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot and Antigravity into free Claude, GPT and Gemini with auto-fallback. RTK + Caveman stacked compression saves 15 to 95 percent of tokens — about 89 percent average on tool-heavy sessions — so you never hit limits. Stats: 357 AI providers, 90+ free tiers, about 1.51B free tokens per month, 15 to 95 percent token savings, 19 routing strategies, zero dollars to start.">
<desc>Animated hero card: a pulse travels the divider line and a compression bar demo repeatedly shrinks a prompt by up to 95 percent; all headline content is static and readable on the first frame.</desc>
<defs>
<pattern id="gridPaperH" width="32" height="32" patternUnits="userSpaceOnUse">
@@ -28,7 +28,7 @@
<text x="48" y="138" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="60" font-weight="800" fill="#e9edf3">Never stop coding<tspan fill="#a855f7">.</tspan></text>
<!-- subheadline -->
<text x="48" y="184" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="25" font-weight="600" fill="#c9d1d9">Every AI tool → <tspan fill="#a78bfa" font-weight="800">354 providers</tspan><tspan fill="#7ee787" font-weight="800">90+ free</tspan> — through one endpoint.</text>
<text x="48" y="184" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="25" font-weight="600" fill="#c9d1d9">Every AI tool → <tspan fill="#a78bfa" font-weight="800">357 providers</tspan><tspan fill="#7ee787" font-weight="800">90+ free</tspan> — through one endpoint.</text>
<!-- plug line -->
<text x="48" y="222" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="16.5" fill="#a1a1aa">Claude Code · Codex · Cursor · Cline · Copilot · Antigravity&#160;&#160;&#160;&#160;<tspan fill="#7ee787" font-weight="700">FREE</tspan> Claude / GPT / Gemini · auto-fallback</text>

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -57,7 +57,7 @@ New tab for extracting content from a URL via `POST /v1/web/fetch` (created in p
- Submit → fetch → render `ScrapeResult.tsx`.
- `ScrapeResult` renders markdown preview + raw toggle.
- Cap: if response body > **256 KB**, UI shows `(truncated, view raw)` and opens raw in a Monaco modal (D21).
- Metadata panel: provider (firecrawl/jina-reader/tavily-search/tinyfish/nimble-search), latency, cost, response size, links count.
- Metadata panel: provider (firecrawl/jina-reader/tavily-search/tinyfish/nimble-search/anysearch-search), latency, cost, response size, links count.
- Uses `useScrapeFetch.ts` hook.
### Compare Tab
@@ -105,15 +105,7 @@ Runs the same query/URL across up to **4 providers in parallel** (D22):
`ProviderCatalog.tsx` exposes the full provider list from `GET /api/search/providers`
(extended in F4 to include fetch providers):
| Field | Source |
| ------------------------------ | ------------------------------------------------------------------------------------------ |
| `id`, `name` | `searchRegistry.ts` |
| `kind` | `"search"` or `"fetch"` (firecrawl, jina-reader, tavily-search, tinyfish, nimble-search) |
| `costPerQuery` | Registry data |
| `freeMonthlyQuota` | Registry data |
| `searchTypes` / `fetchFormats` | Registry data |
| `status` | `"configured"` / `"missing"` / `"rate_limited"` — derived at runtime from credential store |
| `configureHref` | `/dashboard/providers` |
| `kind` | `"search"` (20 providers) or `"fetch"` (firecrawl, jina-reader, tavily-search, tinyfish, nimble-search, anysearch-search) |
The status is **derived at request time** by checking whether credentials exist and whether
all keys are currently in cooldown.
@@ -136,7 +128,7 @@ Only one backend change was needed for this feature:
`src/app/api/search/providers/route.ts` was extended to:
- Include every fetch provider (`firecrawl`, `jina-reader`, `tavily-search`, `tinyfish`, `nimble-search`) in the array.
- Include all 6 fetch providers (`firecrawl`, `jina-reader`, `tavily-search`, `tinyfish`, `nimble-search`, `anysearch-search`) in the array.
- Add `kind: "search" | "fetch"` to every item.
- Add `status: "configured" | "missing" | "rate_limited"` derived from live credential state.
- Maintain backward compatibility — existing fields (`id`, `name`, etc.) unchanged.

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -4,7 +4,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -281,7 +281,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -479,7 +479,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -1199,6 +1199,8 @@ paths:
Searches the web, news, or X through a configured provider. Set `provider`
to `xquik-search` to use Xquik for X search. The aliases `xquik` and
`xquik_search` resolve to the same provider.
AnySearch (`anysearch-search`, aliases `anysearch` / `anysearch_search`)
provides free fallback-only web search.
security:
- BearerAuth: []
requestBody:

View File

@@ -0,0 +1,45 @@
# AnySearch provider integration (PR #11690)
Template: xquik #11370 (merged in release/v3.8.51). Posture: `fallbackOnly`.
Upstream proposal: issue diegosouzapw/OmniRoute#11637.
## 1. Service ground truth (official docs, cross-checked)
- Base URL: `https://api.anysearch.com` (REST) + `POST /mcp` (MCP, JSON-RPC 2.0).
- `POST /v1/search` - params: `query` (required), `max_results` (1-10, default 10), `tag` (`{domain}.{sub_domain}` vertical routing), `zone` (cn/intl), `language`, `params` (structured vertical fields), `format` (json/markdown).
- `GET /v1/sub-domains?domain=...` - capability catalog, does NOT count against quota.
- `POST /v1/extract` - fetch/extract `{url, title, content}`; strict JSON body, 16 KiB cap.
- `POST /v1/auth/email/register` - single-call registration, returns one-time plaintext key `as_sk_...`.
- Auth: optional `Authorization: Bearer <as_sk_...>`; anonymous degrades to per-IP limits consuming the daily free quota; invalid key returns 401/403 with NO silent anonymous fallback.
- Free tier: 1000 requests/day, 20 QPS per key. Paid tier: unpriced (Coming Soon).
- Response envelope: success `{code: 0, message: "success", request_id, data}`; failure `{code: -1, message}`. Auth/quota errors carry no structured `error_code` (the message text is the signal); extract-specific errors do carry `error_code` (`invalid_extract_url`, `extract_failed`). No `Retry-After` header on 429.
## 2. Touch set (~10 layers, mirrors the xquik footprint)
| Layer | File | Change |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| Registry entry | `open-sse/config/searchRegistry.ts` | `anysearch-search` entry + aliases `anysearch`, `anysearch_search` |
| Executor | `open-sse/handlers/search/anysearchSearch.ts` | `buildAnysearchSearchRequest`, `normalizeAnysearchSearchResponse`, `AnysearchSearchEnvelopeError` |
| Dispatch maps | `open-sse/handlers/search.ts` + `searchProxy.ts` | request-builder map + response-normalizer map; envelope error -> 402 (quota) / 502 (other) |
| Fetch executor | `open-sse/executors/anysearch-fetch.ts` + `open-sse/handlers/webFetch.ts` | `POST /v1/extract`; union + `WEB_FETCH_PROVIDERS` + dispatch case; quota envelope -> 402 |
| UI catalog | `src/shared/constants/providers/search.ts` | metadata entry (`serviceKinds: ["webSearch", "webFetch"]`); authHint documents the 1000/day free tier |
| Credential validation | `src/lib/providers/validation/searchProviders.ts` | `SEARCH_VALIDATOR_CONFIGS["anysearch-search"]` (Bearer probe) |
| MCP | `open-sse/mcp-server/schemas/tools.ts` | fetch enum + web_search description |
| API schema | `src/shared/validation/schemas/apiV1.ts`, `docs/openapi.yaml` | alias canonicalization + provider enum |
| Docs | `docs/reference/PROVIDER_REFERENCE.md`, `docs/frameworks/SEARCH_TOOLS_STUDIO.md`, `changelog.d/features/anysearch-search-provider.md` | consistency copies |
| Tests | `tests/unit/anysearch-search-provider.test.ts` (8 cases), `tests/unit/executor-anysearch-fetch.test.ts` (2 cases), `search-registry.test.ts`, `search-route.test.ts`, `tests/integration/search-providers-catalog.test.ts`, `tests/snapshots/executors/dispatch-rules.json` | mirror xquik suite; catalog counts 20 search / 6 fetch (coexisting with nimble-search) |
## 3. Decisions (all reached 2026-08-26)
1. **Routing posture: `fallbackOnly`.** Rationale: a cost-0 free provider must never dominate automatic cost routing; explicit selection and failover return are unaffected. Precedent: merged xquik entry.
2. **Scope: webSearch + webFetch via `POST /v1/extract` in v1.** Aligned with the tavily/exa dual-capability mental model. Vertical surfaces (`tag`, `sub-domains`, `batch_search`) stay out of scope — there is no IR for vertical params today.
3. **Quota display: `freeMonthlyQuota: 0`** (xquik-style conservative display). The real allowance (1000 req/day, daily reset) is carried in the UI catalog `authHint` copy instead. Rationale: quota display must match reset semantics; converting a daily cap to a monthly-equivalent (30000) is a false promise the UI cannot honor.
4. **searchTypes: `["web"]` only.** No public evidence of a news/images vertical in the AnySearch API; gateways integrating APIs without a documented vertical (e.g. Google Custom Search) expose web only rather than silently mapping news -> web.
5. **Key posture:** keyless works; an invalid key returns 401/403 and is never silently downgraded to anonymous (mirrors the upstream contract).
6. **Deliberate exclusions:** `FETCH_BACKEND_TO_PROVIDER` / `FetchInterceptionBackend` (chat interception stays firecrawl/jina/tavily); `ANONYMOUS_CAPABLE_WEB_FETCH_PROVIDERS` (anonymous remote endpoints share one IP-limited pool per egress IP, so keyless extract is opt-in, not an auto-routing candidate); `QUOTA_STATUS_PROVIDERS` (AnySearch signals quota via 429/envelope, not 402/403 status).
## 4. References
- xquik template: commit a0ceccc, PR #11370 (in-tree at release/v3.8.51).
- AnySearch official docs: https://anysearch.com/docs, https://anysearch.com/pricing; MCP catalog mcpservers.org/servers/anysearch-ai/anysearch-mcp-server; skill repo github.com/anysearch-ai/anysearch-skill.
- Industry mental model: LiteLLM search docs (registry + unified search() + Perplexity-spec IR), open-webui web search (built-in providers, search_web/fetch_url dual tools), Dify tool plugin pattern; cost-fallback ladder: self-hosted -> free quota -> paid.

View File

@@ -1,16 +1,16 @@
---
title: "Provider Reference"
version: 3.8.51
lastUpdated: 2026-08-26
lastUpdated: 2026-08-27
---
# Provider Reference
> **Auto-generated** from `src/shared/constants/providers.ts` — do not edit by hand.
> Regenerate with: `npm run gen:provider-reference`
> **Last generated:** 2026-08-26
> **Last generated:** 2026-08-27
Total providers: **354**. See category breakdown below.
Total providers: **357**. See category breakdown below.
## Categories
@@ -122,7 +122,7 @@ Use the dashboard at `/dashboard/providers` to enable, configure, and test each
| `zai-web` | `zw` | Z.ai Web | Web cookie | [link](https://chat.z.ai) | Copy the "token" value from chat.z.ai → DevTools → Application → Local Storage. Do not copy cookies; OmniRoute handles the per-request CAPTCHA through its browser transport. | — |
| `zenmux-free` | `zmf` | ZenMux Free (Web) | Web cookie | [link](https://zenmux.ai) | Login at zenmux.ai, then export all cookies using EditThisCookie or Cookie-Editor and paste the full Cookie header string here. Refresh every ~30 days. | — |
## API Key Providers (paid / paid-with-free-credits) (234)
## API Key Providers (paid / paid-with-free-credits) (235)
| ID | Alias | Name | Tags | Website | Notes |
|----|-------|------|------|---------|-------|
@@ -277,6 +277,7 @@ Use the dashboard at `/dashboard/providers` to enable, configure, and test each
| `oci` | `oci` | OCI Generative AI | API key, enterprise | [link](https://www.oracle.com/artificial-intelligence/generative-ai) | Use your OCI Generative AI API key or IAM bearer token. Base URL can be https://inference.generativeai.<region>.oci.oraclecloud.com/openai/v1/. |
| `ofoxai` | `ofoxai` | OfoxAI | API key, aggregator | [link](https://ofox.ai) | The current catalog advertises 10+ free models without a public numeric quota; review upstream provenance, retention and training terms before production use. |
| `ollama-cloud` | `ollamacloud` | Ollama Cloud | API key | [link](https://ollama.com/settings/keys) | — |
| `oneminai` | `1min` | 1min.AI | API key | [link](https://1min.ai) | Create an API key at https://docs.1min.ai/docs/api/create-api-key, then paste it here. |
| `openadapter` | `oad` | OpenAdapter | API key | [link](https://openadapter.dev) | Use your OpenAdapter API key in Authorization: Bearer sk-cv-<key>. Fully OpenAI-compatible. API base URL: https://api.openadapter.in/v1. |
| `openai` | `openai` | OpenAI | API key | [link](https://platform.openai.com) | — |
| `opencode-go` | `opencode-go` | OpenCode Go | API key | [link](https://opencode.ai/go) | — |
@@ -380,10 +381,11 @@ Use the dashboard at `/dashboard/providers` to enable, configure, and test each
| `vllm` | `vllm` | vLLM | Local, self-hosted | [link](https://github.com/vllm-project/vllm) | API key optional. Configure the local vLLM OpenAI-compatible base URL (default: http://localhost:8000/v1). |
| `xinference` | `xinference` | XInference | Local, self-hosted | [link](https://inference.readthedocs.io) | API key optional. Configure the local XInference OpenAI-compatible base URL (default: http://localhost:9997/v1). |
## Search Providers (16)
## Search Providers (17)
| ID | Alias | Name | Tags | Website | Notes |
|----|-------|------|------|---------|-------|
| `anysearch-search` | `anysearch` | AnySearch | Search | [link](https://anysearch.com) | Optional API key from anysearch.com (as_sk_...) - free 1000/day; keyless tier has lower limits |
| `brave-search` | `brave-search` | Brave Search | Search | [link](https://brave.com/search/api) | Subscription token from Brave Search API dashboard |
| `context7` | `context7` | Context7 (library docs) | Search | [link](https://context7.com) | API key optional (ctx7sk-...) — anonymous tier works without a key; a key raises the rate limit |
| `exa-search` | `exa-search` | Exa Search | Search | [link](https://exa.ai) | API key from dashboard.exa.ai |
@@ -443,7 +445,7 @@ Use the dashboard at `/dashboard/providers` to enable, configure, and test each
- Catalog: [`src/shared/constants/providers.ts`](../../src/shared/constants/providers.ts)
- Registry (per-model details): [`open-sse/config/providerRegistry.ts`](../../open-sse/config/providerRegistry.ts)
- Executors: [`open-sse/executors/`](../../open-sse/executors/) (110 implementations)
- Executors: [`open-sse/executors/`](../../open-sse/executors/) (112 implementations)
- Translators: [`open-sse/translator/`](../../open-sse/translator/)
## See Also

View File

@@ -1,13 +1,13 @@
---
title: "Guardrails"
version: 3.8.50
lastUpdated: 2026-08-24
version: 3.8.51
lastUpdated: 2026-08-26
---
# Guardrails
> **Source of truth:** `src/lib/guardrails/`
> **Last updated:** 2026-08-24 — v3.8.50 (Video Bridge visual dedup hardening + focused captions)
> **Last updated:** 2026-08-26 — v3.8.51 (Video Bridge transcript-retention boundary)
Guardrails enforce safety, policy, and content transformations at the boundary
between OmniRoute and upstream providers. Each guardrail can inspect (and
@@ -439,6 +439,61 @@ are rendered as untrusted observations alongside the frame captions. Invalid,
out-of-range, or provenance-free text is rejected rather than mixed into the
caption stream.
#### Transcript retention boundary
Transcript text remains available to the live bridge and upstream request, but it is not retained
by OmniRoute's logging and memory surfaces. `videoTranscriptLogRedaction.ts` recognizes
`transcript` and `audioTranscript` only inside supported video carriers. A field with either name
in an ordinary tool argument or application object is preserved, and delimiter-shaped caller
prose is not trusted as a bridge result.
When the Video Bridge produces a description containing validated cues, it emits only a
SHA-256/length identity in guardrail metadata. The request pipeline accepts those identities only
from a successful, payload-modifying `video-bridge` result and uses them to omit the exact generated
description segment after translation or concatenation. Raw transcript text is never placed in the
metadata.
The retention policy covers raw, converted, and provider request logs; provider and client response
bodies; detailed pipeline artifacts; call logs, active/pending usage, rejected requests, proxy/error
diagnostics, SSE chunks, and Memory extraction. Response bodies and stream chunks for a sensitive
request are omitted because an upstream may echo request text. Safe operational metadata such as
status, timing, provider, model, headers-presence, token counts, and the fact that redaction occurred
remains available. The constant retained marker is `[omitted: video transcript]`.
Sensitivity is resolved before the guardrail chain from the original client body and resolved again
after the chain from the original body, processed body, and trusted description identities. A
guardrail that removes or replaces the raw carrier therefore cannot clear the request-scoped bit.
Explicit video parts remain sensitive when malformed, and nested carrier objects are inspected under
the same bounds. Rejected-request persistence also inspects the body itself, so forgetting to pass the
bit at one caller does not expose a raw carrier.
The request-scoped bit protects OmniRoute-owned application paths in addition to structured payload
clones. Native priority, round-robin, pinned, and fusion diagnostics; quality-rejection and live-event
logs; terminal combo errors; proxy fast-fail logs; guardrail-registry logs; plugin-dispatcher failure
logs; and stream lifecycle callbacks retain only the constant marker when their detail could echo the
request. Transcript-sensitive requests do not generate Context Relay or Universal Handoff summaries,
and Memory extraction is skipped. Daily-quota routing state uses the server-resolved model rather than
promoting a model token parsed from transcript-sensitive upstream text. These rules affect retention,
not the live request or the functional response returned to the same client.
Inspection is bounded by depth, aggregate entries, trusted identities, description-prefix
occurrences, candidate hashes, and total hashed text. Cycles and binary views are handled without
retaining their contents. If a bound is exceeded, or an enumerable getter/proxy throws during
inspection, the retained copy fails closed to the omission marker; the live request is not changed.
Privacy-redacted Responses artifacts cannot safely reconstruct complete `previous_response_id`
history. `responsesContinuationStore.ts` therefore rejects an artifact carrying the trusted
pipeline-level redaction marker and asks the client to resend full history instead of replaying a
silently incomplete conversation.
Custom guardrails and plugins are privileged, in-process processors: they intentionally receive the
live payload so they can inspect, transform, or block it. OmniRoute supplies the server-owned
`videoTranscriptSensitive` bit, wraps `GuardrailContext.log`, and protects errors emitted by its native
plugin dispatcher. It cannot control a third-party processor that independently writes the live body
to `console`, a file, a database, or the network. Operators must audit such code and treat its own
sinks as outside the OmniRoute-owned retention boundary; clearing or ignoring the bit does not make
the transcript safe to persist.
An advanced caller may provide an already-authorized `audioTranscript` track
for the same video. The fusion seam runs visual and audio observations under
one deadline and abort signal, orders them on a common timeline, collapses

View File

@@ -1,6 +1,6 @@
# OmniRoute
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 354 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 357 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -277,7 +277,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **354 AI providers** with automatic format translation
- **357 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free
@@ -475,7 +475,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
## v3.8.x Highlights
- **354-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **357-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
- **MCP server expanded to 110 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)

View File

@@ -370,6 +370,26 @@ export const SEARCH_PROVIDERS: Record<string, SearchProviderConfig> = {
cacheTTLMs: 5 * 60 * 1000,
fallbackOnly: true,
},
// Free public web search for AI agents (https://anysearch.com). fallback-only:
// a cost-0 provider never overrides configured paid providers in automatic
// selection. max_results is capped at 10 upstream.
"anysearch-search": {
id: "anysearch-search",
name: "AnySearch",
baseUrl: "https://api.anysearch.com/v1/search",
method: "POST",
authType: "apikey",
authHeader: "bearer",
costPerQuery: 0,
freeMonthlyQuota: 0, // free tier is 1000 req/day (daily reset, not monthly) — 0 matches the xquik convention; the daily figure lives in the UI catalog authHint
searchTypes: ["web"],
defaultMaxResults: 5,
maxMaxResults: 10,
timeoutMs: 10_000,
cacheTTLMs: 5 * 60 * 1000,
fallbackOnly: true,
},
};
/**
@@ -419,6 +439,8 @@ export const SEARCH_PROVIDER_ALIASES: Record<string, string> = {
x: "x-search",
xquik: "xquik-search",
xquik_search: "xquik-search",
anysearch: "anysearch-search",
anysearch_search: "anysearch-search",
};
export function resolveSearchProviderId(providerId: string): string {

View File

@@ -0,0 +1,109 @@
/**
* AnySearch Web Fetch Executor
*
* Fetches readable content from a URL using the AnySearch Extract API.
* POST https://api.anysearch.com/v1/extract
*
* Free tier: 1000 requests/day per key, shared with /v1/search. Bearer auth
* is optional upstream - keyless calls use the lower anonymous tier. Routing
* stays key-gated; anonymity only applies at call time.
* Docs: https://anysearch.com/docs
*/
import { sanitizeErrorMessage, buildErrorBody } from "../utils/error.ts";
import type { WebFetchResult, WebFetchFormat, WebFetchCredentials } from "../handlers/webFetch.ts";
const ANYSEARCH_EXTRACT_URL = "https://api.anysearch.com/v1/extract";
const ANYSEARCH_TIMEOUT_MS = 30_000;
interface AnysearchFetchOptions {
url: string;
format: WebFetchFormat;
includeMetadata: boolean;
credentials: WebFetchCredentials;
}
/**
* Execute an AnySearch extract request.
* The upstream contract is strict JSON: a single { url } object with no
* unknown fields, capped at 16 KiB - do not add request fields here.
*/
export async function anysearchFetch(opts: AnysearchFetchOptions): Promise<WebFetchResult> {
// format is accepted but unused: AnySearch extract always returns markdown-ish text
// (mirroring the context7 pattern of accepting the field without rejecting).
const { url, includeMetadata, credentials } = opts;
const controller = new AbortController();
const timeoutId = setTimeout(() => {
const err = new Error(`anysearch-fetch timeout after ${ANYSEARCH_TIMEOUT_MS}ms`);
err.name = "TimeoutError";
controller.abort(err);
}, ANYSEARCH_TIMEOUT_MS);
try {
const response = await fetch(ANYSEARCH_EXTRACT_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
...(credentials.apiKey ? { Authorization: `Bearer ${credentials.apiKey}` } : {}),
},
body: JSON.stringify({ url }),
signal: controller.signal,
});
if (!response.ok) {
const rawError = await response.text().catch(() => `HTTP ${response.status}`);
const msg = sanitizeErrorMessage(`AnySearch error ${response.status}: ${rawError}`);
const body = buildErrorBody(response.status, msg);
return { success: false, status: response.status, error: body.error.message };
}
const data = (await response.json()) as Record<string, unknown>;
// Envelope: { code, message, data: { url, title, content } } - tolerate the
// enveloped and flat shapes before giving up.
const envelope =
data.data && typeof data.data === "object" && !Array.isArray(data.data)
? (data.data as Record<string, unknown>)
: data;
const code = typeof data.code === "number" ? data.code : 0;
if (code !== 0) {
const errorMsg = String(data.error_code ?? data.message ?? code);
// Quota-shaped envelope errors map to 402 (failover-eligible), mirroring
// the search-side AnysearchSearchEnvelopeError → 402 pattern in anysearchSearch.ts.
const isQuota = /quota|exceed|limit|balance|credit|exhaust/i.test(errorMsg);
const status = isQuota ? 402 : 422;
const msg = sanitizeErrorMessage(`AnySearch extract failed: ${errorMsg}`);
const body = buildErrorBody(status, msg);
return { success: false, status, error: body.error.message };
}
const content = String(envelope.content ?? "");
const title = envelope.title != null ? String(envelope.title) : null;
const metadata = includeMetadata ? { title, description: null } : null;
return {
success: true,
data: {
provider: "anysearch-search",
url,
content,
links: [],
metadata,
screenshot_url: null,
},
};
} catch (err: unknown) {
if (err instanceof Error && err.name === "AbortError") {
const body = buildErrorBody(504, "AnySearch request timed out");
return { success: false, status: 504, error: body.error.message };
}
const msg =
err instanceof Error ? sanitizeErrorMessage(err.message) : sanitizeErrorMessage(String(err));
const body = buildErrorBody(502, msg);
return { success: false, status: 502, error: body.error.message };
} finally {
clearTimeout(timeoutId);
}
}

View File

@@ -1,5 +1,6 @@
import { HTTP_STATUS, FETCH_TIMEOUT_MS } from "../config/constants.ts";
import { getRegistryEntry } from "../config/providerRegistry.ts";
import { resolveFetchStartTimeout } from "../utils/fetchStartTimeoutPolicy.ts";
import {
resolveAlternateFormat,
type AlternateFormat,
@@ -201,6 +202,10 @@ export type ExecuteInput = {
* this to apply client-format-aware policies such as `</think>` close-marker
* suppression. */
clientResponseFormat?: string | null;
/** True when upstream diagnostics may echo a video transcript. Executors must
* preserve operational responses/errors while omitting those echoes from
* retained logs. */
videoTranscriptSensitive?: boolean;
/** Callback to persist tokens that are proactively refreshed during execution.
* Accepts a partial credentials patch (e.g. `{ accessToken, refreshToken }` or
* `{ testStatus: "expired", isActive: false }`); the caller merges into the
@@ -902,9 +907,24 @@ export class BaseExecutor {
clampNestedThinkingBudget(transformedBody, thinkingBudgetClampedMax);
}
// Timeout only covers response start; stream stalls are handled downstream.
// #11526: streaming requests cap the headers-wait phase to a client-realistic
// ceiling (see fetchStartTimeoutPolicy.ts) — non-streaming keeps the flat default.
// Declared outside the try/catch below so the catch's TIMEOUT log (on the
// error path) reports the same effective value the fetch actually used.
const fetchStartTimeoutPolicy = resolveFetchStartTimeout({
baseTimeoutMs: this.getTimeoutMs(),
stream,
});
const fetchStartTimeoutMs = fetchStartTimeoutPolicy.timeoutMs;
if (fetchStartTimeoutPolicy.capped) {
log?.debug?.(
"TIMEOUT",
`fetch-start timeout capped ${fetchStartTimeoutPolicy.baseTimeoutMs}ms -> ${fetchStartTimeoutMs}ms (streaming)`
);
}
try {
// Timeout only covers response start; stream stalls are handled downstream.
const fetchStartTimeoutMs = this.getTimeoutMs();
const fetchWithStartTimeout = async (requestUrl: string, requestOptions: RequestInit) => {
// GHSA-4f49: guard here (not only next to the first buildUrl) so retries
// and fallback URLs are validated too, before any bytes leave the host.
@@ -1713,7 +1733,7 @@ export class BaseExecutor {
// Distinguish timeout errors from other abort errors
const err = error instanceof Error ? error : new Error(String(error));
if (err.name === "TimeoutError") {
log?.warn?.("TIMEOUT", `Fetch timeout after ${this.getTimeoutMs()}ms on ${url}`);
log?.warn?.("TIMEOUT", `Fetch timeout after ${fetchStartTimeoutMs}ms on ${url}`);
}
lastError = err;
if (!skipUpstreamRetry && urlIndex + 1 < fallbackCount) {

View File

@@ -16,6 +16,7 @@ import { prepareToolMessages, buildToolAwareResult } from "../translator/webTool
import type { Session } from "../services/sessionPool/session.ts";
import { tryBackedChat } from "../services/browserBackedChat.ts";
import { sanitizeErrorMessage } from "../utils/error.ts";
import { normalizeSystemRole } from "../services/roleNormalizer.ts";
// Issue #6999: Lightweight circuit breaker for the DuckDuckGo executor.
// After CB_THRESHOLD consecutive failures (429, 5xx, or network errors),
@@ -559,8 +560,17 @@ export class DuckDuckGoWebExecutor extends BaseExecutor {
}
}
// #ddgw defense-in-depth: duckchat/v1/chat accepts only user/assistant roles.
// Normalize after catalog resolution so the effective upstream model is used.
// This also shields the system tool prompt injected by prepareToolMessages.
const normalizedMessages = normalizeSystemRole(
messages,
"duckduckgo-web",
upstreamModel
) as typeof messages;
const sendChat = async (vqdHeaders: DuckDuckGoAuthHeaders): Promise<Response> => {
const payload = buildDuckDuckGoPayload(upstreamModel, messages);
const payload = buildDuckDuckGoPayload(upstreamModel, normalizedMessages);
const response = await fetch(CHAT_URL, {
method: "POST",
headers: mergeHeadersCaseInsensitive(
@@ -786,10 +796,7 @@ export class DuckDuckGoWebExecutor extends BaseExecutor {
try {
return {
vqd4: retry.vqd4,
vqdHash1: await solveDuckDuckGoChallenge(
retry.vqdHash1,
FAKE_HEADERS["User-Agent"]
),
vqdHash1: await solveDuckDuckGoChallenge(retry.vqdHash1, FAKE_HEADERS["User-Agent"]),
status: retry.status,
retryAfter: retry.retryAfter,
};

View File

@@ -1,4 +1,5 @@
import { randomUUID } from "node:crypto";
import { redactVideoTranscriptSensitiveText } from "../../src/lib/guardrails/videoTranscriptLogRedaction.ts";
import type { KeyHealth } from "../services/apiKeyRotator.ts";
import { DefaultExecutor } from "./default.ts";
@@ -45,6 +46,11 @@ function asRecord(value: unknown): JsonRecord | null {
return value && typeof value === "object" && !Array.isArray(value) ? (value as JsonRecord) : null;
}
function retainGlmDiagnostic(error: unknown, input: ExecuteInput): string {
const message = error instanceof Error ? error.message : String(error);
return redactVideoTranscriptSensitiveText(message, input.videoTranscriptSensitive === true);
}
function getEffectiveKey(credentials: ProviderCredentials): string {
const extraKeys = (credentials.providerSpecificData?.extraApiKeys as string[] | undefined) ?? [];
if (credentials.apiKey && credentials.connectionId && extraKeys.length > 0) {
@@ -465,6 +471,7 @@ export class GlmExecutor extends DefaultExecutor {
timeoutMs: STREAM_READINESS_TIMEOUT_MS,
provider: this.provider,
model: input.model,
redactUpstreamDiagnosticForLog: input.videoTranscriptSensitive === true,
log: input.log,
});
response = readiness.response;
@@ -559,7 +566,7 @@ export class GlmExecutor extends DefaultExecutor {
if (!isRetryableGlmFallbackError(error)) throw error;
input.log?.debug?.(
"GLM_FALLBACK",
`${primaryTransport} error (${error instanceof Error ? error.message : String(error)}); trying ${fallbackTransport}`
`${primaryTransport} error (${retainGlmDiagnostic(error, input)}); trying ${fallbackTransport}`
);
}
@@ -572,7 +579,7 @@ export class GlmExecutor extends DefaultExecutor {
if (!primaryResult) throw error;
input.log?.debug?.(
"GLM_FALLBACK",
`${fallbackTransport} fallback failed (${error instanceof Error ? error.message : String(error)}); returning primary response`
`${fallbackTransport} fallback failed (${retainGlmDiagnostic(error, input)}); returning primary response`
);
}

View File

@@ -166,6 +166,10 @@ import {
runWithCasGuard,
} from "../services/tokenRefresh.ts";
import { createRequestLogger } from "../utils/requestLogger.ts";
import {
redactVideoTranscriptSensitiveText,
resolveVideoTranscriptLogSensitivity,
} from "@/lib/guardrails/videoTranscriptLogRedaction";
import { createPreparedRequestLogger, runWithCapture } from "../utils/providerRequestLogging.ts";
import { summarizeToolSources } from "../utils/toolSources.ts";
import { applyResponsesPreviousResponseIdPolicy } from "../utils/responsesStatePolicy.ts";
@@ -524,7 +528,21 @@ export async function handleChatCore({
skipResourcePressureGuard = false,
reasoningTransportFallback = "drop",
managedLease = null,
videoTranscriptSensitive = false,
videoTranscriptDescriptionFingerprints = [],
}) {
videoTranscriptSensitive =
videoTranscriptSensitive ||
resolveVideoTranscriptLogSensitivity({
rawRequestBody: clientRawRequest?.body,
processedBody: body,
trustedDescriptionFingerprints: videoTranscriptDescriptionFingerprints,
});
const retainedErrorTextForLog = (error: unknown): string =>
redactVideoTranscriptSensitiveText(
error instanceof Error ? error.message : String(error),
videoTranscriptSensitive
);
let { provider, model, extendedContext } = modelInfo;
const resilienceSettings = resolveResilienceSettings(cachedSettings);
if (!skipResourcePressureGuard) {
@@ -637,6 +655,7 @@ export async function handleChatCore({
apiKeyInfo,
headers: clientRawRequest?.headers,
log,
videoTranscriptSensitive,
});
if (pluginGate.blocked === true) {
return {
@@ -721,6 +740,7 @@ export async function handleChatCore({
effectiveServiceTier,
startTime,
log,
videoTranscriptSensitive,
});
if (idempotencyHit) {
return idempotencyHit;
@@ -902,6 +922,8 @@ export async function handleChatCore({
stage: "registered",
correlationId,
sessionTag: conversationId || null,
videoTranscriptSensitive,
videoTranscriptDescriptionFingerprints,
}) || generateRequestId();
// Initialize rate limit settings from persisted DB (once, lazy)
@@ -1034,6 +1056,8 @@ export async function handleChatCore({
noLogEnabled,
correlationId,
modelPinned,
videoTranscriptSensitive,
videoTranscriptDescriptionFingerprints,
// Resolved conversationId (open-sse/services/conversationTracker.ts) wins when
// present — it's populated for every request now, not just ones where the
// client explicitly sent x-omniroute-session-id. The raw header remains a
@@ -1156,8 +1180,17 @@ export async function handleChatCore({
model,
provider: provider || undefined,
connectionId: connectionId || credentials?.connectionId || undefined,
videoTranscriptSensitive,
videoTranscriptDescriptionFingerprints,
});
const pendingScope = { id: pendingRequestId, model, provider, connectionId: pendingConnId };
const pendingScope = {
id: pendingRequestId,
model,
provider,
connectionId: pendingConnId,
videoTranscriptSensitive,
videoTranscriptDescriptionFingerprints,
};
const providerRequestCapture = createPreparedRequestLogger(reqLogger, pendingScope);
// 0. Log client raw request (before format conversion)
if (clientRawRequest) {
@@ -1203,6 +1236,7 @@ export async function handleChatCore({
apiKeyId: apiKeyInfo?.id ?? undefined,
cacheDefaultMode: (apiKeyInfo as { cacheDefaultMode?: "legacy" | "bypass" } | null)
?.cacheDefaultMode,
videoTranscriptSensitive,
});
if (cacheHit) {
return cacheHit;
@@ -1482,8 +1516,7 @@ export async function handleChatCore({
} catch (err) {
log?.debug?.(
"COMPRESSION",
"Combo compression override lookup skipped: " +
(err instanceof Error ? err.message : String(err))
"Combo compression override lookup skipped: " + retainedErrorTextForLog(err)
);
}
}
@@ -1492,10 +1525,7 @@ export async function handleChatCore({
const { listCompressionCombos } = await import("../../src/lib/db/compressionCombos.ts");
namedCombos = buildNamedComboLookup(listCompressionCombos());
} catch (err) {
log?.debug?.(
"COMPRESSION",
"Named combos load skipped: " + (err instanceof Error ? err.message : String(err))
);
log?.debug?.("COMPRESSION", "Named combos load skipped: " + retainedErrorTextForLog(err));
}
// Phase 3: per-request override. Unknown values fall through in the resolver (never error).
const compressionHeader = resolveCompressionHeader(clientRawRequest?.headers ?? null);
@@ -1543,8 +1573,7 @@ export async function handleChatCore({
} catch (err) {
log?.debug?.(
"COMPRESSION",
"Default compression combo lookup skipped: " +
(err instanceof Error ? err.message : String(err))
"Default compression combo lookup skipped: " + retainedErrorTextForLog(err)
);
}
}
@@ -1586,10 +1615,7 @@ export async function handleChatCore({
}
}
} catch (err) {
log?.debug?.(
"COMPRESSION",
"Output styles skipped: " + (err instanceof Error ? err.message : String(err))
);
log?.debug?.("COMPRESSION", "Output styles skipped: " + retainedErrorTextForLog(err));
}
}
const compressionInputBody = body as Record<string, unknown>;
@@ -1899,8 +1925,7 @@ export async function handleChatCore({
} catch (err) {
log?.warn?.(
"COMPRESSION",
"Compression pipeline error (non-fatal): " +
(err instanceof Error ? err.message : String(err))
"Compression pipeline error (non-fatal): " + retainedErrorTextForLog(err)
);
}
// --- End Modular Compression Pipeline ---
@@ -1954,7 +1979,10 @@ export async function handleChatCore({
`Combo context limit: ${resolved.limit} (source=${resolved.source})`
);
} catch (err) {
log?.warn?.("CONTEXT", "Failed to resolve combo limits for compression: " + err);
log?.warn?.(
"CONTEXT",
"Failed to resolve combo limits for compression: " + retainedErrorTextForLog(err)
);
}
}
@@ -2432,13 +2460,21 @@ export async function handleChatCore({
try {
const { runOnError } = await import("@/lib/plugins/hooks");
await runOnError(
{ requestId: traceId, body, model, provider, apiKeyInfo, metadata: {} },
{
requestId: traceId,
body,
model,
provider,
apiKeyInfo,
metadata: {},
videoTranscriptSensitive,
},
error instanceof Error ? error : new Error(String(error))
);
} catch (pluginErr) {
log?.debug?.(
"PLUGIN",
`onError hook error (non-fatal): ${pluginErr instanceof Error ? pluginErr.message : String(pluginErr)}`
`onError hook error (non-fatal): ${retainedErrorTextForLog(pluginErr)}`
);
}
@@ -2450,7 +2486,13 @@ export async function handleChatCore({
const message = error?.message || "Invalid request";
const errorType = typeof error?.errorType === "string" ? error.errorType : null;
log?.warn?.("TRANSLATE", `Request translation failed: ${message}`);
log?.warn?.(
"TRANSLATE",
`Request translation failed: ${redactVideoTranscriptSensitiveText(
message,
videoTranscriptSensitive
)}`
);
if (errorType) {
trackPendingRequest(model, provider, connectionId, false);
@@ -2544,8 +2586,7 @@ export async function handleChatCore({
// must never turn an otherwise valid translated request into a 500.
log?.warn?.(
"COMPRESSION",
"Post-translation OmniGlyph skipped: " +
(error instanceof Error ? error.message : String(error))
"Post-translation OmniGlyph skipped: " + retainedErrorTextForLog(error)
);
}
}
@@ -2861,7 +2902,7 @@ export async function handleChatCore({
}).catch((err: unknown): EnforceDecision => {
log?.warn?.(
"QUOTA_SHARE",
`enforceQuotaShare failed; fail-open: ${err instanceof Error ? err.message : String(err)}`
`enforceQuotaShare failed; fail-open: ${retainedErrorTextForLog(err)}`
);
return { kind: "allow" as const };
});
@@ -2903,7 +2944,7 @@ export async function handleChatCore({
// Outer fail-open guard — should not be reached (inner .catch covers it)
log?.warn?.(
"QUOTA_SHARE",
`[quotaShare] enforceQuotaShare unexpected error; fail-open: ${err instanceof Error ? err.message : String(err)}`
`[quotaShare] enforceQuotaShare unexpected error; fail-open: ${retainedErrorTextForLog(err)}`
);
}
}
@@ -2915,7 +2956,7 @@ export async function handleChatCore({
} catch (err) {
log?.warn?.(
"QUOTA_SHARE",
`[quotaShare] could not set soft penalty on candidate: ${err instanceof Error ? err.message : String(err)}`
`[quotaShare] could not set soft penalty on candidate: ${retainedErrorTextForLog(err)}`
);
}
}
@@ -2949,6 +2990,8 @@ export async function handleChatCore({
let onPipelineStreamError: streamFailure.PipelineStreamErrorHandler | null = null;
let onClientDisconnectFinalize:
((event: { reason: string; duration: number }) => boolean) | null = null;
const redactStreamDiagnosticsForLog =
videoTranscriptSensitive || reqLogger.isVideoTranscriptSensitive();
// Create stream controller for disconnect detection
const streamController = createStreamController({
@@ -2980,11 +3023,15 @@ export async function handleChatCore({
clientAbortSignal: clientRawRequest?.signal,
allowCompletedToolHandoffGrace: isCodexResponsesEcho,
clientDisconnectGracePeriodMs: STREAM_DISCONNECT_GRACE_PERIOD_MS,
redactStreamDiagnosticsForLog,
});
const dedupRequestBody = { ...translatedBody, model: `${provider}/${model}`, stream };
const dedupEnabled = shouldDeduplicate(dedupRequestBody);
const dedupHash = dedupEnabled ? computeRequestHash(dedupRequestBody) : null;
// Namespaced by the calling API key: dedup hands the SAME response object to
// every joiner, so a shared hash across keys is a cross-principal response
// leak (GHSA-6c7w-56xp-wpc6).
const dedupHash = dedupEnabled ? computeRequestHash(dedupRequestBody, apiKeyInfo?.id) : null;
const executeProviderRequest = async (modelToCall = effectiveModel, allowDedup = false) => {
const execute = async () => {
@@ -3126,6 +3173,7 @@ export async function handleChatCore({
userAgent
),
clientResponseFormat,
videoTranscriptSensitive,
onCredentialsRefreshed,
skipUpstreamRetry,
contextEditing: { enabled: contextEditingEnabled },
@@ -3160,7 +3208,7 @@ export async function handleChatCore({
invalidateCodexQuotaCache(String(attemptConnectionId));
}
} catch (err) {
const errMessage = err instanceof Error ? err.message : String(err);
const errMessage = retainedErrorTextForLog(err);
log?.debug?.("CODEX", `Failed to persist codex quota state: ${errMessage}`);
}
}
@@ -3442,6 +3490,7 @@ export async function handleChatCore({
userAgent
),
clientResponseFormat,
videoTranscriptSensitive,
onCredentialsRefreshed,
skipUpstreamRetry,
contextEditing: { enabled: contextEditingEnabled },
@@ -3674,7 +3723,9 @@ export async function handleChatCore({
} catch (err) {
// Fail-open at Tier 2: Tier 1 already enforced the model/global limit pre-dispatch.
// A transient counter read error here must not break an otherwise-valid request.
log?.warn?.("TOKEN_LIMIT", "Tier 2 token-limit check failed; allowing request", { err });
log?.warn?.("TOKEN_LIMIT", "Tier 2 token-limit check failed; allowing request", {
error: retainedErrorTextForLog(err),
});
}
}
@@ -3693,7 +3744,9 @@ export async function handleChatCore({
);
}
} catch (err) {
log?.warn?.("GEMINI_RATE_LIMIT", "Pre-dispatch TPM check failed; allowing request", { err });
log?.warn?.("GEMINI_RATE_LIMIT", "Pre-dispatch TPM check failed; allowing request", {
error: retainedErrorTextForLog(err),
});
}
}
@@ -3843,7 +3896,12 @@ export async function handleChatCore({
failureStatus,
upstreamErrorCode || (error instanceof Error && error.name ? error.name : "upstream_error")
);
console.log(`${COLORS.red}[ERROR] ${failureMessage}${COLORS.reset}`);
console.log(
`${COLORS.red}[ERROR] ${redactVideoTranscriptSensitiveText(
failureMessage,
videoTranscriptSensitive
)}${COLORS.reset}`
);
if (stream && upstreamErrorCode) {
const result = createStreamingErrorResult(
failureStatus,
@@ -3980,6 +4038,7 @@ export async function handleChatCore({
upstreamExtraHeaders: buildUpstreamHeadersForExecute(retryModelId),
clientHeaders: buildExecutorClientHeaders(clientRawRequest?.headers, userAgent),
clientResponseFormat,
videoTranscriptSensitive,
onCredentialsRefreshed,
skipUpstreamRetry: isCombo,
contextEditing: { enabled: contextEditingEnabled },
@@ -4009,9 +4068,13 @@ export async function handleChatCore({
// executor throw). Don't swallow — the operator-visible signal "the user
// saw 401 even though auth was actually fixed" is much more confusing
// than the original 401 alone. Surface at error level with sanitization.
const retainedRetryError = redactVideoTranscriptSensitiveText(
sanitizeErrorMessage(retryErr),
videoTranscriptSensitive
);
log?.error?.(
"TOKEN",
`${provider?.toUpperCase()} | retry after refresh failed: ${sanitizeErrorMessage(retryErr)}`
`${provider?.toUpperCase()} | retry after refresh failed: ${retainedRetryError}`
);
}
} else {
@@ -4128,6 +4191,11 @@ export async function handleChatCore({
if (signatureRecovery.succeeded) break providerFailure;
const retainedProviderMessage = redactVideoTranscriptSensitiveText(
message,
videoTranscriptSensitive
);
// #10281 — tiny-budget reasoning probes (e.g. Claude Code's `/model` check
// sends `max_tokens: 1`): the model burns the whole budget on thinking, and
// some upstreams (e.g. api.cline.bot for deepseek-v4-flash) answer the empty
@@ -4150,7 +4218,7 @@ export async function handleChatCore({
});
log?.warn?.(
"PROBE",
`Reasoning probe (max_tokens < ${REASONING_BUFFER_MIN_TRIGGER}) answered with truncated 200 — upstream reported "${message}"`
`Reasoning probe (max_tokens < ${REASONING_BUFFER_MIN_TRIGGER}) answered with truncated 200 — upstream reported "${retainedProviderMessage}"`
);
break providerFailure;
}
@@ -4179,7 +4247,7 @@ export async function handleChatCore({
{
testStatus: "banned",
isActive: false,
lastError: message,
lastError: retainedProviderMessage,
lastErrorType: errorType,
errorCode: String(statusCode),
},
@@ -4210,7 +4278,7 @@ export async function handleChatCore({
) {
await updateProviderConnection(errorConnectionId, {
lastErrorType: errorType,
lastError: message,
lastError: retainedProviderMessage,
errorCode: statusCode,
});
console.warn(
@@ -4223,7 +4291,7 @@ export async function handleChatCore({
{
testStatus: "deactivated",
isActive: false,
lastError: message,
lastError: retainedProviderMessage,
lastErrorType: errorType,
errorCode: String(statusCode),
},
@@ -4247,7 +4315,7 @@ export async function handleChatCore({
errorConnectionId,
{
testStatus: "credits_exhausted",
lastError: message,
lastError: retainedProviderMessage,
lastErrorType: errorType,
errorCode: String(statusCode),
},
@@ -4295,7 +4363,7 @@ export async function handleChatCore({
rateLimitedUntil: kimiRateLimitResetAt,
backoffLevel: 0,
lastErrorType: PROVIDER_ERROR_TYPES.RATE_LIMITED,
lastError: message,
lastError: retainedProviderMessage,
errorCode: statusCode,
});
console.warn(
@@ -4325,7 +4393,7 @@ export async function handleChatCore({
errorConnectionId,
{
testStatus: "credits_exhausted",
lastError: message,
lastError: retainedProviderMessage,
lastErrorType: errorType,
errorCode: String(statusCode),
},
@@ -4341,14 +4409,14 @@ export async function handleChatCore({
// Normal 401 (token/session auth issue): keep account active for refresh/re-auth.
await updateProviderConnection(errorConnectionId, {
lastErrorType: errorType,
lastError: message,
lastError: retainedProviderMessage,
errorCode: statusCode,
});
} else if (errorType === PROVIDER_ERROR_TYPES.OAUTH_INVALID_TOKEN) {
// OAuth 401 with invalid credentials - token refresh can recover
await updateProviderConnection(errorConnectionId, {
lastErrorType: errorType,
lastError: message,
lastError: retainedProviderMessage,
errorCode: statusCode,
});
console.warn(
@@ -4358,7 +4426,7 @@ export async function handleChatCore({
// Cloud Code 403 with stale project: not a ban, keep account active.
await updateProviderConnection(errorConnectionId, {
lastErrorType: errorType,
lastError: message,
lastError: retainedProviderMessage,
errorCode: statusCode,
});
console.warn(
@@ -4374,7 +4442,7 @@ export async function handleChatCore({
const geoCooldownMs = COOLDOWN_MS.geoBlocked ?? 24 * 60 * 60 * 1000;
await updateProviderConnection(errorConnectionId, {
lastErrorType: errorType,
lastError: message,
lastError: retainedProviderMessage,
errorCode: statusCode,
});
// T-PROBE: the 24h exclusion is a routing mutation — a probe must
@@ -4399,7 +4467,7 @@ export async function handleChatCore({
const byopCooldownMs = COOLDOWN_MS.gcpProjectRequired ?? 24 * 60 * 60 * 1000;
await updateProviderConnection(errorConnectionId, {
lastErrorType: errorType,
lastError: message,
lastError: retainedProviderMessage,
errorCode: statusCode,
});
try {
@@ -4445,7 +4513,13 @@ export async function handleChatCore({
}).catch(() => {});
const errMsg = formatProviderError(new Error(message), provider, model, statusCode);
console.log(`${COLORS.red}[ERROR] ${errMsg}${COLORS.reset}`);
const retainedErrMsg = formatProviderError(
new Error(retainedProviderMessage),
provider,
model,
statusCode
);
console.log(`${COLORS.red}[ERROR] ${retainedErrMsg}${COLORS.reset}`);
// Log Antigravity retry time if available
if (retryAfterMs && provider === "antigravity") {
@@ -4772,12 +4846,11 @@ export async function handleChatCore({
}
}
} catch (retryErr) {
log?.warn?.(
"RETRY",
`clinepass retry failed: ${
retryErr instanceof Error ? retryErr.message : String(retryErr)
}`
const retainedRetryError = redactVideoTranscriptSensitiveText(
retryErr instanceof Error ? retryErr.message : String(retryErr),
videoTranscriptSensitive
);
log?.warn?.("RETRY", `clinepass retry failed: ${retainedRetryError}`);
}
}
if (envError) {
@@ -4996,6 +5069,7 @@ export async function handleChatCore({
cacheReasoningFromAssistantMessage(msg, provider, model, {
scope: reasoningCacheScope,
historyMessages: Array.isArray(historyMessages) ? historyMessages : [],
videoTranscriptSensitive,
});
}
} catch {
@@ -5047,12 +5121,18 @@ export async function handleChatCore({
);
if (memoryOwnerId && memorySettings?.enabled && memorySettings.maxTokens > 0) {
const requestMemoryText = extractMemoryTextFromRequestBody(body as Record<string, unknown>);
const requestMemoryText = extractMemoryTextFromRequestBody(
body as Record<string, unknown>,
videoTranscriptSensitive,
{ trustedDescriptionFingerprints: videoTranscriptDescriptionFingerprints }
);
if (requestMemoryText) {
extractFacts(requestMemoryText, memoryOwnerId, pipelineSessionId);
}
const memoryText = extractMemoryTextFromResponse(memoryExtractionResponse);
const memoryText = videoTranscriptSensitive
? ""
: extractMemoryTextFromResponse(memoryExtractionResponse);
if (memoryText) {
extractFacts(memoryText, memoryOwnerId, pipelineSessionId);
}
@@ -5092,6 +5172,7 @@ export async function handleChatCore({
provider,
responsePayloadFormat,
clientResponseFormat,
videoTranscriptSensitive,
});
const postCallGuardrails = await guardrailRegistry.runPostCallHooks(
translatedResponse,
@@ -5133,7 +5214,10 @@ export async function handleChatCore({
}
log?.warn?.(
"GUARDRAIL",
`Response blocked by ${postCallGuardrails.guardrail || "guardrail"}: ${guardrailMessage}`
`Response blocked by ${postCallGuardrails.guardrail || "guardrail"}: ${redactVideoTranscriptSensitiveText(
guardrailMessage,
videoTranscriptSensitive
)}`
);
finalizePendingScope(pendingScope, {
providerResponse: responseBody,
@@ -5236,6 +5320,7 @@ export async function handleChatCore({
apiKeyId: apiKeyInfo?.id ?? undefined,
usage,
log,
videoTranscriptSensitive,
});
// ── Phase 9.2: Save for idempotency ──
@@ -5315,6 +5400,7 @@ export async function handleChatCore({
apiKeyInfo,
headers: clientRawRequest?.headers,
response: { status: 200, data: translatedResponse },
videoTranscriptSensitive,
});
// Routing event (feedback foundation) — fire-and-forget, cheap.
@@ -5390,6 +5476,7 @@ export async function handleChatCore({
provider,
model,
log,
redactUpstreamDiagnosticForLog: videoTranscriptSensitive,
});
if (streamReadiness.ok === false) {
const { response: failureResponse, reason } = streamReadiness;
@@ -5521,6 +5608,7 @@ export async function handleChatCore({
cacheReasoningFromAssistantMessage(msg, provider, model, {
scope: reasoningCacheScope,
historyMessages: Array.isArray(historyMessages) ? historyMessages : [],
videoTranscriptSensitive,
});
}
} catch {
@@ -5553,6 +5641,7 @@ export async function handleChatCore({
status: normalizedStreamStatus,
error: streamError,
errorCode: streamErrorCode,
videoTranscriptSensitive,
});
// Track cache token metrics for streaming responses
@@ -5675,14 +5764,20 @@ export async function handleChatCore({
memorySettings.maxTokens > 0 &&
streamStatus === 200
) {
const requestMemoryText = extractMemoryTextFromRequestBody(body as Record<string, unknown>);
const requestMemoryText = extractMemoryTextFromRequestBody(
body as Record<string, unknown>,
videoTranscriptSensitive,
{ trustedDescriptionFingerprints: videoTranscriptDescriptionFingerprints }
);
if (requestMemoryText) {
extractFacts(requestMemoryText, memoryOwnerId, pipelineSessionId);
}
const streamedMemoryText = extractMemoryTextFromResponse(
(streamResponseBody ?? null) as Record<string, unknown> | null
);
const streamedMemoryText = videoTranscriptSensitive
? ""
: extractMemoryTextFromResponse(
(streamResponseBody ?? null) as Record<string, unknown> | null
);
if (streamedMemoryText) {
extractFacts(streamedMemoryText, memoryOwnerId, pipelineSessionId);
}
@@ -5699,6 +5794,7 @@ export async function handleChatCore({
apiKeyId: apiKeyInfo?.id ?? undefined,
streamUsage,
log,
videoTranscriptSensitive,
});
// Plugin onStreamComplete hook — fire-and-forget, fail-open (#9571)
@@ -5767,7 +5863,8 @@ export async function handleChatCore({
// openai-responses → openai translation still wants the namespace identity
// map for #7936-style round-trip closure when the client also speaks
// Responses (Codex CLI).
requestToolIdentityMap
requestToolIdentityMap,
redactStreamDiagnosticsForLog
);
} else if (needsTranslation(targetFormat, clientResponseFormat)) {
// Standard translation for other providers
@@ -5797,7 +5894,8 @@ export async function handleChatCore({
clientResponseFormat,
}),
customToolNames,
requestToolIdentityMap
requestToolIdentityMap,
redactStreamDiagnosticsForLog
);
} else {
log?.debug?.("STREAM", `Standard passthrough mode`);
@@ -5812,7 +5910,8 @@ export async function handleChatCore({
apiKeyInfo,
handleStreamFailure,
clientResponseFormat,
requestToolIdentityMap
requestToolIdentityMap,
redactStreamDiagnosticsForLog
);
}
@@ -5824,6 +5923,7 @@ export async function handleChatCore({
clientRawRequestHeaders: clientRawRequest?.headers,
clientResponseFormat,
echoModel,
redactStreamDiagnosticsForLog,
responseHeaders,
});
@@ -5839,6 +5939,7 @@ export async function handleChatCore({
apiKeyInfo,
headers: clientRawRequest?.headers,
response: { status: 200, streamed: true },
videoTranscriptSensitive,
});
return {

View File

@@ -15,6 +15,10 @@ import { logAuditEvent } from "@/lib/compliance";
import { emit } from "@/lib/events/eventBus";
import type { RequestCompletedPayload, RequestFailedPayload } from "@/lib/events/types";
import { saveCallLog } from "@/lib/usageDb";
import {
VIDEO_TRANSCRIPT_LOG_OMISSION_MARKER,
VIDEO_TRANSCRIPT_REDACTION_PIPELINE_KEY,
} from "@/lib/guardrails/videoTranscriptLogRedaction";
import { FORMATS } from "../../translator/formats.ts";
import { takeEarlyKeepaliveBytes } from "../../utils/earlyKeepaliveByteBuffer.ts";
import { cloneBoundedChatLogPayload, truncateForLog } from "./logTruncation.ts";
@@ -68,7 +72,13 @@ export type PersistAttemptLogsContext = {
model: string | null | undefined;
skillRequestId: string;
detailedLoggingEnabled: boolean;
reqLogger: { getPipelinePayloads?: () => Record<string, unknown> | undefined } | null | undefined;
reqLogger:
| {
getPipelinePayloads?: () => Record<string, unknown> | undefined;
isVideoTranscriptSensitive?: () => boolean;
}
| null
| undefined;
pendingRequestId: unknown;
clientRawRequest: { endpoint?: string } | null | undefined;
requestedModel: unknown;
@@ -89,12 +99,34 @@ export type PersistAttemptLogsContext = {
* explicitly present (never synthesized from skillRequestId) — persisted as call_logs.session_tag
* for per-session cost attribution. */
sessionTag?: string | null;
/** Trusted request state derived from the Video Bridge guardrail result. */
videoTranscriptSensitive?: boolean;
/** Exact SHA-256 identities of transcript descriptions generated by the guardrail. */
videoTranscriptDescriptionFingerprints?: readonly string[];
};
function toConnectionId(value: unknown): string | null {
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
}
function omitSensitivePipelineResponse(value: unknown): Record<string, unknown> {
const record =
value && typeof value === "object" && !Array.isArray(value)
? (value as Record<string, unknown>)
: {};
return {
...(typeof record.timestamp === "string" ? { timestamp: record.timestamp } : {}),
...(typeof record.status === "number" && Number.isFinite(record.status)
? { status: record.status }
: {}),
...(record.headers !== undefined ? { headers: VIDEO_TRANSCRIPT_LOG_OMISSION_MARKER } : {}),
...(record.statusText !== undefined
? { statusText: VIDEO_TRANSCRIPT_LOG_OMISSION_MARKER }
: {}),
body: VIDEO_TRANSCRIPT_LOG_OMISSION_MARKER,
};
}
function buildAccountRotationMeta(
provider: string | null | undefined,
initialConnectionId: string | null,
@@ -204,6 +236,8 @@ export function persistAttemptLogs(args: PersistAttemptLogsArgs, ctx: PersistAtt
correlationId,
modelPinned,
sessionTag,
videoTranscriptSensitive,
videoTranscriptDescriptionFingerprints,
} = ctx;
const initialConnectionId = toConnectionId(connectionId);
const finalConnectionId = toConnectionId(credentials?.connectionId) || initialConnectionId;
@@ -212,8 +246,21 @@ export function persistAttemptLogs(args: PersistAttemptLogsArgs, ctx: PersistAtt
initialConnectionId,
finalConnectionId
);
const transcriptSensitive =
videoTranscriptSensitive === true || reqLogger?.isVideoTranscriptSensitive?.() === true;
const descriptionLogContext = {
trustedDescriptionFingerprints: videoTranscriptDescriptionFingerprints ?? [],
};
const providerWarnings = extractProviderWarnings(providerResponse, clientResponse, responseBody);
const detectedProviderWarnings = extractProviderWarnings(
providerResponse,
clientResponse,
responseBody
);
const providerWarnings =
transcriptSensitive && detectedProviderWarnings.length > 0
? [VIDEO_TRANSCRIPT_LOG_OMISSION_MARKER]
: detectedProviderWarnings;
if (providerWarnings.length > 0) {
logAuditEvent({
action: "provider.warning",
@@ -227,6 +274,7 @@ export function persistAttemptLogs(args: PersistAttemptLogsArgs, ctx: PersistAtt
model,
connectionId: finalConnectionId,
httpStatus: status,
warningCount: detectedProviderWarnings.length,
warnings: providerWarnings,
},
});
@@ -273,8 +321,51 @@ export function persistAttemptLogs(args: PersistAttemptLogsArgs, ctx: PersistAtt
};
}
}
if (transcriptSensitive) {
pipelinePayloads[VIDEO_TRANSCRIPT_REDACTION_PIPELINE_KEY] = true;
for (const requestStage of [
"clientRawRequest",
"openaiRequest",
"providerRequest",
] as const) {
if (pipelinePayloads[requestStage] !== undefined) {
pipelinePayloads[requestStage] = cloneBoundedChatLogPayload(
pipelinePayloads[requestStage],
0,
requestStage !== "clientRawRequest" ? descriptionLogContext : {}
) as Record<string, unknown>;
}
}
if (pipelinePayloads.providerResponse !== undefined || providerResponse !== undefined) {
pipelinePayloads.providerResponse = omitSensitivePipelineResponse(
pipelinePayloads.providerResponse ?? providerResponse
);
}
if (pipelinePayloads.clientResponse !== undefined || clientResponse !== undefined) {
pipelinePayloads.clientResponse = omitSensitivePipelineResponse(
pipelinePayloads.clientResponse ?? clientResponse
);
}
if (pipelinePayloads.error !== undefined || error) {
const errorRecord =
pipelinePayloads.error && typeof pipelinePayloads.error === "object"
? pipelinePayloads.error
: {};
pipelinePayloads.error = {
...(typeof errorRecord.timestamp === "string"
? { timestamp: errorRecord.timestamp }
: {}),
message: VIDEO_TRANSCRIPT_LOG_OMISSION_MARKER,
};
}
delete pipelinePayloads.streamChunks;
}
}
const responseBodyForLog = transcriptSensitive
? VIDEO_TRANSCRIPT_LOG_OMISSION_MARKER
: responseBody;
saveCallLog({
id: pendingRequestId,
method: "POST",
@@ -290,10 +381,12 @@ export function persistAttemptLogs(args: PersistAttemptLogsArgs, ctx: PersistAtt
attachLogMeta(truncateForLog(body as Record<string, unknown>), {
...accountRotationMeta,
claudePromptCache: claudeCacheMeta,
})
}),
0,
descriptionLogContext
),
responseBody: cloneBoundedChatLogPayload(
attachLogMeta(truncateForLog(responseBody as Record<string, unknown>), {
attachLogMeta(truncateForLog(responseBodyForLog as Record<string, unknown>), {
...accountRotationMeta,
claudePromptCache: claudeCacheMeta
? {
@@ -305,7 +398,7 @@ export function persistAttemptLogs(args: PersistAttemptLogsArgs, ctx: PersistAtt
claudePromptCacheUsage: claudeCacheUsageMeta,
})
),
error: error || null,
error: transcriptSensitive && error ? VIDEO_TRANSCRIPT_LOG_OMISSION_MARKER : error || null,
sourceFormat,
targetFormat,
comboName,
@@ -332,7 +425,7 @@ export function persistAttemptLogs(args: PersistAttemptLogsArgs, ctx: PersistAtt
const lifecycle = resolveRequestLifecycleEvent({
traceId,
status,
error,
error: transcriptSensitive && error ? VIDEO_TRANSCRIPT_LOG_OMISSION_MARKER : error,
model,
provider,
comboName,

View File

@@ -17,8 +17,10 @@
*/
import { getExecutor } from "../../executors/index.ts";
import type { ExecuteInput } from "../../executors/base.ts";
import { isCliproxyapiDeepModeEnabled } from "../../executors/cliproxyapi.ts";
import { isDarioDeepModeEnabled } from "../../executors/dario.ts";
import { redactVideoTranscriptSensitiveText } from "../../../src/lib/guardrails/videoTranscriptLogRedaction.ts";
import { getCachedSettings } from "@/lib/db/readCache";
import { getUpstreamProxyConfigCached } from "./comboContextCache.ts";
import type { FallbackBackend } from "@/lib/db/upstreamProxy";
@@ -48,6 +50,11 @@ function parseFallbackCodes(raw: unknown): number[] | null {
return parsed.length > 0 ? parsed : null;
}
function retainExecutorDiagnostic(error: unknown, input: ExecuteInput): string {
const message = error instanceof Error ? error.message : String(error);
return redactVideoTranscriptSensitiveText(message, input.videoTranscriptSensitive === true);
}
/**
* Reads the CLIProxyAPI-related settings shared by both the direct
* `mode: "cliproxyapi"` passthrough leg and the `mode: "fallback"` retry leg:
@@ -155,25 +162,20 @@ export async function resolveExecutorWithProxy(
const isRetryableStatus = (s: number) => fallbackCodes.includes(s) || s === 0;
const wrapper = Object.create(nativeExec);
wrapper.execute = async (input: {
model: string;
body: unknown;
stream: boolean;
credentials: unknown;
signal?: AbortSignal | null;
log?: unknown;
upstreamExtraHeaders?: Record<string, string> | null;
}) => {
wrapper.execute = async (input: ExecuteInput) => {
let result;
try {
result = await nativeExec.execute(input);
} catch (err) {
const errMsg = err instanceof Error ? err.message : String(err);
log?.info?.("UPSTREAM_PROXY", `${prov} native error (${errMsg}), retrying via ${backendLabel}`);
const errMsg = retainExecutorDiagnostic(err, input);
log?.info?.(
"UPSTREAM_PROXY",
`${prov} native error (${errMsg}), retrying via ${backendLabel}`
);
try {
return await proxyExec.execute(input);
} catch (proxyErr) {
const proxyMsg = proxyErr instanceof Error ? proxyErr.message : String(proxyErr);
const proxyMsg = retainExecutorDiagnostic(proxyErr, input);
log?.error?.("UPSTREAM_PROXY", `${prov} ${backendLabel} fallback also failed: ${proxyMsg}`);
throw proxyErr;
}
@@ -189,7 +191,7 @@ export async function resolveExecutorWithProxy(
try {
return await proxyExec.execute(input);
} catch (proxyErr) {
const proxyMsg = proxyErr instanceof Error ? proxyErr.message : String(proxyErr);
const proxyMsg = retainExecutorDiagnostic(proxyErr, input);
log?.error?.("UPSTREAM_PROXY", `${prov} ${backendLabel} fallback also failed: ${proxyMsg}`);
throw proxyErr;
}

View File

@@ -124,6 +124,7 @@ export async function checkIdempotencyCache({
effectiveServiceTier,
startTime,
log,
videoTranscriptSensitive,
}: {
clientRawRequest: IdempotencyRequest;
provider: string;
@@ -132,7 +133,9 @@ export async function checkIdempotencyCache({
effectiveServiceTier: EffectiveServiceTier | null | undefined;
startTime: number;
log: LoggerLike;
videoTranscriptSensitive: boolean;
}): Promise<{ hit: { success: true; response: Response } | null; idempotencyKey: string | null }> {
if (videoTranscriptSensitive) return { hit: null, idempotencyKey: null };
// NEXA fusion-idempotency fix: namespace the raw header key (see composeIdempotencyKey).
const rawIdempotencyKey = getIdempotencyKey(clientRawRequest?.headers);
const idempotencyKey = composeIdempotencyKey({

View File

@@ -5,6 +5,10 @@ import {
getChatLogMaxObjectKeys,
getChatLogMaxBodyBytes,
} from "@/lib/logEnv";
import {
omitVideoTranscriptForLog,
type VideoTranscriptLogContext,
} from "@/lib/guardrails/videoTranscriptLogRedaction";
import { estimateSizeFast } from "../../utils/estimateSize.ts";
export const MEMORY_EXTRACTION_TEXT_LIMIT = 64 * 1024;
@@ -22,7 +26,7 @@ export function truncateChatLogText(value: string): string {
return `${head}\n[...truncated ${value.length - limit} chars...]\n${tail}`;
}
export function cloneBoundedChatLogPayload(value: unknown, depth = 0): unknown {
function cloneBoundedChatLogPayloadValue(value: unknown, depth = 0): unknown {
if (value === null || value === undefined) return value;
if (typeof value === "string") return truncateChatLogText(value);
if (typeof value !== "object") return value;
@@ -32,7 +36,7 @@ export function cloneBoundedChatLogPayload(value: unknown, depth = 0): unknown {
if (Array.isArray(value)) {
const retained = value.length > maxTailItems ? value.slice(-maxTailItems) : value;
const cloned = retained.map((item) => cloneBoundedChatLogPayload(item, depth + 1));
const cloned = retained.map((item) => cloneBoundedChatLogPayloadValue(item, depth + 1));
if (value.length > maxTailItems) {
return [
{
@@ -47,10 +51,11 @@ export function cloneBoundedChatLogPayload(value: unknown, depth = 0): unknown {
}
const result: Record<string, unknown> = {};
const entries = Object.entries(value as Record<string, unknown>);
const record = value as Record<string, unknown>;
const entries = Object.entries(record);
const maxKeys = getChatLogMaxObjectKeys();
for (const [key, item] of maxKeys > 0 ? entries.slice(0, maxKeys) : entries) {
result[key] = cloneBoundedChatLogPayload(item, depth + 1);
result[key] = cloneBoundedChatLogPayloadValue(item, depth + 1);
}
if (maxKeys > 0 && entries.length > maxKeys) {
result._omniroute_truncated_keys = entries.length - maxKeys;
@@ -58,6 +63,16 @@ export function cloneBoundedChatLogPayload(value: unknown, depth = 0): unknown {
return result;
}
export function cloneBoundedChatLogPayload(
value: unknown,
depth = 0,
descriptionContext: VideoTranscriptLogContext = {}
): unknown {
const transcriptSafeValue =
depth === 0 ? omitVideoTranscriptForLog(value, descriptionContext) : value;
return cloneBoundedChatLogPayloadValue(transcriptSafeValue, depth);
}
/**
* Truncate a large object for logging. If its JSON representation exceeds
* getChatLogMaxBodyBytes() (default 1MB; CHAT_LOG_MAX_BODY_KB env override),

View File

@@ -1,5 +1,39 @@
import {
containsVideoTranscriptForLog,
omitVideoTranscriptDerivedTextForMemory,
type VideoTranscriptLogContext,
} from "../../../src/lib/guardrails/videoTranscriptLogRedaction.ts";
import { capMemoryExtractionText, MEMORY_EXTRACTION_TEXT_LIMIT } from "./logTruncation.ts";
function normalizeMemoryInputText(value: unknown, context: VideoTranscriptLogContext = {}): string {
if (typeof value !== "string") return "";
return omitVideoTranscriptDerivedTextForMemory(value, context).trim();
}
function extractMemoryTextPart(
part: Record<string, unknown>,
transcriptSensitive: boolean,
context: VideoTranscriptLogContext
): string {
try {
const rawText = typeof part?.text === "string" ? part.text : "";
if (!rawText) return "";
const retainedText = normalizeMemoryInputText(rawText, context);
if (!retainedText) return "";
if (
transcriptSensitive &&
containsVideoTranscriptForLog(part, context) &&
retainedText === rawText.trim()
) {
return "";
}
return retainedText;
} catch {
return "";
}
}
export function extractMemoryTextFromResponse(
response: Record<string, unknown> | null | undefined
): string {
@@ -29,9 +63,16 @@ export function extractMemoryTextFromResponse(
}
export function extractMemoryTextFromRequestBody(
body: Record<string, unknown> | null | undefined
body: Record<string, unknown> | null | undefined,
videoTranscriptSensitive = false,
context: VideoTranscriptLogContext = {}
): string {
if (!body || typeof body !== "object") return "";
// Re-check the structured body at the sink boundary. The explicit bit covers
// processed requests whose raw carrier was already replaced; trusted hashes
// identify only descriptions emitted by a modified Video Bridge guardrail.
const transcriptSensitive =
videoTranscriptSensitive || containsVideoTranscriptForLog(body, context);
const messages = Array.isArray(body.messages) ? body.messages : null;
if (messages && messages.length > 0) {
@@ -39,18 +80,16 @@ export function extractMemoryTextFromRequestBody(
const msg = messages[i] as Record<string, unknown>;
if (msg?.role !== "user") continue;
if (typeof msg.content === "string" && msg.content.trim().length > 0) {
return capMemoryExtractionText(msg.content.trim());
const messageText = normalizeMemoryInputText(msg.content, context);
if (messageText) {
return capMemoryExtractionText(messageText);
}
if (Array.isArray(msg.content)) {
const text = msg.content
.map((part: Record<string, unknown>) => {
if (typeof part?.text === "string") return part.text.trim();
if (part?.type === "input_text" && typeof part?.text === "string")
return part.text.trim();
return "";
})
.map((part: Record<string, unknown>) =>
extractMemoryTextPart(part, transcriptSensitive, context)
)
.filter(Boolean)
.join("\n")
.trim();
@@ -68,17 +107,15 @@ export function extractMemoryTextFromRequestBody(
if (role && role !== "user") continue;
if (itemType && itemType !== "message") continue;
if (typeof item?.content === "string" && item.content.trim()) {
return capMemoryExtractionText(item.content.trim());
const itemText = normalizeMemoryInputText(item?.content, context);
if (itemText) {
return capMemoryExtractionText(itemText);
}
if (Array.isArray(item?.content)) {
const text = item.content
.map((part: Record<string, unknown>) => {
if (typeof part?.text === "string") return part.text.trim();
if (part?.type === "input_text" && typeof part?.text === "string")
return part.text.trim();
return "";
})
.map((part: Record<string, unknown>) =>
extractMemoryTextPart(part, transcriptSensitive, context)
)
.filter(Boolean)
.join("\n")
.trim();
@@ -96,15 +133,14 @@ export function extractMemoryTextFromRequestBody(
if (role && role !== "user") return "";
if (itemType && itemType !== "message") return "";
if (typeof item?.content === "string") return item.content.trim();
if (typeof item?.content === "string") {
return normalizeMemoryInputText(item.content, context);
}
if (Array.isArray(item?.content)) {
return item.content
.map((part: Record<string, unknown>) => {
if (typeof part?.text === "string") return part.text.trim();
if (part?.type === "input_text" && typeof part?.text === "string")
return part.text.trim();
return "";
})
.map((part: Record<string, unknown>) =>
extractMemoryTextPart(part, transcriptSensitive, context)
)
.filter(Boolean)
.join("\n")
.trim();

View File

@@ -9,6 +9,8 @@
* byte-identical to the previous inline block.
*/
import { redactVideoTranscriptSensitiveText } from "@/lib/guardrails/videoTranscriptLogRedaction";
type LoggerLike =
{ info?: (...args: unknown[]) => void; debug?: (...args: unknown[]) => void } | null | undefined;
@@ -25,6 +27,7 @@ export async function runPluginOnRequestHook(args: {
apiKeyInfo: unknown;
headers?: Record<string, string | string[] | undefined>;
log?: LoggerLike;
videoTranscriptSensitive?: boolean;
}): Promise<PluginOnRequestGate> {
try {
const { runOnRequest } = await import("@/lib/plugins/hooks");
@@ -36,6 +39,7 @@ export async function runPluginOnRequestHook(args: {
apiKeyInfo: args.apiKeyInfo,
headers: args.headers,
metadata: {},
videoTranscriptSensitive: args.videoTranscriptSensitive === true,
};
const pluginResult = await runOnRequest(pluginCtx);
if (pluginResult?.blocked) {
@@ -55,10 +59,11 @@ export async function runPluginOnRequestHook(args: {
}
return { blocked: false, body: pluginResult?.body };
} catch (pluginErr) {
args.log?.debug?.(
"PLUGIN",
`onRequest hook error (non-fatal): ${pluginErr instanceof Error ? pluginErr.message : String(pluginErr)}`
const retainedPluginError = redactVideoTranscriptSensitiveText(
pluginErr instanceof Error ? pluginErr.message : String(pluginErr),
args.videoTranscriptSensitive === true
);
args.log?.debug?.("PLUGIN", `onRequest hook error (non-fatal): ${retainedPluginError}`);
return { blocked: false };
}
}

View File

@@ -26,6 +26,7 @@ export async function runPluginOnResponseHook(args: {
apiKeyInfo: unknown;
headers?: Record<string, string | string[] | undefined>;
response: PluginOnResponsePayload;
videoTranscriptSensitive?: boolean;
}): Promise<void> {
try {
const { runOnResponse } = await import("@/lib/plugins/hooks");
@@ -38,6 +39,7 @@ export async function runPluginOnResponseHook(args: {
apiKeyInfo: args.apiKeyInfo,
headers: args.headers,
metadata: {},
videoTranscriptSensitive: args.videoTranscriptSensitive === true,
},
args.response
).catch(() => {});

View File

@@ -36,6 +36,7 @@ export function buildPostCallGuardrailContext(
provider: string | null | undefined;
responsePayloadFormat: unknown;
clientResponseFormat: unknown;
videoTranscriptSensitive?: boolean;
},
resolveDisabledGuardrails: typeof defaultResolveDisabled = defaultResolveDisabled
): GuardrailContext {
@@ -57,5 +58,6 @@ export function buildPostCallGuardrailContext(
sourceFormat: optionalString(args.responsePayloadFormat),
stream: false,
targetFormat: optionalString(args.clientResponseFormat),
videoTranscriptSensitive: args.videoTranscriptSensitive === true,
};
}

View File

@@ -1,8 +1,4 @@
import {
generateSignature,
getCachedResponse,
isCacheableForRead,
} from "@/lib/semanticCache";
import { generateSignature, getCachedResponse, isCacheableForRead } from "@/lib/semanticCache";
import { calculateCost } from "@/lib/usage/costCalculator";
import { trackPendingRequest } from "@/lib/usageDb";
import { synthesizeOpenAiSseFromJson } from "../../utils/jsonToSse.ts";
@@ -25,6 +21,7 @@ export async function checkSemanticCache({
persistAttemptLogs,
apiKeyId,
cacheDefaultMode,
videoTranscriptSensitive,
}: {
semanticCacheEnabled: boolean;
// Only the fields this read path actually touches are named; everything else
@@ -42,7 +39,9 @@ export async function checkSemanticCache({
persistAttemptLogs: (args: unknown) => void;
apiKeyId?: string | null;
cacheDefaultMode?: "legacy" | "bypass" | null;
videoTranscriptSensitive: boolean;
}) {
if (videoTranscriptSensitive) return null;
// Per-key bypass: skip cache lookup entirely when the API key opts out.
if (cacheDefaultMode === "bypass") return null;
if (semanticCacheEnabled && isCacheableForRead(body, clientRawRequest?.headers)) {

View File

@@ -50,10 +50,12 @@ export function storeSemanticCacheResponse(
apiKeyId?: string;
usage?: UsageLike;
log?: LoggerLike;
videoTranscriptSensitive: boolean;
},
deps: SemanticCacheStoreDeps = DEFAULT_DEPS
): void {
if (
args.videoTranscriptSensitive ||
!args.enabled ||
!deps.isCacheableForWrite(args.body, args.headers) ||
!deps.isSmallEnoughForSemanticCache(args.translatedResponse)

View File

@@ -68,6 +68,7 @@ export function assembleStreamingPipeline(
clientRawRequestHeaders: HeadersLike;
clientResponseFormat: Parameters<typeof defaultShape>[0];
echoModel: string | null | undefined;
redactStreamDiagnosticsForLog?: boolean;
responseHeaders: Record<string, string>;
},
deps: StreamingPipelineDeps = DEFAULT_DEPS
@@ -83,7 +84,8 @@ export function assembleStreamingPipeline(
let piiStream = deps.pipeWithDisconnect(
args.providerResponse,
args.transformStream,
args.streamController
args.streamController,
{ redactStreamDiagnosticsForLog: args.redactStreamDiagnosticsForLog }
);
if (typeof args.createPiiTransform === "function") {
piiStream = piiStream.pipeThrough((args.createPiiTransform as () => TransformStream)());

View File

@@ -49,6 +49,7 @@ interface StreamingCacheArgs {
apiKeyId?: string;
streamUsage?: Record<string, unknown> | null;
log?: LoggerLike;
videoTranscriptSensitive: boolean;
}
function streamTokensSaved(streamUsage: Record<string, unknown> | null | undefined): number {
@@ -87,6 +88,7 @@ export function storeStreamingSemanticCacheResponse(
deps: StreamingSemanticCacheStoreDeps = DEFAULT_DEPS
): void {
if (
args.videoTranscriptSensitive ||
!args.enabled ||
args.streamStatus !== 200 ||
!args.streamResponseBody ||

View File

@@ -92,19 +92,65 @@ interface KieImageOptions {
}
// KIE Market catalog ids are namespaced for OmniRoute's catalog
// (`google-imagen/<model>`), but the KIE Market createTask API expects
// (`<vendor>/<model>`), but the KIE Market createTask API expects
// vendor-specific upstream ids that do not follow a single consistent
// pattern (confirmed against docs.kie.ai/market/google/* — see #11225,
// #11296): nano-banana-2 and nano-banana-pro drop the vendor namespace
// entirely, while nano-banana and nano-banana-edit use a `google/` prefix
// instead of `google-imagen/`. Every other KIE Market namespace (seedream,
// flux, ideogram, qwen, wan, grok-imagine, gpt) already matches its real
// upstream id byte-for-byte, so this map stays scoped to google-imagen.
// pattern. Every entry below was confirmed individually against the literal
// example request JSON published on docs.kie.ai (never inferred by pattern —
// see #11326's false "everything else already matches" claim and #11296's
// follow-up correction):
// - google-imagen: nano-banana-2 and nano-banana-pro drop the vendor
// namespace entirely; nano-banana and nano-banana-edit use a `google/`
// prefix instead of `google-imagen/` (docs.kie.ai/market/google/*).
// - gpt: gpt-image-2-* drops the `gpt/` namespace entirely
// (docs.kie.ai/market/gpt/gpt-image-2-*); gpt-image-1.5-* uses a
// `gpt-image/` namespace instead of `gpt/gpt-image-1.5-`, and keeps the
// dot in "1.5" (docs.kie.ai/market/gpt-image/1-5-*).
// - seedream: 5.0-lite-* drops the ".0" — real id is `5-lite-*`
// (docs.kie.ai/market/seedream/5-lite-text-to-image); seedream 4.5 (T2I
// and edit) already matches byte-for-byte.
// - flux: `flux/2-*` uses a `flux-2/` namespace (dash, not slash); the
// generic (non-"pro") variant is named `flex` upstream, not `2`
// (docs.kie.ai/market/flux2/pro-*, .../flex-*).
// - wan: `wan/2.7-*` keeps the dot in our catalog, but KIE's documented
// enum uses a dash — real id is `wan/2-7-*`
// (docs.kie.ai/market/wan/2-7-image[-pro]).
// - ideogram (v3-text-to-image, v3-edit, v3-remix), qwen, qwen2, and
// grok-imagine already match byte-for-byte
// (docs.kie.ai/market/{ideogram,qwen,qwen2,grok-imagine}/*).
// ideogram/v3-reframe has no dedicated docs.kie.ai page as of this sweep
// (its 3 siblings above are all direct id matches, so it is assumed
// correct by pattern, not independently confirmed).
// Two catalog entries remain UNRESOLVED after this sweep and are
// deliberately left untouched pending a follow-up (see #11296 discussion):
// - z-image/4.0-text-to-image and z-image/4.5-text-to-image: the only
// documented Z-Image Market page (docs.kie.ai/market/z-image/z-image)
// shows a single fixed `model` enum value `"z-image"` with no
// version-specific id or "version" input field found — unclear whether
// both catalog ids should collapse to the same upstream call.
// - flux/kontext: no `docs.kie.ai/market/flux2/kontext` (or similar)
// Market page exists; Flux Kontext is documented under the separate
// `/flux-kontext-api/*` docs tree with its own endpoint
// (`POST /api/v1/flux/kontext/generate`, models `flux-kontext-pro`/
// `flux-kontext-max`), not the Market `createTask` flow this map feeds.
// This entry may be miscatalogued as `isMarket: true` and need a
// dedicated reroute rather than an id rewrite.
export const KIE_MARKET_UPSTREAM_MODEL_IDS: ReadonlyMap<string, string> = new Map([
["google-imagen/nano-banana", "google/nano-banana"],
["google-imagen/nano-banana-2", "nano-banana-2"],
["google-imagen/nano-banana-pro", "nano-banana-pro"],
["google-imagen/nano-banana-edit", "google/nano-banana-edit"],
["gpt/gpt-image-2-text-to-image", "gpt-image-2-text-to-image"],
["gpt/gpt-image-2-image-to-image", "gpt-image-2-image-to-image"],
["gpt/gpt-image-1.5-text-to-image", "gpt-image/1.5-text-to-image"],
["gpt/gpt-image-1.5-image-to-image", "gpt-image/1.5-image-to-image"],
["seedream/5.0-lite-text-to-image", "seedream/5-lite-text-to-image"],
["seedream/5.0-lite-image-to-image", "seedream/5-lite-image-to-image"],
["flux/2-pro-text-to-image", "flux-2/pro-text-to-image"],
["flux/2-pro-image-to-image", "flux-2/pro-image-to-image"],
["flux/2-text-to-image", "flux-2/flex-text-to-image"],
["flux/2-image-to-image", "flux-2/flex-image-to-image"],
["wan/2.7-image", "wan/2-7-image"],
["wan/2.7-image-pro", "wan/2-7-image-pro"],
]);
export function resolveKieMarketUpstreamModelId(publicModelId: string): string {

View File

@@ -9,6 +9,7 @@ import { randomUUID } from "crypto";
* youcom-search, searxng-search, ollama-search, zai-search, jina-search,
* duckduckgo-free, x-search (Grok / SuperGrok X Search — explicit or search_type "x")
* and xquik-search (direct X API search — explicit or credentialed fallback)
* and anysearch-search (free public web search — fallback-only)
*
* Request format:
* {
@@ -31,6 +32,7 @@ import { type FirecrawlSearchEnvelope } from "./search/firecrawlSearch.ts";
import { buildJinaSearchRequest, extractJinaSearchItems } from "./search/jinaSearch.ts";
import * as xSearch from "./search/xSearch.ts";
import * as xquikSearch from "./search/xquikSearch.ts";
import * as anysearchSearch from "./search/anysearchSearch.ts";
import { freeWebSearch } from "../services/freeWebSearch.ts";
import { saveCallLog } from "@/lib/usageDb";
import { safeOutboundFetch } from "@/shared/network/safeOutboundFetch";
@@ -751,6 +753,7 @@ const requestBuilders: Record<string, SearchRequestBuilder> = {
"jina-search": buildJinaSearchRequest,
"x-search": xSearch.buildXSearchRequest,
"xquik-search": xquikSearch.buildXquikSearchRequest,
"anysearch-search": anysearchSearch.buildAnysearchSearchRequest,
};
function buildRequest(
@@ -1370,6 +1373,7 @@ const responseNormalizers: Record<string, SearchResponseNormalizer> = {
"jina-search": normalizeJinaSearchResponse,
"x-search": normalizeXSearchResponse,
"xquik-search": (data) => xquikSearch.normalizeXquikSearchResponse(data, makeResult),
"anysearch-search": (data) => anysearchSearch.normalizeAnysearchSearchResponse(data, makeResult),
};
function normalizeResponse(

Some files were not shown because too many files have changed in this diff Show More