Files
OmniRoute/open-sse/executors/uc/catalog.ts
Armin Anton” ∴ 530096a3be feat(providers): add UC (uncensored.com) — persona (un-metered) + direct (metered) (#11513)
Adds uncensored.com as two OpenAI-compatible providers mirroring UC's own surfaces: uc, the persona/subscription side over WebSocket with a durable Clerk credential minting a short-lived per-connect token (no API key, un-metered), as a full multimodal port — chat, tools, vision, doc-RAG, image, video, TTS; and uc-direct, the metered Developer API over REST with X-api-key. Same underlying models, two billing surfaces.

Reconciled on merge. 57 files conflicted; only seven carried UC content, the rest was drift from the older release line and took the tip's side.

- executors/index.ts: the tip has since refactored the executor map to lazy dynamic imports, so uc is registered in that shape. uc-direct needs no entry — it routes through the default OpenAI-compatible executor.
- imageGeneration.ts: the branch still carried the retired designerWeb import alongside ucImage; kept only the UC one.
- config/providers/index.ts, webSessionCredentials.ts and web-cookie.ts resolved additively against the MaxAI entries #11461 put on the tip an hour earlier.
- web-cookie.ts: the uc entry declared no serviceKinds, required since #11392, so provider validation would have thrown at load. Declared ["llm"]. uc-direct already declared it at the end of its own entry — an earlier pass of mine added a second one after id and TypeScript caught the duplicate (TS1117); the author's placement is what shipped.

Every count was measured against the merged tree rather than taken from the branch, and all three would have been wrong: reserved prefixes are 406, not 399; APIKEY_PROVIDERS is 237, not 234; providers are 355. PROVIDER_REFERENCE.md regenerated, the count updated across README/AGENTS.md/llm.txt and its 42 mirrors, package.json and 6 SVGs — every changed line in the protected surfaces is a digit substitution and nothing else, verified by masking digits and comparing the removed and added sets (90 lines each, identical). The executor-map golden snapshot went 134 -> 135.

The branch's file-size-baseline.json predates #12411's ratchet re-tightening and was discarded rather than merged; imageGeneration.ts (+12 for the uc-image format branch) was entered against the current baseline under a _rebaseline annotation, and no other cap moves.

Verified: typecheck:core clean, check:provider-consistency OK (271 REGISTRY entries, 355 canonical providers), check:docs-counts exit 0, check-file-size OK, check:cycles OK, 119/119 across the PR's test files, and 2/2 executor-map-golden.

Thanks @arminanton — two providers for two real billing surfaces, rather than one entry pretending to be both, is the right modelling.
2026-09-02 02:23:33 -03:00

175 lines
5.2 KiB
TypeScript

/**
* UC (uncensored.com) PERSONA model catalog.
*
* These 19 ids are the empirically-verified working persona-mode models: each
* one returned real text from the WebSocket backend in a live audit
* (UC-UNCENSORED-MODELS.md / UC-NATIVE-PORT-FINDINGS.md). Guessed/broken ids
* (e.g. persona `gpt-5.4`, base `claude-opus-4.8` non-uncensored) were dropped
* so the provider never advertises a model that 500s.
*
* `id` is the UC persona **shortname** (provider prefix dropped, dots stripped):
* this is exactly the value sent as the WS frame's `model` field. Context /
* max-output come from UC's direct-mode catalog (direct-models.json); grok-4.x
* publish no separate output cap (bounded by the context window).
*
* The ⭐ `-uncensored` / persona variants are the differentiator (unlocked
* behavior) — the whole reason this un-metered surface is worth porting.
*/
import type { RegistryModel } from "../../config/providers/shared.ts";
interface UcModelSpec {
id: string;
name: string;
contextLength: number;
maxOutputTokens?: number;
supportsReasoning?: boolean;
/**
* Vision-capable (the underlying model accepts image input). UC persona feeds
* images via the blob-upload layer (see uc/media.ts), which the backend parses
* server-side and hands to the model — so vision works for these ids.
* Sourced from UC's direct-mode catalog (direct-models.json capabilities).
*/
supportsVision?: boolean;
}
/** The 19 offered persona (un-metered) chat models. */
export const UC_MODELS: UcModelSpec[] = [
// Anthropic (persona: 4.8 is uncensored-only, so we expose the -uncensored id)
{
id: "claude-opus-45",
name: "Claude Opus 4.5",
contextLength: 200_000,
maxOutputTokens: 64_000,
supportsVision: true,
},
{
id: "claude-opus-46",
name: "Claude Opus 4.6",
contextLength: 1_000_000,
maxOutputTokens: 128_000,
supportsVision: true,
},
{
id: "claude-opus-46-v2",
name: "Claude Opus 4.6 (v2)",
contextLength: 1_000_000,
maxOutputTokens: 128_000,
supportsVision: true,
},
{
id: "claude-opus-47",
name: "Claude Opus 4.7",
contextLength: 1_000_000,
maxOutputTokens: 128_000,
supportsVision: true,
},
{
id: "claude-opus-47-v2",
name: "Claude Opus 4.7 (v2)",
contextLength: 1_000_000,
maxOutputTokens: 128_000,
supportsVision: true,
},
{
id: "claude-opus-48-uncensored",
name: "Claude Opus 4.8 (Uncensored)",
contextLength: 1_000_000,
maxOutputTokens: 128_000,
supportsVision: true,
},
// DeepSeek
{
id: "deepseek-r1",
name: "DeepSeek R1",
contextLength: 163_840,
maxOutputTokens: 16_000,
supportsReasoning: true,
},
// GLM
{ id: "glm-5.1", name: "GLM 5.1", contextLength: 202_752, maxOutputTokens: 131_072 },
// OpenAI (gpt-5.5 is the only working persona GPT; guardrailed → code-style tools)
{
id: "gpt-5.5",
name: "GPT-5.5",
contextLength: 1_050_000,
maxOutputTokens: 128_000,
supportsVision: true,
},
// Google Gemini
{
id: "gemini-3-flash",
name: "Gemini 3 Flash",
contextLength: 1_048_576,
maxOutputTokens: 65_536,
supportsVision: true,
},
{
id: "gemini-31-uncensored",
name: "Gemini 3.1 (Uncensored)",
contextLength: 1_048_576,
maxOutputTokens: 65_536,
supportsVision: true,
},
{
id: "gemini-emotional",
name: "Gemini (Emotional)",
contextLength: 1_048_576,
maxOutputTokens: 65_536,
supportsVision: true,
},
{
id: "gemini-3-uncensored",
name: "Gemini 3 (Uncensored)",
contextLength: 1_048_576,
maxOutputTokens: 65_536,
supportsVision: true,
},
// xAI Grok (no separate output cap — bounded by context window)
{ id: "grok-4", name: "Grok 4", contextLength: 1_000_000, supportsVision: true },
{ id: "grok-4-20", name: "Grok 4.20", contextLength: 2_000_000, supportsVision: true },
{ id: "grok-4-3", name: "Grok 4.3", contextLength: 1_000_000, supportsVision: true },
// Moonshot Kimi
{
id: "kimi-k2-thinking",
name: "Kimi K2 Thinking",
contextLength: 262_144,
maxOutputTokens: 262_144,
supportsReasoning: true,
},
{
id: "kimi-k2.5",
name: "Kimi K2.5",
contextLength: 262_144,
maxOutputTokens: 262_144,
supportsVision: true,
},
// MiniMax
{
id: "minimax-m2-her",
name: "MiniMax M2 (Her)",
contextLength: 204_800,
maxOutputTokens: 131_072,
},
];
/** RegistryModel[] form for the provider registry entry. */
export const UC_REGISTRY_MODELS: RegistryModel[] = UC_MODELS.map((m) => ({
id: m.id,
name: m.name,
contextLength: m.contextLength,
// Prompted tool-calling: UC persona has no native tools[] API, but the
// executor injects a <tool_call> preamble and parses the calls back, so the
// capability is real from the client's perspective.
toolCalling: true,
...(m.maxOutputTokens ? { maxOutputTokens: m.maxOutputTokens } : {}),
...(m.supportsReasoning ? { supportsReasoning: true } : {}),
...(m.supportsVision ? { supportsVision: true } : {}),
}));
/** Default context window for an unknown model. */
export const UC_DEFAULT_CONTEXT = 128_000;
export function ucContextWindow(modelId: string): number {
return UC_MODELS.find((m) => m.id === modelId)?.contextLength ?? UC_DEFAULT_CONTEXT;
}