Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/reference/PROVIDER_REFERENCE.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
title: "Provider Reference"
version: 3.8.52
lastUpdated: 2026-10-17
lastUpdated: 2026-10-18
---

# 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-10-17
> **Last generated:** 2026-10-18

Total providers: **374**. See category breakdown below.

Expand Down Expand Up @@ -44,7 +44,7 @@ Use the dashboard at `/dashboard/providers` to enable, configure, and test each
| `codex-app-server` | `cxa` | OpenAI Codex (App-Server) | No-auth | [link](https://developers.openai.com/codex/cli) | No token stored by OmniRoute. The Codex CLI app-server manages its own ChatGPT sign-in (~/.codex/auth.json, auto-refreshed). Use “Sign in with ChatGPT” if the CLI is not yet authenticated. | — |
| `devin-cli-agentic` | `dva` | Devin CLI Agentic Bridge | No-auth | [link](https://docs.devin.ai/work-with-devin/devin-cli) | Authentication is owned by the official Devin CLI in its isolated bridge volume. | emulated |
| `duckduckgo-web` | `ddgw` | DuckDuckGo AI Chat | No-auth | [link](https://duckduckgo.com/duckchat) | No credentials required — DuckDuckGo AI Chat is anonymous and free. | emulated |
| `uncloseai` | `unc` | UncloseAI | No-auth | [link](https://uncloseai.com) | No auth required. API accepts any non-empty string as key for identification. If older built-in models return 404, use Available Models → Import from /models or Auto-Sync; verified live model: Lorbus/Qwen3.6-27B-int4-AutoRound. | emulated |
| `uncloseai` | `unc` | UncloseAI | No-auth | [link](https://uncloseai.com) | No auth required. API accepts any non-empty string as key for identification. If older built-in models return 404, use Available Models → Import from /models or Auto-Sync; verified live model: turboderp/Qwen3.8-27B-exl3. | emulated |
| `veoaifree-web` | `veo-free` | Veo AI Free | No-auth, video | [link](https://veoaifree.com) | No auth required. Rate limited to 6 requests/hour per IP. | — |
| `zcode` | `zc` | ZCode (GLM Coding Plan) | No-auth | [link](https://zcode.z.ai) | No API key stored by OmniRoute. The local ZCode app-server uses the existing builtin:zai-coding-plan login. | — |

Expand Down Expand Up @@ -462,7 +462,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/) (153 implementations)
- Executors: [`open-sse/executors/`](../../open-sse/executors/) (154 implementations)
- Translators: [`open-sse/translator/`](../../open-sse/translator/)

## See Also
Expand Down
8 changes: 4 additions & 4 deletions open-sse/config/freeModelCatalog.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,10 +432,10 @@ export const FREE_MODEL_BUDGETS: FreeModelBudget[] = [
{ provider: "t3-web", modelId: "qwen3-32b", displayName: "Qwen3 32B (via t3.chat)", monthlyTokens: 0, creditTokens: 0, freeType: "recurring-daily", poolKey: "t3-web", tos: "avoid" },
{ provider: "t3-web", modelId: "kimi-k2", displayName: "Kimi K2 (via t3.chat)", monthlyTokens: 0, creditTokens: 0, freeType: "recurring-daily", poolKey: "t3-web", tos: "avoid" },
{ provider: "tencent", modelId: "hunyuan-pro", displayName: "Hunyuan Pro", monthlyTokens: 0, creditTokens: 0, freeType: "recurring-uncapped", poolKey: "tencent", tos: "caution" },
// 2026-09-15 refresh: upstream /v1/models serves a single live model; the
// three previously catalogued ids 404 on /v1/chat/completions (see the
// matching comment in providers/registry/uncloseai/index.ts).
{ provider: "uncloseai", modelId: "Lorbus/Qwen3.6-27B-int4-AutoRound", displayName: "Qwen3.6 27B int4 AutoRound (🆓 Free)", monthlyTokens: 0, creditTokens: 0, freeType: "keyless", poolKey: "uncloseai", tos: "caution" },
// 2026-10-16 refresh: upstream /v1/models serves a single live model; the
// previously catalogued id 404s on /v1/chat/completions (see the matching
// comment in providers/registry/uncloseai/index.ts).
{ provider: "uncloseai", modelId: "turboderp/Qwen3.8-27B-exl3", displayName: "Qwen3.8 27B exl3 (🆓 Free)", monthlyTokens: 0, creditTokens: 0, freeType: "keyless", poolKey: "uncloseai", tos: "caution" },
{ provider: "vertex", modelId: "gemini-3.1-pro-preview", displayName: "Gemini 3.1 Pro Preview (Vertex)", monthlyTokens: 0, creditTokens: 300000000, freeType: "one-time-initial", poolKey: "vertex", tos: "caution" },
{ provider: "vertex", modelId: "gemini-3.1-flash-lite", displayName: "Gemini 3.1 Flash Lite (Vertex)", monthlyTokens: 0, creditTokens: 300000000, freeType: "one-time-initial", poolKey: "vertex", tos: "caution" },
{ provider: "vertex", modelId: "gemini-3-flash-preview", displayName: "Gemini 3 Flash Preview (Vertex)", monthlyTokens: 0, creditTokens: 300000000, freeType: "one-time-initial", poolKey: "vertex", tos: "caution" },
Expand Down
24 changes: 17 additions & 7 deletions open-sse/config/providers/registry/uncloseai/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,25 @@ export const uncloseaiProvider: RegistryEntry = {
authType: "optional",
authHeader: "bearer",
toolCalling: "emulated",
// The roster rotates every few weeks (see the models[] comment below), so the
// context window must NOT hang off a pinned model id: resolveTokenLimit() would
// miss a newly-rotated id, fall through to the generic 128000 catch-all, and let
// enforceOutputTokenBudget() hand out a completion budget that overflows the real
// 65536 window (upstream then 400s: "context length 65536 ... you requested
// 65537"). A provider-level default survives the rotation — any uncloseai model
// resolves to 65536 even with no discovery/import run. Per-model discovery
// (max_model_len → auto:discovery override) still wins when a sync has run.
defaultContextLength: 65536,
models: [
// 2026-09-15 refresh — upstream rotated its roster: /v1/models now serves
// exactly one model, and every previously catalogued id (adamo1139/
// Hermes-3-Llama-3.1-8B-FP8-Dynamic, qwen3.6:27b, gemma4:31b) returns
// 404 "model does not exist" on /v1/chat/completions. The live id below
// was confirmed with a real completion (vllm backend, max_model_len 65536).
// 2026-10-16 refresh — upstream rotated its roster again (it does this every
// few weeks): /v1/models now serves exactly one model, and the previously
// catalogued id (Lorbus/Qwen3.6-27B-int4-AutoRound) returns 404 "model does
// not exist" on /v1/chat/completions. The live id below was read straight
// from GET https://hermes.ai.unturf.com/v1/models (vllm backend,
// max_model_len 65536).
{
id: "Lorbus/Qwen3.6-27B-int4-AutoRound",
name: "Qwen3.6 27B int4 AutoRound (🆓 Free)",
id: "turboderp/Qwen3.8-27B-exl3",
name: "Qwen3.8 27B exl3 (🆓 Free)",
contextLength: 65536,
},
],
Expand Down
2 changes: 1 addition & 1 deletion src/shared/constants/providers/noauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export const NOAUTH_PROVIDERS = {
serviceKinds: ["llm"],
toolCalling: "emulated",
authHint:
"No auth required. API accepts any non-empty string as key for identification. If older built-in models return 404, use Available Models → Import from /models or Auto-Sync; verified live model: Lorbus/Qwen3.6-27B-int4-AutoRound.",
"No auth required. API accepts any non-empty string as key for identification. If older built-in models return 404, use Available Models → Import from /models or Auto-Sync; verified live model: turboderp/Qwen3.8-27B-exl3.",
freeNote: "Free forever — no signup, no credit card. OpenAI-compatible endpoints.",
notice: {
text: "UncloseAI needs no API key. API accepts any non-empty string as key for identification. If older built-in models return 404, use Available Models → Import from /models or Auto-Sync.",
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/combo-builder-options-route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ test("combo builder options route includes no-auth provider (uncloseai) even wit
assert.ok(noAuth.models.length > 0, "uncloseai should expose its built-in models");
// Spot-check a known built-in model from providerRegistry.ts
assert.ok(
noAuth.models.some((m: any) => m.id === "Lorbus/Qwen3.6-27B-int4-AutoRound"),
noAuth.models.some((m: any) => m.id === "turboderp/Qwen3.8-27B-exl3"),
"the built-in model should be among uncloseai models"
);
// #2901: no-auth providers route under their alias ("unc/"), not their id.
Expand Down
8 changes: 4 additions & 4 deletions tests/unit/models-catalog-route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,11 @@ test("v1 models catalog includes display names by default", async () => {
new Request("http://localhost/api/v1/models")
);
const body = (await response.json()) as any;
const model = body.data.find((item) => item.id === "unc/Lorbus/Qwen3.6-27B-int4-AutoRound");
const model = body.data.find((item) => item.id === "unc/turboderp/Qwen3.8-27B-exl3");

assert.equal(response.status, 200);
assert.ok(model);
assert.equal(model.name, "Qwen3.6 27B int4 AutoRound (🆓 Free)");
assert.equal(model.name, "Qwen3.8 27B exl3 (🆓 Free)");
});

test("v1 models catalog omits display names when the feature flag is disabled", async () => {
Expand All @@ -191,12 +191,12 @@ test("v1 models catalog omits display names when the feature flag is disabled",
new Request("http://localhost/api/v1/models")
);
const body = (await response.json()) as any;
const model = body.data.find((item) => item.id === "unc/Lorbus/Qwen3.6-27B-int4-AutoRound");
const model = body.data.find((item) => item.id === "unc/turboderp/Qwen3.8-27B-exl3");

assert.equal(response.status, 200);
assert.ok(model);
assert.equal("name" in model, false);
assert.equal(model.root, "Lorbus/Qwen3.6-27B-int4-AutoRound");
assert.equal(model.root, "turboderp/Qwen3.8-27B-exl3");
} finally {
featureFlagsDb.removeFeatureFlagOverride("MODEL_CATALOG_INCLUDE_NAMES");
}
Expand Down
67 changes: 58 additions & 9 deletions tests/unit/uncloseai-registry-refresh.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,27 @@ import assert from "node:assert/strict";
import { getRegistryEntry } from "../../open-sse/config/providerRegistry.ts";
import { FREE_MODEL_BUDGETS } from "../../open-sse/config/freeModelCatalog.ts";

// Dynamic imports (mirrors tests/unit/deepseek-flash-context-limit-13922.test.ts):
// contextManager pulls in the model-capability/DB chain, which must not run at
// module scope.
const { resolveTokenLimit } = await import("../../open-sse/services/contextManager.ts");
const { enforceOutputTokenBudget } =
await import("../../open-sse/handlers/chatCore/outputTokenBudget.ts");

/**
* 2026-09-15: uncloseai (hermes.ai.unturf.com) rotated its roster — /v1/models
* went down to a single live model and every previously catalogued id started
* returning 404 "model does not exist" on /v1/chat/completions, so requests
* routed through the static seed failed while the provider itself was healthy
* (a real completion against the live id succeeds). The seed is only the
* offline fallback (live discovery via NAMED_OPENAI_STYLE_PROVIDERS), but the
* dashboard serves it whenever discovery has not run, so the stale ids must
* not survive in the registry or the free-model catalog.
* 2026-10-16: uncloseai (hermes.ai.unturf.com) rotated its roster again —
* /v1/models serves a single live model and the previously catalogued id
* (Lorbus/Qwen3.6-27B-int4-AutoRound) started returning 404 "model does not
* exist" on /v1/chat/completions, so requests routed through the static seed
* failed while the provider itself was healthy (a real completion against the
* live id succeeds). The seed is only the offline fallback (live discovery via
* NAMED_OPENAI_STYLE_PROVIDERS), but the dashboard serves it whenever discovery
* has not run, so the stale ids must not survive in the registry or the
* free-model catalog. Same rotation as the 2026-09-15 entry below.
*/
const LIVE_MODEL = "Lorbus/Qwen3.6-27B-int4-AutoRound";
const LIVE_MODEL = "turboderp/Qwen3.8-27B-exl3";
const DEAD_MODELS = [
"Lorbus/Qwen3.6-27B-int4-AutoRound",
"adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic",
"qwen3.6:27b",
"gemma4:31b",
Expand Down Expand Up @@ -55,3 +64,43 @@ test("free-model catalog carries exactly the live uncloseai row", () => {
assert.equal(stillListed, false, `retired id ${dead} must not remain in the free catalog`);
}
});

/**
* The rotating roster must not take the context window down with it.
*
* resolveTokenLimit() step 3 (provider-registry `defaultContextLength`) is the
* source that survives a rotation: the pinned `models[]` id goes stale every few
* weeks, and a freshly rotated id is absent from the registry *and* from any
* synced discovery row, so with no provider-level window it falls through to the
* generic 128000 catch-all. enforceOutputTokenBudget() then derives available
* output from 128000, which overstates the real 65536 window, and the vLLM
* upstream rejects the request — observed live: "This model's maximum context
* length is 65536 tokens ... you requested 65537" (33537 input + 32000 max_tokens).
* Per-model discovery (max_model_len → auto:discovery override) still wins when a
* sync has run; this is the floor that works with no discovery at all.
*/
test("uncloseai declares a provider-level window that survives a roster rotation", () => {
assert.equal(getRegistryEntry("uncloseai")?.defaultContextLength, 65536);
});

test("any uncloseai model id — rotated or not yet seen — resolves to the 65536 window", () => {
for (const id of [LIVE_MODEL, ...DEAD_MODELS, "some/future-model-not-in-registry"]) {
const resolved = resolveTokenLimit("uncloseai", id);
assert.equal(resolved.limit, 65536, `${id} must resolve to the real window`);
assert.equal(resolved.specific, true, `${id} must not fall through to the generic default`);
}
});

test("the observed overflow (33537 input + 32000 max_tokens) is clamped to fit 65536", () => {
const input = 33537;
const budget = enforceOutputTokenBudget(
{ max_tokens: 32000 },
input,
resolveTokenLimit("uncloseai", LIVE_MODEL).limit
);
assert.equal(budget.ok, true);
if (budget.ok !== true) return;
const maxTokens = (budget.body as Record<string, unknown>).max_tokens as number;
assert.equal(maxTokens, 65536 - input);
assert.ok(input + maxTokens <= 65536, "prompt + completion must fit the window");
});
Loading