mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-17 20:32:25 +03:00
The opencode executor classifies rate-limited 429 bodies (`classify429`, with real tests) and, when a whole account wave is exhausted, returns the last real upstream 429 — status, body, `Retry-After` and quota headers intact — so the provider error rules (monthly-quota cooldown) keep working.
Maintainer rework before merge (kept the idea, no default behavior change):
- The original stopped the cross-account wave at the first classified 429 and replaced the response with a synthetic one that dropped the body and headers; stopping early is now opt-in behind `OPENCODE_RATE_LIMITED_429_EARLY_STOP` (default off), the rate-limited account is still cooled down, the body is read as a bounded 8 KiB prefix from a clone and the original is never consumed, and the unused `status` input is gone.
Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests.
Thanks @maxmad64bis!
837 lines
35 KiB
TypeScript
837 lines
35 KiB
TypeScript
export interface FeatureFlagDefinition {
|
|
key: string;
|
|
label: string;
|
|
description: string;
|
|
descriptionI18nKey: string;
|
|
category: "security" | "network" | "policies" | "runtime" | "cli" | "health";
|
|
defaultValue: string;
|
|
type: "boolean" | "enum";
|
|
enumValues?: string[];
|
|
requiresRestart: boolean;
|
|
warningLevel?: "info" | "caution" | "danger";
|
|
}
|
|
|
|
export const FEATURE_FLAG_DEFINITIONS: FeatureFlagDefinition[] = [
|
|
// ──────────────── Security (10) ────────────────
|
|
{
|
|
key: "REQUIRE_API_KEY",
|
|
label: "Require API Key",
|
|
description: "Require an API key for all incoming requests",
|
|
descriptionI18nKey: "featureFlagRequireApiKeyDescription",
|
|
category: "security",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "INPUT_SANITIZER_ENABLED",
|
|
label: "Input Sanitizer",
|
|
description: "Enable input sanitization for all requests",
|
|
descriptionI18nKey: "featureFlagInputSanitizerEnabledDescription",
|
|
category: "security",
|
|
defaultValue: "true",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "INJECTION_GUARD_MODE",
|
|
label: "Injection Guard Mode",
|
|
description: "Set the prompt injection guard mode",
|
|
descriptionI18nKey: "featureFlagInjectionGuardModeDescription",
|
|
category: "security",
|
|
defaultValue: "off",
|
|
type: "enum",
|
|
enumValues: ["off", "warn", "block", "redact"],
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "PII_REDACTION_ENABLED",
|
|
label: "PII Redaction",
|
|
description: "Redact personally identifiable information from requests",
|
|
descriptionI18nKey: "featureFlagPiiRedactionEnabledDescription",
|
|
category: "security",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "PII_RESPONSE_SANITIZATION",
|
|
label: "PII Response Sanitization",
|
|
description: "Sanitize PII from provider responses",
|
|
descriptionI18nKey: "featureFlagPiiResponseSanitizationDescription",
|
|
category: "security",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "PII_RESPONSE_SANITIZATION_MODE",
|
|
label: "PII Response Sanitization Mode",
|
|
description:
|
|
"Mode for PII response sanitization: redact (replace PII), warn (log only), block (reject), off (disable)",
|
|
descriptionI18nKey: "featureFlagPiiResponseSanitizationModeDescription",
|
|
category: "security",
|
|
defaultValue: "redact",
|
|
type: "enum",
|
|
enumValues: ["redact", "warn", "block", "off"],
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "OUTBOUND_SSRF_GUARD_ENABLED",
|
|
label: "SSRF Guard",
|
|
description: "Block outbound requests to private/internal IP ranges",
|
|
descriptionI18nKey: "featureFlagOutboundSsrfGuardEnabledDescription",
|
|
category: "security",
|
|
defaultValue: "true",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "ALLOW_API_KEY_REVEAL",
|
|
label: "API Key Reveal",
|
|
description:
|
|
"Allow authenticated dashboard users to reveal stored API keys instead of only seeing masked values.",
|
|
descriptionI18nKey: "featureFlagAllowApiKeyRevealDescription",
|
|
category: "security",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "danger",
|
|
},
|
|
{
|
|
key: "AUTH_LOG_INCLUDE_ACCOUNT_ID",
|
|
label: "Log Account IDs",
|
|
description:
|
|
'Include account prefix in AUTH log lines (e.g. "Using <provider> account: abc12345..."). ' +
|
|
"Disabled by default so account identifiers are redacted from shared/multi-tenant process logs. " +
|
|
"Independent from Debug Mode; flipping Debug Mode does not reveal this.",
|
|
descriptionI18nKey: "featureFlagAuthLogIncludeAccountIdDescription",
|
|
category: "security",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_OIDC_DISABLE_PASSWORD_LOGIN",
|
|
label: "Disable Password Login With OIDC",
|
|
description:
|
|
"When OIDC is enabled, disable password login so users can only authenticate via OIDC Single Sign-On. When disabled (default), both password login and OIDC are available.",
|
|
descriptionI18nKey: "featureFlagOidcDisablePasswordLoginDescription",
|
|
category: "security",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
// ──────────────── Network (7) ────────────────
|
|
{
|
|
key: "ENABLE_TLS_FINGERPRINT",
|
|
label: "TLS Fingerprint",
|
|
description: "Enable TLS fingerprint stealth mode",
|
|
descriptionI18nKey: "featureFlagEnableTlsFingerprintDescription",
|
|
category: "network",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: true,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "AUDIO_REMOTE_PROVIDER_NODES",
|
|
label: "Remote Audio Provider Nodes",
|
|
description:
|
|
"Allow the /v1/audio/* routes to use OpenAI-compatible provider nodes hosted outside localhost. Off by default — routing audio to a remote host changes egress identity and must be an explicit operator decision. Loopback nodes are always allowed and unaffected.",
|
|
descriptionI18nKey: "settings.featureFlags.audioRemoteProviderNodes",
|
|
category: "network",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "danger",
|
|
},
|
|
{
|
|
key: "PROXY_AUTO_SELECT_ENABLED",
|
|
label: "Proxy Auto-Selection Fallback",
|
|
description:
|
|
"When no proxy is assigned to a connection, auto-select the first working proxy from the registry. Off by default — otherwise any single registry proxy becomes a global fallback for all traffic (#3332).",
|
|
descriptionI18nKey: "settings.featureFlags.proxyAutoSelectEnabled",
|
|
category: "network",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_CONTROL_PLANE_PROXY_DIRECT_FALLBACK",
|
|
label: "Control-Plane Proxy Direct Fallback",
|
|
description:
|
|
"Allow OAuth and provider validation flows to bypass a pinned proxy and connect directly when proxy reachability pre-checks fail. Off by default because this can change account egress IP.",
|
|
descriptionI18nKey: "featureFlagOmnirouteControlPlaneProxyDirectFallbackDescription",
|
|
category: "network",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "danger",
|
|
},
|
|
{
|
|
key: "NETWORK_ROTATION_SHARED_EGRESS_GUARD",
|
|
label: "Network Rotation Shared-Egress Guard",
|
|
description:
|
|
"On a network exception (timeout, connection refused/reset) for a multi-account rotation executor, when the failing account has no dedicated proxy, apply a short cooldown and skip other proxy-less accounts for the rest of the request instead of retrying each one. On by default (safe: no egress IP change, only reduces latency/cooldown risk on shared-egress accounts). Disable to restore immediate propagation on the first proxy-less throw.",
|
|
descriptionI18nKey: "featureFlagNetworkRotationSharedEgressGuardDescription",
|
|
category: "network",
|
|
defaultValue: "true",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "PROXY_SKIP_RECENTLY_FAILED",
|
|
label: "Skip Recently Failed Proxies",
|
|
description:
|
|
"Proxy pools and the per-account rotation of opencode stop re-serving a proxy that just failed (refused TCP probe, or a 429 received through it) for a per-process period that doubles on each repeat, up to a cap. No proxy status is written; with every candidate set aside the choice is unchanged. Off by default: selection order is exactly the plain rotation.",
|
|
descriptionI18nKey: "featureFlagProxySkipRecentlyFailedDescription",
|
|
category: "network",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "PROXY_POOL_EGRESS_OBSERVATION",
|
|
label: "Proxy Pool Egress Observation",
|
|
description:
|
|
"Show, under a proxy pool in the dashboard, how many observed egress IPs served its members over the last 24 h, how many connections used them and the most seen behind one IP. Read-only, computed from the proxy log, never used for routing. Off by default: the pool editor is unchanged and the observation route answers null.",
|
|
descriptionI18nKey: "featureFlagProxyPoolEgressObservationDescription",
|
|
category: "network",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "OPENCODE_RESPONSES_STALL_ROTATION",
|
|
label: "OpenCode Responses Stall Rotation",
|
|
description:
|
|
"For the OpenCode executor, watch the first body byte of a streamed Responses reply (window: RESPONSES_FIRST_BYTE_TIMEOUT_MS, default 15000). A 2xx Responses stream that stays silent past the window is treated as stalled: the account is cooled down and the request rotates to the next account once; a second stall fails fast. Off by default: stalled streams keep today's wait until the stream readiness timeout.",
|
|
descriptionI18nKey: "featureFlagOpencodeResponsesStallRotationDescription",
|
|
category: "network",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "OPENCODE_USER_BLOCKED_ROTATION",
|
|
label: "OpenCode user_blocked Rotation",
|
|
description:
|
|
"For the OpenCode executor, when an upstream answers 403 or 451 carrying a user_blocked refusal (not a geo block, not a Cloudflare fingerprint rejection), cool the refused account down and rotate to the next account at most once per request; a second refusal is returned as-is without a success mark. Off by default: routing around an upstream user block can look like evasion and spread the flag across the account fleet, so the refusal is returned unchanged unless the operator opts in.",
|
|
descriptionI18nKey: "featureFlagOpencodeUserBlockedRotationDescription",
|
|
category: "network",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "OPENCODE_TRANSIENT_FAILOVER_BACKOFF",
|
|
label: "OpenCode Transient Failover Backoff",
|
|
description:
|
|
"For the OpenCode multi-account rotation, pause before dispatching to the next account once two consecutive attempts failed with a transient upstream error (5xx or an empty 400 rejection). The pause starts at 1.5s, doubles per further consecutive failure, is capped at 6s per pause and 10s per request, is skipped when the client disconnects, and the failed response body is released before waiting. Off by default: failover stays immediate.",
|
|
descriptionI18nKey: "featureFlagOpencodeTransientFailoverBackoffDescription",
|
|
category: "network",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "OPENCODE_RATE_LIMITED_429_EARLY_STOP",
|
|
label: "OpenCode Rate-Limited 429 Early Stop",
|
|
description:
|
|
"For the OpenCode multi-account rotation, stop the account wave at the first 429 classified as a real rate limit (a parseable Retry-After header, or a body naming a rate/usage limit) and return that upstream 429 unchanged (status, body, Retry-After and quota headers), instead of trying every remaining account. Unclassified 429s keep rotating. Off by default: the free tier is limited per egress IP (#9611), so every 429 rotates to the next account, and an exhausted wave returns the last upstream 429.",
|
|
descriptionI18nKey: "featureFlagOpencodeRateLimited429EarlyStopDescription",
|
|
category: "network",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "MITM_DISABLE_TLS_VERIFY",
|
|
label: "Disable TLS Verify (MITM)",
|
|
description: "Disable TLS certificate verification for MITM proxy",
|
|
descriptionI18nKey: "featureFlagMitmDisableTlsVerifyDescription",
|
|
category: "network",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: true,
|
|
warningLevel: "danger",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS",
|
|
label: "Allow Private Provider URLs",
|
|
description: "Allow provider URLs pointing to private/internal networks",
|
|
descriptionI18nKey: "featureFlagOmnirouteAllowPrivateProviderUrlsDescription",
|
|
category: "network",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_ALLOW_LOCAL_PROVIDER_URLS",
|
|
label: "Allow Local Provider URLs",
|
|
description:
|
|
"Allow adding and validating providers on local/private addresses (127.0.0.1, localhost, LAN, private IP ranges) — needed for local OpenAI-compatible models. Enabled by default (OmniRoute is local-first); turn it OFF to enforce strict public-only blocking if you only use public providers. Cloud-metadata endpoints (e.g. 169.254.169.254) stay blocked either way.",
|
|
descriptionI18nKey: "featureFlagOmnirouteAllowLocalProviderUrlsDescription",
|
|
category: "network",
|
|
defaultValue: "true",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "ENABLE_CC_COMPATIBLE_PROVIDER",
|
|
label: "CC Compatible Provider",
|
|
description: "Enable Claude Code compatible provider mode",
|
|
descriptionI18nKey: "featureFlagEnableCcCompatibleProviderDescription",
|
|
category: "network",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: true,
|
|
warningLevel: "info",
|
|
},
|
|
|
|
// ──────────────── Policies (5) ────────────────
|
|
{
|
|
key: "TOOL_POLICY_MODE",
|
|
label: "Tool Policy Mode",
|
|
description: "Set the tool use policy enforcement mode",
|
|
descriptionI18nKey: "featureFlagToolPolicyModeDescription",
|
|
category: "policies",
|
|
defaultValue: "disabled",
|
|
type: "enum",
|
|
enumValues: ["disabled", "warn", "block"],
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "RATE_LIMIT_AUTO_ENABLE",
|
|
label: "Rate Limit Auto-Enable",
|
|
description: "Automatically enable rate limiting based on usage patterns",
|
|
descriptionI18nKey: "featureFlagRateLimitAutoEnableDescription",
|
|
category: "policies",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "DISABLE_CONTEXT_WINDOW_CHECKS",
|
|
label: "Disable Context Window Checks",
|
|
description:
|
|
"Skip OmniRoute's local context-window and max-input-token check for direct single-model requests. Upstream providers remain responsible for enforcing their actual limits. Off by default.",
|
|
descriptionI18nKey: "featureFlagDisableContextWindowChecksDescription",
|
|
category: "policies",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "danger",
|
|
},
|
|
{
|
|
key: "CAPABILITY_FILTER_ENABLED",
|
|
label: "Capability Filter",
|
|
description:
|
|
"Reject requests before dispatch when the target model lacks required capabilities (vision, tools, structured output, context window). Protects direct single-provider requests that bypass the combo-layer compatibility filter.",
|
|
descriptionI18nKey: "featureFlagCapabilityFilterEnabledDescription",
|
|
category: "policies",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "RADAR_ENABLED",
|
|
label: "Radar",
|
|
description:
|
|
"Enable the OmniRoute Radar module (catalog feed screens and sync). Off by default; enabling only unlocks the UI — data sync remains a separate opt-in.",
|
|
descriptionI18nKey: "featureFlagRadarEnabledDescription",
|
|
category: "policies",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
|
|
// ──────────────── Runtime (17) ────────────────
|
|
{
|
|
key: "UNIVERSAL_CONTEXT_HANDOFF_ENABLED",
|
|
label: "Universal Context Handoff",
|
|
description:
|
|
"Generate and inject conversation summaries when combo routing switches models. Disable to treat model switches independently and prevent background handoff requests for all existing and future combos.",
|
|
descriptionI18nKey: "featureFlagUniversalContextHandoffEnabledDescription",
|
|
category: "runtime",
|
|
defaultValue: "true",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "RESPONSES_PASSTHROUGH_DROP_COMMENTARY",
|
|
label: "Drop Responses Commentary",
|
|
description:
|
|
"Drop internal commentary-phase output items from Responses API passthrough streams before forwarding to clients. Disable to receive raw upstream commentary.",
|
|
descriptionI18nKey: "featureFlagResponsesPassthroughDropCommentaryDescription",
|
|
category: "runtime",
|
|
defaultValue: "true",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_MCP_ENFORCE_SCOPES",
|
|
label: "MCP Enforce Scopes",
|
|
description: "Enforce scope restrictions on MCP tool access",
|
|
descriptionI18nKey: "featureFlagOmnirouteMcpEnforceScopesDescription",
|
|
category: "runtime",
|
|
defaultValue: "true",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_MCP_COMPRESS_DESCRIPTIONS",
|
|
label: "MCP Compress Descriptions",
|
|
description: "Compress MCP tool descriptions to reduce token usage",
|
|
descriptionI18nKey: "featureFlagOmnirouteMcpCompressDescriptionsDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_ENABLE_RUNTIME_BACKGROUND_TASKS",
|
|
label: "Runtime Background Tasks",
|
|
description: "Enable background task processing at runtime",
|
|
descriptionI18nKey: "featureFlagOmnirouteEnableRuntimeBackgroundTasksDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_DISABLE_BACKGROUND_SERVICES",
|
|
label: "Disable Background Services",
|
|
description: "Disable all background services (quota refresh, sync, etc)",
|
|
descriptionI18nKey: "featureFlagOmnirouteDisableBackgroundServicesDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: true,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_RTK_TRUST_PROJECT_FILTERS",
|
|
label: "RTK Trust Project Filters",
|
|
description: "Trust project-level filters from RTK without validation",
|
|
descriptionI18nKey: "featureFlagOmnirouteRtkTrustProjectFiltersDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_ENABLE_LIVE_WS",
|
|
label: "Live Dashboard WebSocket",
|
|
description:
|
|
"Start the real-time dashboard WebSocket server on import (port 20132, loopback-bound by default). Default: enabled. Set to '0' or 'false' to disable. LAN exposure requires LIVE_WS_HOST=0.0.0.0 + LIVE_WS_ALLOWED_ORIGINS.",
|
|
descriptionI18nKey: "featureFlagOmnirouteEnableLiveWsDescription",
|
|
category: "runtime",
|
|
defaultValue: "true",
|
|
type: "boolean",
|
|
requiresRestart: true,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_CODEX_WS_ENABLED",
|
|
label: "Codex Responses WebSocket",
|
|
description:
|
|
"Allow Codex to use the Responses-over-WebSocket transport (the codex CLI WS endpoint and codexTransport=websocket). When off, Codex falls back to HTTP Responses.",
|
|
descriptionI18nKey: "featureFlagOmnirouteCodexWsEnabledDescription",
|
|
category: "runtime",
|
|
defaultValue: "true",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_CODEX_APP_SERVER_ENABLED",
|
|
label: "Codex App-Server Transport",
|
|
description:
|
|
"Allow Codex to use the local app-server WebSocket JSON-RPC transport (codexTransport=app-server). When off, connections opted into app-server fall back to Codex's other transports.",
|
|
descriptionI18nKey: "featureFlagOmnirouteCodexAppServerEnabledDescription",
|
|
category: "runtime",
|
|
defaultValue: "true",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_EMERGENCY_FALLBACK",
|
|
label: "Emergency Fallback",
|
|
description: "Route budget-exhausted requests to the emergency free fallback provider/model.",
|
|
descriptionI18nKey: "featureFlagOmnirouteEmergencyFallbackDescription",
|
|
category: "runtime",
|
|
defaultValue: "true",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "STREAM_RECOVERY_ENABLED",
|
|
label: "Stream Recovery",
|
|
description:
|
|
"Enable transparent early retry for truncated upstream SSE streams before any response bytes reach the client.",
|
|
descriptionI18nKey: "featureFlagStreamRecoveryEnabledDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "STREAM_RECOVERY_MIDSTREAM_ENABLED",
|
|
label: "Mid-Stream Continuation",
|
|
description:
|
|
"Allow stream recovery to re-request and stitch a response after bytes have already reached the client.",
|
|
descriptionI18nKey: "featureFlagStreamRecoveryMidstreamEnabledDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "danger",
|
|
},
|
|
{
|
|
key: "STREAM_RECOVERY_TOOLCALL_ORDER_FIX",
|
|
label: "Tool-Call-Safe Continuation",
|
|
description:
|
|
"Make mid-stream continuation tool-call safe: never resume a cut stream once a tool call was emitted (in flight or already finished with finish_reason tool_calls), and close after one empty continuation instead of spending the whole budget. Off: release behavior.",
|
|
descriptionI18nKey: "featureFlagStreamRecoveryToolcallOrderFixDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "STREAM_EARLY_EOF_SIBLING_FAILOVER_ENABLED",
|
|
label: "Early-EOF Sibling Failover",
|
|
description:
|
|
"Fail over once to a sibling connection when an SSE stream closes before emitting any useful frame and the bounded same-connection retry is spent; with no usable sibling the original STREAM_EARLY_EOF 502 is returned. Off by default: early-EOF stays terminal after the same-connection retry.",
|
|
descriptionI18nKey: "featureFlagStreamEarlyEofSiblingFailoverEnabledDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "MODEL_CATALOG_INCLUDE_NAMES",
|
|
label: "Model Catalog Names",
|
|
description:
|
|
"Include display-friendly name fields in /v1/models responses. Disable for clients that expect model IDs only.",
|
|
descriptionI18nKey: "settings.featureFlags.modelCatalogIncludeNames",
|
|
category: "runtime",
|
|
defaultValue: "true",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "MODELS_CATALOG_PREFIX_MODE",
|
|
label: "Models Catalog Prefix Mode",
|
|
description:
|
|
"Controls how model IDs are prefixed in /v1/models. 'dual' (default) emits both alias and canonical provider-id prefixes for backward compatibility. 'alias' emits only the short alias prefix (e.g. ds-web/model, not deepseek-web/model). 'canonical' emits only the full provider-id prefix.",
|
|
descriptionI18nKey: "featureFlagModelsCatalogPrefixModeDescription",
|
|
category: "runtime",
|
|
defaultValue: "dual",
|
|
type: "enum",
|
|
enumValues: ["dual", "alias", "canonical"],
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "ARENA_ELO_SYNC_ENABLED",
|
|
label: "Arena ELO Sync",
|
|
description: "Enable periodic Arena AI leaderboard ELO sync for model intelligence rankings.",
|
|
descriptionI18nKey: "featureFlagArenaEloSyncEnabledDescription",
|
|
category: "runtime",
|
|
defaultValue: "true",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "EXPOSE_CC_DISCOVERY_ALIASES",
|
|
label: "Claude Code Discovery Aliases",
|
|
description:
|
|
"Advertise claude/<provider>/<model> mirror ids on /v1/models so Claude Code gateway model discovery lists non-Claude models. Warning: doubles catalog entries for all clients when enabled globally.",
|
|
descriptionI18nKey: "featureFlagExposeCcDiscoveryAliasesDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "NO_THINKING_ALIAS_ENABLED",
|
|
label: "No-Thinking Model Aliases",
|
|
description:
|
|
"Master switch for the no-think/<provider>/<model> gateway aliases. On (default): /v1/models advertises a no-thinking variant for every eligible thinking-capable Claude model, and a no-think/ id sent on a request resolves back to the real model with reasoning suppressed. Off: no variants are advertised and a no-think/ id is treated like any other unknown model id. The per-model ModelSpec.noThinkingAlias opt-in/opt-out still applies while this is on.",
|
|
descriptionI18nKey: "featureFlagNoThinkingAliasEnabledDescription",
|
|
category: "runtime",
|
|
defaultValue: "true",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_DISABLE_THINKING_LEVEL_VARIANTS",
|
|
label: "Disable Thinking Level Variants",
|
|
description:
|
|
"Disable the generation of thinking level variants (e.g. -low, -medium, -high) in the /v1/models catalog.",
|
|
descriptionI18nKey: "featureFlagOmnirouteDisableThinkingLevelVariantsDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_CHAT_VIRTUAL_LANES",
|
|
label: "Adaptive Virtual Admission Lanes",
|
|
description:
|
|
"Enable per-tenant adaptive virtual admission lanes for provider dispatch (#9654): one tenant's burst no longer 503s another. The OMNIROUTE_CHAT_VIRTUAL_LANES env var wins over this dashboard override; changes take effect at server restart.",
|
|
descriptionI18nKey: "featureFlagChatVirtualLanesEnabledDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: true,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "EXPOSE_FUNCTIONAL_GATEWAY_MIRRORS",
|
|
label: "Functional Gateway Mirrors",
|
|
description:
|
|
"Advertise <gateway-alias>/<model> mirror ids on /v1/models for models whose canonical owner has no active credential but a passthrough gateway with an active credential routes them. Warning: adds catalog entries for all clients when enabled globally.",
|
|
descriptionI18nKey: "featureFlagExposeFunctionalGatewayMirrorsDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
|
|
{
|
|
key: "NEWAPI_AGGREGATOR_BALANCE",
|
|
label: "New-API Aggregator Balance",
|
|
description:
|
|
"Enable balance detection for New-API / One-API / Sub2API aggregator compatible nodes. When enabled, compatible nodes with the aggregator flag set will report their balance in the dashboard and quota-preflight routing.",
|
|
descriptionI18nKey: "featureFlagNewApiAggregatorBalanceDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "SERVER_OWNED_TOOL_LOOP_ENABLED",
|
|
label: "Server-Owned Tool Loop",
|
|
description:
|
|
"Continue non-streaming server-owned tool calls until the model returns a client-usable response.",
|
|
descriptionI18nKey: "featureFlagServerOwnedToolLoopDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "SEARCH_STATS_HIDE_DELETED_CONNECTIONS",
|
|
label: "Hide Deleted Search Connections",
|
|
description:
|
|
"Search stats and recent searches only count providers that still have a live connection (keyless providers such as duckduckgo-free always count). Off keeps every retained search row with a provider id.",
|
|
descriptionI18nKey: "featureFlagSearchStatsHideDeletedConnectionsDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "FREE_BADGE_REQUIRES_PROVIDER_FREE_TIER",
|
|
label: "Strict Free Badge",
|
|
description:
|
|
"Dashboard provider pages: show the Free badge only on signals the provider honors — drops the display-name heuristic, non-boolean free fields and :free suffixes on registered providers without a documented free tier. Off keeps the historical badge rule.",
|
|
descriptionI18nKey: "featureFlagFreeBadgeRequiresProviderFreeTierDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "RETRY_AFTER_PROVENANCE_ENABLED",
|
|
label: "Retry-After Provenance",
|
|
description:
|
|
"On aggregated 429/503 unavailable responses, omit Retry-After when no concrete future retry time is known (instead of a synthetic 1s), add error.retry_after_provenance (signal | none), and let combo drain paths read prose retry hints from JSON and plain-text upstream bodies.",
|
|
descriptionI18nKey: "featureFlagRetryAfterProvenanceEnabledDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "PROTECTED_PRIORITY_INFRA_502_ENABLED",
|
|
label: "Protected-Priority Infra Stops as 502",
|
|
description:
|
|
"When a priority combo target marked fallback-only-on-quota-exhaustion stops the combo for a cause that is provably not quota (provider circuit breaker open, predictive latency skip), answer 502 instead of the quota-looking 503. Lockout, cooldown, unavailable, exhaustion and concurrency-cap stops keep 503.",
|
|
descriptionI18nKey: "featureFlagProtectedPriorityInfra502EnabledDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "MISTRAL_AMBIGUOUS_401_SOFT_LOCKOUT",
|
|
label: "Mistral Ambiguous 401 Soft Lockout",
|
|
description:
|
|
'A bare Mistral 401 ({"detail":"Unauthorized"}, no explicit auth signal) is byte-identical for a revoked key and for exhausted quota. When enabled, such a 401 cools the connection down instead of parking it as expired, up to 3 times within an hour; the next one still parks it as expired, so a revoked key converges. Off by default: every bare Mistral 401 parks the connection as expired, as before.',
|
|
descriptionI18nKey: "featureFlagMistralAmbiguous401SoftLockoutDescription",
|
|
category: "runtime",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
|
|
// ──────────────── CLI (5) ────────────────
|
|
{
|
|
key: "CLI_COMPAT_ALL",
|
|
label: "CLI Compat All",
|
|
description: "Enable compatibility mode for all CLI clients",
|
|
descriptionI18nKey: "featureFlagCliCompatAllDescription",
|
|
category: "cli",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: true,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "MODEL_ALIAS_COMPAT_ENABLED",
|
|
label: "Model Alias Compat",
|
|
description: "Enable model alias compatibility layer",
|
|
descriptionI18nKey: "featureFlagModelAliasCompatEnabledDescription",
|
|
category: "cli",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "PRICING_SYNC_ENABLED",
|
|
label: "Pricing Sync",
|
|
description:
|
|
"Enable automatic pricing data synchronization (requires the PRICING_SYNC_ENABLED environment variable to be set to true)",
|
|
descriptionI18nKey: "featureFlagPricingSyncEnabledDescription",
|
|
category: "cli",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_AUTO_SYNC_CODEX_PROFILES",
|
|
label: "Auto-Sync Codex Profiles",
|
|
description:
|
|
"After a provider model sync, automatically (re)write ~/.codex/*.config.toml profile files from the live catalog. Never changes the active/default Codex config. Off by default.",
|
|
descriptionI18nKey: "featureFlagOmnirouteAutoSyncCodexProfilesDescription",
|
|
category: "cli",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_AUTO_SYNC_CLAUDE_PROFILES",
|
|
label: "Auto-Sync Claude Code Profiles",
|
|
description:
|
|
"After a provider model sync, automatically (re)write ~/.claude/profiles/'<name>'/settings.json Claude Code profiles from the live catalog. Never changes the active/default Claude config. Off by default.",
|
|
descriptionI18nKey: "featureFlagOmnirouteAutoSyncClaudeProfilesDescription",
|
|
category: "cli",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
|
|
// ──────────────── Health (3) ────────────────
|
|
{
|
|
key: "OMNIROUTE_DISABLE_LOCAL_HEALTHCHECK",
|
|
label: "Disable Local Health Check",
|
|
description: "Disable the local instance health check endpoint",
|
|
descriptionI18nKey: "featureFlagOmnirouteDisableLocalHealthcheckDescription",
|
|
category: "health",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "OMNIROUTE_DISABLE_TOKEN_HEALTHCHECK",
|
|
label: "Disable Token Health Check",
|
|
description: "Disable the token validation health check",
|
|
descriptionI18nKey: "featureFlagOmnirouteDisableTokenHealthcheckDescription",
|
|
category: "health",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
{
|
|
key: "SKILLS_SANDBOX_NETWORK_ENABLED",
|
|
label: "Skills Sandbox Network",
|
|
description: "Enable network access in the skills sandbox environment",
|
|
descriptionI18nKey: "featureFlagSkillsSandboxNetworkEnabledDescription",
|
|
category: "health",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "caution",
|
|
},
|
|
{
|
|
key: "PROXY_HEALTH_BLOCKED_RESETS_STREAK",
|
|
label: "Proxy Health: Refusal Resets Failure Streak",
|
|
description:
|
|
"In the proxy health sweep, let a probe the target refused (401/403/429: the proxy relayed, the destination refused this egress IP) reset the proxy's consecutive-failure streak, like a served probe. Off by default: a refusal stays neutral and keeps the streak (#10654). A 5xx stays inconclusive either way, and a refusal never removes, disables or re-activates a proxy.",
|
|
descriptionI18nKey: "featureFlagProxyHealthBlockedResetsStreakDescription",
|
|
category: "health",
|
|
defaultValue: "false",
|
|
type: "boolean",
|
|
requiresRestart: false,
|
|
warningLevel: "info",
|
|
},
|
|
];
|