From 754ba0fa86eb199bd0e6be062b02cbeaf39769a1 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Sun, 9 Aug 2026 15:16:55 -0300 Subject: [PATCH] fix(release): repair post-sweep base regressions --- .env.example | 273 +++++++++++++++--- .../release-v3850-post-sweep-locale-lint.md | 1 + config/quality/dependency-allowlist.json | 1 + config/quality/eslint-suppressions.json | 5 - config/quality/file-size-baseline.json | 19 +- config/quality/quality-baseline.json | 3 +- docs/openapi.yaml | 160 ++++++++++ docs/proposals/TELEGRAM-MINIAPP.md | 4 +- docs/reference/ENVIRONMENT.md | 147 ++++++++-- open-sse/config/constants.ts | 3 +- .../providers/registry/openference/index.ts | 4 +- .../compression/engines/cavemanAdapter.ts | 7 +- open-sse/utils/publicCreds.ts | 3 + package-lock.json | 228 +++++++++++++-- package.json | 33 ++- scripts/check/check-db-rules.mjs | 1 + scripts/check/check-migration-numbering.mjs | 12 +- src/app/api/telegram/update/route.ts | 3 +- src/i18n/messages/ar.json | 19 +- src/i18n/messages/az.json | 19 +- src/i18n/messages/bg.json | 19 +- src/i18n/messages/bn.json | 19 +- src/i18n/messages/cs.json | 19 +- src/i18n/messages/da.json | 19 +- src/i18n/messages/de.json | 19 +- src/i18n/messages/en.json | 123 +++++++- src/i18n/messages/es.json | 31 +- src/i18n/messages/fa.json | 19 +- src/i18n/messages/fi.json | 19 +- src/i18n/messages/fr.json | 177 ++++++------ src/i18n/messages/gu.json | 19 +- src/i18n/messages/he.json | 19 +- src/i18n/messages/hi.json | 19 +- src/i18n/messages/hu.json | 19 +- src/i18n/messages/id.json | 19 +- src/i18n/messages/in.json | 19 +- src/i18n/messages/it.json | 187 ++++++------ src/i18n/messages/ja.json | 19 +- src/i18n/messages/ko.json | 19 +- src/i18n/messages/mr.json | 19 +- src/i18n/messages/ms.json | 19 +- src/i18n/messages/nl.json | 19 +- src/i18n/messages/no.json | 19 +- src/i18n/messages/phi.json | 19 +- src/i18n/messages/pl.json | 19 +- src/i18n/messages/pt-BR.json | 115 +++++++- src/i18n/messages/pt.json | 19 +- src/i18n/messages/ro.json | 19 +- src/i18n/messages/ru.json | 179 ++++++------ src/i18n/messages/sk.json | 19 +- src/i18n/messages/sv.json | 19 +- src/i18n/messages/sw.json | 19 +- src/i18n/messages/ta.json | 19 +- src/i18n/messages/te.json | 19 +- src/i18n/messages/th.json | 19 +- src/i18n/messages/tr.json | 19 +- src/i18n/messages/uk-UA.json | 19 +- src/i18n/messages/ur.json | 19 +- src/i18n/messages/vi.json | 21 +- src/i18n/messages/zh-CN.json | 77 ++--- src/i18n/messages/zh-TW.json | 67 +++-- src/lib/db/migrationRunner.ts | 2 + src/lib/db/migrationRunner/constants.ts | 6 + ..._job_registry.sql => 146_job_registry.sql} | 2 +- src/lib/oauth/constants/oauth.ts | 2 +- src/lib/telegram/errorMessage.ts | 5 + .../check-db-rules-classification.test.ts | 3 +- tests/unit/check-migration-numbering.test.ts | 6 +- tests/unit/codebuddy-cn-provider.test.ts | 37 ++- ...ob-registry-migration-renumber-139.test.ts | 59 ++++ ...db-migrationrunner-constants-split.test.ts | 12 +- tests/unit/openference-oauth-provider.test.ts | 5 + tests/unit/publicCreds.test.ts | 6 + .../telegram-route-error-sanitization.test.ts | 18 ++ tests/unit/ui/resilience-connections.test.tsx | 7 +- 75 files changed, 2033 insertions(+), 667 deletions(-) create mode 100644 changelog.d/fixes/release-v3850-post-sweep-locale-lint.md rename src/lib/db/migrations/{139_job_registry.sql => 146_job_registry.sql} (97%) create mode 100644 src/lib/telegram/errorMessage.ts create mode 100644 tests/unit/db-job-registry-migration-renumber-139.test.ts create mode 100644 tests/unit/telegram-route-error-sanitization.test.ts diff --git a/.env.example b/.env.example index 3aecf2f17e..63a23d8801 100644 --- a/.env.example +++ b/.env.example @@ -67,6 +67,14 @@ DISABLE_SQLITE_AUTO_BACKUP=false # Used by: src/shared/utils/rateLimiter.ts # Example: redis://localhost:6379 (or redis://redis:6379 in Docker) # REDIS_URL=redis://localhost:6379 +# Host interface docker-compose publishes the Redis sidecar on. +# Default: 127.0.0.1 (loopback only). The compose Redis runs WITHOUT +# `requirepass`, and app containers reach it over the compose network +# (redis:6379) — the published port is only for host-side tooling. Setting this +# to 0.0.0.0 exposes an unauthenticated Redis to your whole LAN. +# REDIS_BIND_HOST=127.0.0.1 +# Host port for the compose Redis sidecar. Default: 6379. +# REDIS_PORT=6379 # ═══════════════════════════════════════════════════════════════════════════════ # 3. NETWORK & PORTS @@ -337,14 +345,18 @@ ALLOW_API_KEY_REVEAL=false # OMNIROUTE_CHAT_HEAVY_TOOL_COUNT=64 # Conservative string-size token estimate that classifies a request as heavyweight. Default 32000. # OMNIROUTE_CHAT_HEAVY_ESTIMATED_TOKENS=32000 -# Hard message-count cap; excess receives compact-required 413. Default 800. -# OMNIROUTE_CHAT_HARD_MAX_MESSAGES=800 +# Optional opt-in hard message-count cap; excess receives compact-required 413 before +# compression can run. Unset/0 (the default) means no history cap: heap growth is bounded +# by OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT and the heap-pressure shed instead. Set a positive +# value only on memory-constrained deployments that need a hard ceiling. +# OMNIROUTE_CHAT_HARD_MAX_MESSAGES=0 # Hard cap (bytes) for a non-streaming upstream response buffered fully into memory # (#5152). Past this the upstream reader is cancelled and the request fails fast # instead of growing an unbounded string until the V8 heap is exhausted. # Used by: open-sse/handlers/chatCore/nonStreamingResponseBody.ts # Default: 67108864 (64 MB) +# OMNIROUTE_FORWARDING_HEADER_BUDGET_BYTES=768 # OMNIROUTE_MAX_NONSTREAMING_RESPONSE_BYTES=67108864 # CORS configuration — controls which cross-origin browser clients can call the API. @@ -445,6 +457,13 @@ ALLOW_API_KEY_REVEAL=false # Default: false # OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS=false +# Per-model concurrency cap for round-robin combos (#9100). +# Used by: open-sse/services/comboConfig.ts — the round-robin combo semaphore +# was hard-capped at 3 concurrent requests per model with no override, which +# serialized higher-concurrency traffic behind that cap. +# Validated to >= 1, clamped to <= 32. | Default: 3 +# COMBO_CONCURRENCY_PER_MODEL=3 + # ═══════════════════════════════════════════════════════════════════════════════ # 7. URLS & CLOUD SYNC # ═══════════════════════════════════════════════════════════════════════════════ @@ -520,16 +539,6 @@ NEXT_PUBLIC_BASE_URL=http://localhost:20128 # cost of more upstream polling; raise to reduce request volume. # OMNIROUTE_CGPT_WEB_PRO_POLL_INTERVAL_MS=4000 -# Timeout for the /api/jobs/:id/run-now endpoint, in milliseconds. -# This bounds the CALL, not the job. runNow() dispatches the handler with -# `void` and returns as soon as it has decided to start, so on the normal -# path it resolves in milliseconds. It only matters when the job is already -# running: runNow() then waits for the in-flight run before starting the -# queued one, and this timeout prevents that wait from hanging forever. -# Used by: src/app/api/jobs/[id]/run-now/route.ts -# Default: 30000 (30 seconds) -# OMNIROUTE_RUNNOW_TIMEOUT_MS=30000 - # Public cloud URL — client-side mirror of CLOUD_URL. NEXT_PUBLIC_CLOUD_URL= @@ -788,6 +797,16 @@ PROVIDER_LIMITS_SYNC_SPACING_MS=1500 # Disable the proactive recovery scheduler entirely (default: false). # OMNIROUTE_DISABLE_CONNECTION_RECOVERY=false +# Proactive Claude warmup scheduler (#8848): fires a trivial request to opted-in +# OAuth connections on a cron schedule (America/Los_Angeles) so accounts do not +# hit the 5-hour sliding window cold. Off by default — set ENABLED=1 and flip +# per-connection flags in settings.claudeWarmup.connections to activate. +# Used by: src/lib/warmupScheduler.ts. +# OMNIROUTE_WARMUP_ENABLED=false +# OMNIROUTE_WARMUP_CRON="0 7 * * *" +# OMNIROUTE_WARMUP_CONCURRENCY=3 +# OMNIROUTE_WARMUP_MODEL= + # Background job interval for budget reset checks (ms). Default: 600000 (10m). # Used by: src/lib/jobs/budgetResetJob.ts. Floor: 10000. #OMNIROUTE_BUDGET_RESET_JOB_INTERVAL_MS=600000 @@ -852,6 +871,12 @@ PROVIDER_LIMITS_SYNC_SPACING_MS=1500 # (>= 3 retrievals = never compressed). 1 disables the ramp (binary skip at the threshold only). # Used by: open-sse/services/compression/engines/ccr/index.ts. Default: 2. #COMPRESSION_CCR_RETRIEVAL_RAMP_FACTOR=2 +# CCR durable block store (#9061). The in-memory store loses blocks to LRU eviction, the TTL, a +# restart, or a retrieve landing on another instance, while the model is told it can retrieve them +# verbatim. Set to false to keep blocks in memory only, at the cost of that promise. Blocks over +# 512KB and cloud runtimes are memory-only regardless. +# Used by: open-sse/services/compression/engines/ccr/index.ts. Default: true. +#COMPRESSION_CCR_DURABLE_STORE=true # T08/H5 — usage-observed prefix freeze (OPT-IN, default off). When enabled, a system prompt seen # >= THRESHOLD times is treated as a stable cacheable prefix and preserved from compression even # for providers the static cache-aware heuristic does not recognize (freeze = preserve, never @@ -1036,6 +1061,17 @@ GITHUB_OAUTH_CLIENT_ID=Iv1.b507a08c87ecfe98 # VISION_BRIDGE_BASE_URL= # VISION_BRIDGE_API_KEY= +# ── Raycast Pro (local auto-import) ── +# Raycast Pro AI is a reverse-engineered, unofficial API — local/personal use +# only (no OAuth client_id/secret; token is captured via macOS Auto-Import +# from the Keychain + local Raycast SQLite DB, or pasted manually). These +# vars are optional manual overrides used by open-sse/services/raycast.ts +# and the direct-probe benchmark script scripts/raycast/usage-benchmark.mjs. +# RAYCAST_BEARER_TOKEN= +# RAYCAST_DEVICE_ID= +# RAYCAST_AID= +# RAYCAST_SIG_SECRET= + # ───────────────────────────────────────────────────────────────────────────── # ⚠️ GOOGLE OAUTH (Antigravity) & OTHER PROVIDERS — REMOTE SERVERS # ───────────────────────────────────────────────────────────────────────────── @@ -1176,6 +1212,17 @@ CURSOR_USER_AGENT="Cursor/3.4" # fallback when FETCH_TIMEOUT_MS is unset. Default: 120000 (2 min). # OMNIROUTE_DEFAULT_FETCH_TIMEOUT_MS=120000 +# ── Proxy/relay fetch (connection pooling, #9158) ── +# Used by: open-sse/utils/proxyFetch.ts. +# A hung relay must fail BEFORE the client/agent timeout (typically 30s) so the +# caller sees a relay-specific failure instead of a generic upstream timeout. +# Capped at 29000ms so this timeout always fires first. Default: 25000 (25s). +# OMNIROUTE_RELAY_FETCH_TIMEOUT_MS=25000 + +# Shared retry backoff (ms) for the direct/relay/proxy retry-once paths. +# 0 = retry immediately. Default: 10. +# OMNIROUTE_RETRY_BACKOFF_MS=10 + # ── Firecrawl web-fetch executor ── # Point at a self-hosted Firecrawl instance (defaults to the public cloud API). # When set to a non-cloud base URL, the API key becomes optional. @@ -1237,6 +1284,14 @@ CURSOR_USER_AGENT="Cursor/3.4" # OMNIROUTE_BROWSER_POOL=on # WEB_COOKIE_USE_BROWSER=0 +# ── Adobe Firefly browser sign-in (system Chrome/Edge CDP) ── +# Used by: open-sse/services/adobeFireflyBrowserLogin.ts. The Firefly login +# flow drives a real, system-installed Chrome or Microsoft Edge via CDP so the +# user can sign in interactively; the executable is auto-detected from common +# install paths per OS. Set this to override that detection (e.g. a portable +# install or a non-standard path) when auto-detection fails. +# OMNIROUTE_LOGIN_BROWSER_PATH= + # ── Circuit breaker thresholds and reset windows ── # Used by: open-sse/config/constants.ts → src/lib/resilience/settings.ts. # Defaults match historical PROVIDER_PROFILES values (post-scaling for @@ -1348,6 +1403,10 @@ APP_LOG_TO_FILE=true # Default: 100000 # CALL_LOGS_TABLE_MAX_ROWS=100000 +# Force detailed request logging on or off, overriding the dashboard setting. +# Values: true | false | Default: unset (follow dashboard setting) +# ENABLE_REQUEST_LOGS=false + # Maximum age for orphaned active request log entries before the in-memory # pending-request reaper removes them. Accepts milliseconds. # Default: 3600000 (1 hour) @@ -1367,10 +1426,9 @@ APP_LOG_TO_FILE=true # bodies is retained in the database. # Used by: open-sse/handlers/chatCore.ts — cloneBoundedChatLogPayload() # CHAT_LOG_TEXT_LIMIT=65536 # Max string length before truncation (default: 64 KB) -# CHAT_LOG_ARRAY_TAIL_ITEMS=128 # Number of array items retained from tail (default: 128) +# CHAT_LOG_ARRAY_TAIL_ITEMS=128 # Number of array items retained from tail (default: 128) # CHAT_LOG_MAX_DEPTH=6 # Max nesting depth before truncation (default: 6) # CHAT_LOG_MAX_OBJECT_KEYS=80 # Max object keys retained (default: 80, 0 = no limit) -# CHAT_LOG_MAX_BODY_KB=1024 # Max request/response body size before summarizing, in KB (default: 1024) # Maximum rows in the proxy_logs SQLite table. # Default: 100000 @@ -1425,10 +1483,6 @@ APP_LOG_TO_FILE=true # Default: ~/.omniroute/plugins/ Override in dev/CI to point at a local plugin tree. # OMNIROUTE_PLUGIN_PATH= -# Allow plugins to request the 'exec' permission (spawn child processes from the -# plugin worker sandbox). Disabled by default; set to 1 to enable (local operator only). -# OMNIROUTE_PLUGINS_ALLOW_EXEC=0 - # ── Prompt cache (system prompt deduplication) ── # Used by: open-sse/services — caches identical system prompts across requests. # PROMPT_CACHE_MAX_SIZE=50 # Max cached entries (default: 50) @@ -1486,6 +1540,15 @@ APP_LOG_TO_FILE=true # ═══════════════════════════════════════════════════════════════════════════════ # 19. MODEL SYNC (Dev) # ═══════════════════════════════════════════════════════════════════════════════ +# Enable the models.dev capability sync. Default: false (opt-in only). +# Also settable from Dashboard > Settings > AI. This variable wins over that +# setting whenever it is set to anything non-empty, in either direction, so a +# deployment can pin the sync on or off without depending on database state +# surviving a rebuild. Leave it unset to let the dashboard toggle decide. +# On: 1, true, yes or on (any casing). Any other value is off. +# Used by: src/lib/modelsDevSync.ts +# MODELS_DEV_SYNC_ENABLED=false + # Development-time model catalog sync interval in seconds. # Used by: src/lib/modelsDevSync.ts # Default: 86400 (24 hours) @@ -1508,6 +1571,14 @@ APP_LOG_TO_FILE=true # Default: 86400000 (24 hours) # OPENROUTER_CATALOG_TTL_MS=86400000 +# Enrich the dashboard providers list with OpenRouter weekly ranking stats. +# ON by default; set false to skip the background fetch entirely (#9324). +# Used by: src/lib/catalog/openrouterProviderStats.ts +# OPENROUTER_PROVIDER_STATS_ENABLED=true +# Cache TTL for the OpenRouter provider stats snapshot, in ms. +# Default: 86400000 (24 hours) +# OPENROUTER_PROVIDER_STATS_TTL_MS=86400000 + # ── Model catalog response shape ── # Include display-friendly name fields in /v1/models responses. # Disable for clients that expect model IDs only. @@ -1522,25 +1593,19 @@ APP_LOG_TO_FILE=true # NANOBANANA_POLL_TIMEOUT_MS=120000 # Max wait for job completion (default: 120s) # NANOBANANA_POLL_INTERVAL_MS=2500 # Poll frequency (default: 2.5s) -# ── Adobe Firefly (Image / Video Generation) ── -# Optional absolute path to a system Chrome or Edge executable used for interactive sign-in -# and off-screen risk-session renewal. Auto-detected when unset. -# OMNIROUTE_LOGIN_BROWSER_PATH= -# Browser renewal and durable session cache are enabled by default; set either to 0 to opt out. -# ADOBE_FIREFLY_BROWSER_REFRESH=1 -# ADOBE_FIREFLY_SESSION_DISK=1 -# Minimum gap between generate submissions and extra gap after every third success (ms). -# ADOBE_FIREFLY_MIN_SUBMIT_GAP_MS=12000 -# ADOBE_FIREFLY_BATCH_EXTRA_GAP_MS=15000 -# Base backoff after a transient 408 response (ms); five attempts maximum. -# ADOBE_FIREFLY_SUBMIT_BASE_DELAY_MS=8000 - # ── Microsoft Designer Web (Image Generation) ── # Polling config for the microsoft-designer-web submit-then-poll image job. # Used by: open-sse/handlers/imageGeneration/providers/designerWeb.ts # DESIGNER_WEB_POLL_TIMEOUT_MS=60000 # Max wait for job completion (default: 60s) # DESIGNER_WEB_POLL_INTERVAL_MS=2000 # Poll frequency (default: 2s) +# ── Adobe Firefly (Image Upscale) ── +# Base delay (ms) for the submit-retry exponential backoff when Adobe Firefly's +# upscale job submission is rate-limited. Used by: +# open-sse/services/adobeFireflyUpscale.ts::submitRetryDelayMs. +# Default: 8000 (20 under NODE_ENV=test/VITEST/NODE_TEST_CONTEXT). +# ADOBE_FIREFLY_SUBMIT_BASE_DELAY_MS=8000 + # ── AWS Bedrock (Kiro / Audio) ── # Region used to construct AWS Bedrock endpoints. Used by: # src/lib/providers/validation.ts and open-sse/handlers/audioSpeech.ts. @@ -1635,6 +1700,26 @@ APP_LOG_TO_FILE=true # Used by: src/lib/services/bootstrap.ts, src/app/api/services/mux/_lib.ts # MUX_SERVICE_PORT=8322 +# ── Dario embedded service ── +# Override the host/port the embedded Dario (Claude Code subscription proxy) +# daemon binds to and is reached at. Always bound to 127.0.0.1 — never +# configurable to 0.0.0.0. Rarely needed — defaults to 127.0.0.1:3456. +# Used by: src/lib/services/installers/dario.ts, src/lib/services/bootstrap.ts, +# src/app/api/services/dario/_lib.ts, src/app/api/services/dario/admin/_lib.ts, +# open-sse/executors/dario.ts +# DARIO_HOST=127.0.0.1 +# DARIO_PORT=3456 + +# ── Dario embedded service ── +# Override the host/port the embedded Dario (Claude Code subscription proxy) +# daemon binds to and is reached at. Always bound to 127.0.0.1 — never +# configurable to 0.0.0.0. Rarely needed — defaults to 127.0.0.1:3456. +# Used by: src/lib/services/installers/dario.ts, src/lib/services/bootstrap.ts, +# src/app/api/services/dario/_lib.ts, src/app/api/services/dario/admin/_lib.ts, +# open-sse/executors/dario.ts +# DARIO_HOST=127.0.0.1 +# DARIO_PORT=3456 + # ── Local hostnames (Docker networking) ── # Comma-separated additional hostnames treated as "local" for provider routing. # Used by: open-sse/config/providerRegistry.ts — allows Docker service names. @@ -1867,6 +1952,18 @@ APP_LOG_TO_FILE=true # ── Devin CLI binary path ── # Used by: open-sse/executors/devin-cli.ts. Default: looked up via PATH. # CLI_DEVIN_BIN=devin +# Agentic bridge-only binary override. The bridge still executes ACP stdio only. +# CLI_DEVIN_AGENTIC_BIN=devin +# Required isolated HOME for the agentic Devin child process. +# DEVIN_AGENTIC_HOME=/home/bridge +# Bounded ACP turn timeout in milliseconds. Default: 120000. +# DEVIN_AGENTIC_ACP_TIMEOUT_MS=120000 +# Agentic bridge model aliases. Values must keep the devin-cli-agentic/ prefix. +# DEVIN_BRIDGE_MODEL=devin-cli-agentic/swe-1-7 +# DEVIN_BRIDGE_SONNET_MODEL=devin-cli-agentic/swe-1-7 +# DEVIN_BRIDGE_OPUS_MODEL=devin-cli-agentic/swe-1-7 +# DEVIN_BRIDGE_HAIKU_MODEL=devin-cli-agentic/swe-1-7 +# DEVIN_BRIDGE_SUBAGENT_MODEL=devin-cli-agentic/swe-1-7 # ── Command Code (custom CLI) callback ── # Local port used for OAuth-style callbacks from the Command Code CLI helper. @@ -1921,6 +2018,15 @@ APP_LOG_TO_FILE=true # CHANGELOG_BASE_REF=origin/release/v0.0.0 # ALLOW_CHANGELOG_REMOVALS=1 +# ── Remote audio provider nodes ── +# Used by: src/app/api/v1/_shared/audioProviderNodes.ts — lets the /v1/audio/* +# routes use an OpenAI-compatible provider node hosted outside localhost. +# OFF by default: routing audio to a remote host changes egress identity, so it +# must be an explicit operator decision. Loopback/private nodes (localhost, +# 127.0.0.1, 172.16-31.x) are always allowed and unaffected by this flag. +# When enabled, the node authenticates with the API key stored on its connection. +# AUDIO_REMOTE_PROVIDER_NODES=false + # ── 1Proxy egress pool ── # Used by: src/lib/oneproxySync.ts — fetches proxy nodes from the OmniRoute # CrofAI 1Proxy service. Disable, override URL, or tune the import quality. @@ -2128,6 +2234,11 @@ PLAYGROUND_COMPARE_MAX_COLUMNS=4 # MEMORY_TYPED_DECAY_EPISODIC_DAYS=30 # episodic TTL in days; 0 = episodic immune too # MEMORY_TYPED_DECAY_ACCESS_IMMUNITY=3 # access_count >= N → immune; 0 disables access immunity # MEMORY_TYPED_DECAY_SWEEP_INTERVAL=0 # periodic sweep interval (seconds); 0 = no periodic sweep +# ─── Memory Backend Connectors (Generic HTTP) ────────────────────────────── +# NOTION_API_KEY= +# NOTION_API_URL= +# OBSIDIAN_API_KEY= +# OBSIDIAN_API_URL= # AgentBridge + Traffic Inspector (Group A) # AgentBridge @@ -2143,6 +2254,15 @@ INSPECTOR_MAX_BODY_KB=1024 INSPECTOR_MASK_SECRETS=true INSPECTOR_LLM_HOSTS_EXTRA= INSPECTOR_INTERNAL_INGEST_TOKEN= +# Shared secret for identity-preserving internal REST hops (#9260): when an +# OmniRoute component calls another local OmniRoute route, this token (sent as +# x-omniroute-internal-service-token) marks the request as internal so the +# original caller identity is preserved. OPT-IN: unset disables the mechanism. +# Used by: src/lib/api/internalServiceAuth.ts +# OMNIROUTE_INTERNAL_SERVICE_TOKEN= +# File-based variant (secret-file pattern; wins only when the inline var is +# unset): path to a file whose trimmed content is the token. +# OMNIROUTE_INTERNAL_SERVICE_TOKEN_FILE= # Quota Sharing (Group B — planos 16+22) QUOTA_STORE_DRIVER=sqlite # sqlite | redis # QUOTA_STORE_REDIS_URL= # ex.: redis://localhost:6379 (apenas quando driver=redis) @@ -2253,6 +2373,11 @@ QUOTA_STORE_DRIVER=sqlite # sqlite | redis # Host port for the 1-click Redis launcher. Default: 6379. Bump if the host # already binds 6379. The container's internal port stays 6379. # OMNIROUTE_REDIS_HOST_PORT= +# Host interface the 1-click Redis launcher publishes on. Default: 127.0.0.1 +# (loopback only). The launcher starts Redis WITHOUT a password, so binding +# 0.0.0.0 hands every host on your LAN an unauthenticated Redis — only widen +# this if you also set a password on the instance yourself. +# OMNIROUTE_REDIS_BIND_HOST= # Redis image used by the 1-click Redis launcher. Default: redis:7-alpine. # Override to redis:8-alpine or a private registry mirror as needed. # OMNIROUTE_REDIS_IMAGE= @@ -2355,20 +2480,80 @@ QUOTA_STORE_DRIVER=sqlite # sqlite | redis # ───────────────────────────────────────────────────────────────────────────── # VIBEPROXY_DATA_DIR= -# ───────────────────────────────────────────────────────────────────────────── -# Telegram Mini App (inbound bot webhook + Mini App chat) -# Used by: src/lib/telegram/*, src/app/api/telegram/update/route.ts -# ───────────────────────────────────────────────────────────────────────────── -# Bot token from @BotFather (:). Enables the inbound -# update webhook and doubles as the HMAC secret for Mini App initData -# verification. When unset, /api/telegram/update returns 503. +# ── Internal service auth (management-plane service-to-service calls) ───────── +# Inline token for internal service authentication; prefer the _FILE variant in +# containerized deployments so the secret never lands in the environment table. +# OMNIROUTE_INTERNAL_SERVICE_TOKEN= +# Path to a file containing the internal service token (overrides the inline var). +# OMNIROUTE_INTERNAL_SERVICE_TOKEN_FILE= + +# ═══════════════════════════════════════════════════════════════════════════════ +# 26. RADAR FEED (SELF-HOSTING) +# ═══════════════════════════════════════════════════════════════════════════════ +# Optional add-on (feature flag RADAR_ENABLED, default off — see feature flag +# settings, not an env var) that overlays a signed, freshly-curated free-model +# catalog on top of the release baseline. All four variables below are optional +# and only needed to point the client at a self-hosted/forked feed or +# supporter-key flow instead of the default OmniRoute Radar service. Used by: +# src/lib/radar/sync.ts, src/lib/radar/pinnedKeys.ts, src/lib/radar/links.ts. + +# Base URL of the Radar feed service. Overrides the built-in default so forks +# and self-hosters can point at their own signed feed. +# RADAR_FEED_URL=https://radar.omniroute.online + +# Ed25519 public key (base64-DER SPKI or PEM) used to verify the feed +# signature, replacing the pinned default key. Required when self-hosting a +# feed signed with a different key pair. +# RADAR_FEED_PUBKEY= + +# URL the dashboard's "I'm a contributor" button opens (GitHub OAuth +# supporter-key claim flow). No pricing/value lives in this repo — only the +# link. +# RADAR_CONTRIBUTOR_CLAIM_URL=https://radar.omniroute.online/auth/github + +# URL the dashboard's "Support the project" button opens (payment/plans +# page). No pricing/value lives in this repo — only the link. +# RADAR_SUPPORTER_PLANS_URL=https://radar.omniroute.online/planos + +# ═══════════════════════════════════════════════════════════════════════════════ +# 27. RELEASE v3.8.50 ADDITIONS +# ═══════════════════════════════════════════════════════════════════════════════ + +# Heavy chat admission queue wait before returning retryable 503. Set 0 for the +# legacy immediate rejection. Used by: src/shared/middleware/chatBodyAdmission.ts. +# Default: 5000 (5 seconds) +# OMNIROUTE_CHAT_ADMISSION_QUEUE_MS=5000 + +# Timeout for /api/jobs/:id/run-now while it waits for an in-flight run. +# Used by: src/app/api/jobs/[id]/run-now/route.ts. Default: 30000 (30 seconds) +# OMNIROUTE_RUNNOW_TIMEOUT_MS=30000 + +# Maximum request/response body size before chat-log summarization, in KiB. +# Used by: src/lib/chatLogTruncation.ts. Default: 1024 +# CHAT_LOG_MAX_BODY_KB=1024 + +# Adobe Firefly browser renewal and durable session cache (enabled by default). +# Used by: open-sse/services/adobeFireflySession.ts. +# ADOBE_FIREFLY_BROWSER_REFRESH=1 +# ADOBE_FIREFLY_SESSION_DISK=1 +# Minimum spacing between submissions and the extra pause after every third success. +# ADOBE_FIREFLY_MIN_SUBMIT_GAP_MS=12000 +# ADOBE_FIREFLY_BATCH_EXTRA_GAP_MS=15000 +# Chrome CDP runtime used by Adobe Firefly renewal. True headless is debug-only: +# Adobe colligo normally rejects risk tokens minted without a headed browser. +# ADOBE_FIREFLY_CHROME_CDP_PORT=9334 +# ADOBE_FIREFLY_CHROME_VISIBLE=0 +# ADOBE_FIREFLY_CHROME_HEADLESS=0 +# ADOBE_FIREFLY_CHROME_FORCE_RESTART=0 +# ADOBE_FIREFLY_CHROME_PING=auto +# ADOBE_FIREFLY_LOGIN_WAIT_MS=0 +# ADOBE_FIREFLY_FORTER_WAIT_MS=45000 +# Optional absolute Chrome executable; auto-detected when unset. +# CHROME_PATH= + +# Telegram Mini App bridge. The update endpoint remains disabled while the bot +# token is unset. Used by: src/lib/telegram/* and src/app/api/telegram/update/route.ts. # TELEGRAM_BOT_TOKEN= - -# Model used for Telegram chat replies (default: auto/chat). # TELEGRAM_DEFAULT_MODEL=auto/chat - -# Bot API base URL override (for proxies/self-hosted Bot API servers). # TELEGRAM_BOT_API_BASE=https://api.telegram.org - -# Timeout (ms) for outbound Bot API calls (sendMessage/setWebhook). # TELEGRAM_WEBHOOK_TIMEOUT_MS=60000 diff --git a/changelog.d/fixes/release-v3850-post-sweep-locale-lint.md b/changelog.d/fixes/release-v3850-post-sweep-locale-lint.md new file mode 100644 index 0000000000..3377f5c04a --- /dev/null +++ b/changelog.d/fixes/release-v3850-post-sweep-locale-lint.md @@ -0,0 +1 @@ +- Repair release-sweep regressions in locale and environment contracts, package metadata, scripts, dependency, size and dead-code ratchets, OpenAPI coverage, Telegram error sanitization, Openference public-credential handling, DB-module classification, resilience UI test assertions, strict CodeBuddy CN tests, Lite compression typing, and the job-registry migration number. diff --git a/config/quality/dependency-allowlist.json b/config/quality/dependency-allowlist.json index 842eb696f3..ce8d808361 100644 --- a/config/quality/dependency-allowlist.json +++ b/config/quality/dependency-allowlist.json @@ -115,6 +115,7 @@ "recharts", "safe-regex", "selfsigned", + "sharp", "size-limit", "smol-toml", "socks", diff --git a/config/quality/eslint-suppressions.json b/config/quality/eslint-suppressions.json index f5a0417997..76f8b0c13e 100644 --- a/config/quality/eslint-suppressions.json +++ b/config/quality/eslint-suppressions.json @@ -2036,11 +2036,6 @@ "count": 3 } }, - "tests/unit/codebuddy-cn-provider.test.ts": { - "@typescript-eslint/no-explicit-any": { - "count": 3 - } - }, "tests/unit/codex-banked-reset-credits-5199.test.ts": { "@typescript-eslint/no-explicit-any": { "count": 7 diff --git a/config/quality/file-size-baseline.json b/config/quality/file-size-baseline.json index 852455a288..cc9cab5e81 100644 --- a/config/quality/file-size-baseline.json +++ b/config/quality/file-size-baseline.json @@ -163,9 +163,11 @@ "_rebaseline_2026_06_20_4389_thinking_toolchoice": "Re-baseline base.ts 1387->1399 (#4389): tool_choice-forced thinking guard at the existing Claude wire-image injection chokepoint (effThinking gate avoids the Anthropic 400 when tool_choice forces a tool). Cohesive guard; structural shrink tracked in #3501.", "_rebaseline_2026_07_18_6979_codex_test": "PR #6979 own growth: executor-codex.test.ts 1340->1347 (+7 = generalized ensureThinkingBudget assertion added to the existing codex thinking-budget cases). antigravity-test bump 942->977 REVERTED here: #7408's test split dropped that file to 888, so this PR's +35 fits under the original 942 frozen cap.", "_rebaseline_2026_07_24_8354_logs_timeline_sidebar": "PR #8354 (hartmark, feature/scrolling-log) own growth: src/shared/constants/sidebarVisibility/sections.ts 812->820 (+8, the single new logs-timeline SidebarItemDefinition entry added to LOGS_GROUP.items for the new /dashboard/logs/timeline scrolling request-timeline page). Irreducible data-literal wiring at the existing sidebar-sections chokepoint, same shape as every other item in the file; not extractable without an ad-hoc single-item exception to the file's otherwise-uniform multi-line item style.", + "_rebaseline_2026_08_09_v3850_post_sweep_tip": "Release-captain reconciliation of absolute file-size drift on pure tip 382449d593 after the authorized cherry-pick wave. The affected production growth already belongs to merged, tested commits: Adobe Firefly CDP/session recovery (#9881), model capability serialization (#9296), Modality Bridge request wiring (#9759), disconnect-grace/reasoning-cache chatCore wiring (#9653/#9183), stacked Lite precedence, and Responses tool-call index/argument handling (#9843 plus the release translator fixes). This repair adds only the compact migration-146 retroactive guard, covered by db-job-registry-migration-renumber-139.test.ts. Values are the exact check:file-size split-newline measurements and remain shrink-only; structural decomposition remains tracked by the existing #3501 notes.", "cap": 1000, "testCap": 1000, "testFrozen": { + "tests/unit/adobe-firefly.test.ts": 1136, "tests/unit/reasoning-cache.test.ts": 1035, "_rebaseline_2026_06_27_5193_antigravity_test": "#5193 own test growth: oauth-providers-config.test.ts 870->873 (+3: antigravity projectId assertion + 50ms tick for the now fire-and-forget onboarding, matching the no-PKCE/no-openid flow).", "_rebaseline_2026_07_02_5928_base_red": "web-cookie-providers-new.test.ts 845->850: #5928 (test(security) Kimi Web URL host parse, CodeQL #689) grew the file +5 lines and merged into release/v3.8.44 WITHOUT rebaselining, leaving a fast-gates base-red that blocked every subsequent PR->release. Test growth is legitimate (a security regression test); maintainer absorbs the drift here. Frozen at 850.", @@ -355,7 +357,7 @@ "open-sse/executors/deepseek-web.ts": 1148, "open-sse/executors/grok-web.ts": 1044, "open-sse/executors/muse-spark-web.ts": 1405, - "open-sse/handlers/chatCore.ts": 5042, + "open-sse/handlers/chatCore.ts": 5050, "open-sse/handlers/imageGeneration.ts": 3101, "open-sse/handlers/responseSanitizer.ts": 1128, "open-sse/handlers/search.ts": 1536, @@ -364,12 +366,15 @@ "open-sse/mcp-server/server.ts": 1448, "open-sse/mcp-server/tools/advancedTools.ts": 1120, "open-sse/services/accountFallback.ts": 1978, - "open-sse/services/adobeFireflyClient.ts": 2385, + "open-sse/services/adobeFireflyBrowserLogin.ts": 1362, + "open-sse/services/adobeFireflyChromeRuntime.ts": 1201, + "open-sse/services/adobeFireflyClient.ts": 2999, + "open-sse/services/adobeFireflySession.ts": 1003, "open-sse/services/claudeCodeCompatible.ts": 1202, "open-sse/services/combo.ts": 3648, - "open-sse/services/compression/strategySelector.ts": 1060, + "open-sse/services/compression/strategySelector.ts": 1061, "open-sse/services/rateLimitManager.ts": 1167, - "open-sse/translator/response/openai-responses.ts": 1224, + "open-sse/translator/response/openai-responses.ts": 1271, "open-sse/utils/cursorAgentProtobuf.ts": 1505, "open-sse/utils/stream.ts": 2889, "src/app/(dashboard)/dashboard/HomePageClient.tsx": 1388, @@ -393,10 +398,10 @@ "src/app/(dashboard)/dashboard/usage/components/EvalsTab.tsx": 2148, "src/app/(dashboard)/dashboard/usage/components/ProviderLimits/index.tsx": 1119, "src/app/api/providers/[id]/models/route.ts": 2361, - "src/app/api/v1/models/catalog.ts": 1590, + "src/app/api/v1/models/catalog.ts": 1597, "src/lib/db/apiKeys.ts": 1529, "src/lib/db/core.ts": 1639, - "src/lib/db/migrationRunner.ts": 1094, + "src/lib/db/migrationRunner.ts": 1101, "src/lib/db/models.ts": 1097, "src/lib/db/providers.ts": 1034, "src/lib/memory/retrieval.ts": 1073, @@ -406,7 +411,7 @@ "src/shared/components/RequestLoggerV2.tsx": 1629, "src/shared/components/analytics/charts.tsx": 1035, "src/shared/services/cliRuntime.ts": 1122, - "src/sse/handlers/chat.ts": 1904, + "src/sse/handlers/chat.ts": 1918, "src/sse/services/auth.ts": 2508, "tests/unit/account-fallback-service.test.ts": 1572, "tests/unit/provider-validation-specialty.test.ts": 2985, diff --git a/config/quality/quality-baseline.json b/config/quality/quality-baseline.json index 2fe9c2c4e0..d127a83fb2 100644 --- a/config/quality/quality-baseline.json +++ b/config/quality/quality-baseline.json @@ -101,8 +101,9 @@ "_rebaseline_2026_07_28_v3849_release": "75.5 -> 99 (+23.5). Aperto EXIGIDO pelo modo --require-tighten do ratchet: a métrica melhorou de verdade no ciclo v3.8.49. A causa é o workflow assíncrono de tradução, que finalmente alcançou o denominador em EN — as rebaselines anteriores (v3.8.39/.44/.47) foram todas afrouxamentos registrando o atraso das traduções, e agora ele foi pago. O coletor SUBTRAI os placeholders (present - placeholder em scripts/quality/collect-metrics.mjs), então os 317 marcadores __MISSING__ que esta release introduziu para o drift de valor já estão descontados dos 99 — o número é honesto, não inflado por placeholder. Medido pelo collect-metrics do CI no run 30404226939." }, "deadExports": { - "value": 227, + "value": 230, "direction": "down", + "_rebaseline_2026_08_09_v3850_post_sweep": "227 -> 230. Measured by npm run check:dead-code on the unmodified release/v3.8.50 tip 382449d593 during the mandatory --full-ci pre-flight. The +3 is inherited cycle drift from the authorized merge sweep; this repair adds no production exports. Rebaseline records the actual tip so ci.yml quality-gate can run, while structural cleanup remains separate debt.", "_rebaseline_2026_07_01_v3843_release": "225->227 (+2). v3.8.43 cycle drift, surfaced in the Quality Ratchet job after eslintWarnings was rebaselined (check:dead-code runs there). 227 = measured by check:dead-code (knip) on the release tip 4635076eb. The 5 CI fixes add 0 dead exports: safeHttpHref in linkify.ts is module-local AND used (called by linkifyText); no new exports; test files are not scanned. Tighten via --update next cycle.", "dedicatedGate": true, "_rebaseline_2026_06_30_v3842_deadcode_wave": "310 -> 225. Measured by `node scripts/check/check-dead-code.mjs` on the v3.8.42 tip after the JxnLexn dead-code (#5463/#5464/#5466) + duplication (#5471..#5500) wave landed: DEAD_EXPORTS=133 + DEAD_FILES=92 = 225. The stale 310 was the v3.8.38 release snapshot never ratcheted on PR->release fast-gates (check:dead-code runs only on ci.yml PR->main, not quality.yml). Tightening to the true measured value; release-time captain rebaselines up if parallel cycle merges add dead exports.", diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 27e1d37cc8..ae0ca05c56 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -5225,6 +5225,102 @@ paths: "200": description: Sync initialized + # ─── Background Jobs (local-only administration) ─────────────── + + /api/jobs: + get: + tags: [System] + summary: List registered background jobs + description: Local-only runtime administration. Returns each registered job and its latest run. + x-internal: true + responses: + "200": + description: Registered jobs + "500": + description: Failed to list jobs + + /api/jobs/{id}/enable: + post: + tags: [System] + summary: Enable a background job + description: Local-only runtime administration. Enables the job and restarts its timer. + x-internal: true + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + "200": + description: Job enabled + "404": + description: Job not found + "500": + description: Failed to enable job + + /api/jobs/{id}/disable: + post: + tags: [System] + summary: Disable a background job + description: Local-only runtime administration. Disables the job and stops its timer. + x-internal: true + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + "200": + description: Job disabled + "404": + description: Job not found + "500": + description: Failed to disable job + + /api/jobs/{id}/run-now: + post: + tags: [System] + summary: Trigger a background job + description: >- + Local-only runtime administration. Starts the job, or waits for an in-flight + run before queueing the next one, subject to OMNIROUTE_RUNNOW_TIMEOUT_MS. + x-internal: true + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + "200": + description: Job trigger accepted + "404": + description: Job not found + "500": + description: Failed to trigger job + + /api/jobs/{id}/runs: + get: + tags: [System] + summary: Read background-job run history + description: Local-only runtime administration. Returns newest-first run history for one job. + x-internal: true + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + "200": + description: Job run history + "404": + description: Job not found + "500": + description: Failed to load job runs + # ─── Resilience & Monitoring ──────────────────────────────────── /api/resilience: @@ -5247,6 +5343,70 @@ paths: "200": description: Updated resilience configuration + /api/resilience/connections: + get: + tags: [System] + summary: Inspect connection resilience state + description: >- + Local-only operational view of per-connection cooldowns, provider circuit + breakers, model lockouts, and recent breaker transitions. Credential columns + are excluded by an explicit database whitelist. + x-internal: true + parameters: + - name: windowMs + in: query + schema: + type: integer + minimum: 0 + maximum: 86400000 + default: 3600000 + - name: provider + in: query + schema: + type: string + minLength: 1 + maxLength: 64 + responses: + "200": + description: Connection, breaker, lockout, window, and degradation metadata + "400": + description: Invalid query parameters + "500": + description: Failed to collect resilience state + + /api/telegram/update: + post: + tags: [System] + summary: Receive Telegram updates or Mini App messages + description: >- + Public Telegram integration endpoint. Bot updates are acknowledged after + reply dispatch is queued. Mini App requests must include Telegram-signed + initData, which is verified with TELEGRAM_BOT_TOKEN before chat proxying. + security: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + additionalProperties: true + properties: + initData: + type: string + message: + type: string + update_id: + type: integer + responses: + "200": + description: Update acknowledged or Mini App reply returned + "400": + description: Invalid JSON, request shape, or missing Mini App message + "401": + description: Invalid Mini App initData signature + "503": + description: Telegram integration is not configured + /api/resilience/reset: post: tags: [System] diff --git a/docs/proposals/TELEGRAM-MINIAPP.md b/docs/proposals/TELEGRAM-MINIAPP.md index 884e5c4959..b7f390ac54 100644 --- a/docs/proposals/TELEGRAM-MINIAPP.md +++ b/docs/proposals/TELEGRAM-MINIAPP.md @@ -58,7 +58,7 @@ the natural shape is: - **Public HTTPS required.** Telegram only delivers updates to an HTTPS endpoint with a valid cert. Self-hosted OmniRoute behind Tailscale/ngrok needs a public tunnel or Cloudflare Tunnel for the webhook path - (`TELEGRAM_WEBHOOK_URL`-style env). The dashboard can render the current + (a future webhook-URL setting). The dashboard can render the current public origin (`OMNIROUTE_PUBLIC_BASE_URL`) but no webhook registration helper exists. - **Encryption gate.** `webhooks/route.ts:77` already refuses telegram @@ -102,7 +102,7 @@ the natural shape is: 1. Add `grammy` or `telegraf` (or ~60 lines of hand-rolled HMAC + fetch). 2. Implement `src/lib/telegram/initData.ts` — `verifyInitData(initData, botToken)`. 3. Stand up a throwaway `POST /api/telegram/miniapp/webhook` route behind - `TELEGRAM_WEBHOOK_SECRET`; register via `setWebhook` once, locally. + a dedicated webhook secret; register via `setWebhook` once, locally. ### Phase 1 — Minimal chat slice (1–2 dev-days) diff --git a/docs/reference/ENVIRONMENT.md b/docs/reference/ENVIRONMENT.md index 4df67f64e4..4669c5f9a0 100644 --- a/docs/reference/ENVIRONMENT.md +++ b/docs/reference/ENVIRONMENT.md @@ -43,6 +43,7 @@ lastUpdated: 2026-06-28 - [22. Debugging](#22-debugging) - [23. GitHub Integration](#23-github-integration) - [24. Skills Sandbox (v3.8.0+)](#24-skills-sandbox-v380) +- [27. Radar Feed (Self-Hosting)](#27-radar-feed-self-hosting) - [Deployment Scenarios](#deployment-scenarios) - [Audit: Removed / Dead Variables](#audit-removed--dead-variables) @@ -189,19 +190,20 @@ OmniRoute uses **SQLite** (via `better-sqlite3`) for all persistence. These vari | `MAX_BODY_SIZE_BYTES` | `10485760` (10 MB) | `src/shared/middleware/bodySizeGuard.ts` | Maximum allowed request body size. Rejects payloads exceeding this limit. | | `OMNIROUTE_CHAT_LARGE_BODY_BYTES` | `262144` (256 KB) | `src/shared/middleware/chatBodyAdmission.ts` | Actual request bodies at or above this threshold require an atomic process-local heavyweight admission lease before JSON parsing. | | `OMNIROUTE_CHAT_HARD_MAX_BODY_BYTES` | `52428800` (50 MB) | `src/shared/middleware/chatBodyAdmission.ts` | Chat-route hard cap enforced against bytes read during bounded ingestion, including requests with missing, invalid, or dishonest `Content-Length`; excess receives `413`. | -| `OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT` | `1` | `src/shared/middleware/chatBodyAdmission.ts` | Maximum heavyweight chat requests admitted concurrently in one process. When capacity is unavailable, OmniRoute waits up to `OMNIROUTE_CHAT_ADMISSION_QUEUE_MS` for a slot, then returns retryable `503` with `Retry-After`. | -| `OMNIROUTE_CHAT_ADMISSION_QUEUE_MS` | `5000` | `src/shared/middleware/chatBodyAdmission.ts` | How long a heavyweight chat request waits for an admission slot before the retryable `503`. A bounded wait serializes agent bursts (OpenCode, Claude Code, Cursor sub-requests) that would otherwise burn their client retry budget on immediate rejections; `0` restores the legacy immediate-reject behaviour. | +| `OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT` | `1` | `src/shared/middleware/chatBodyAdmission.ts` | Maximum heavyweight chat requests admitted concurrently in one process. When capacity is unavailable, OmniRoute returns retryable `503` with `Retry-After`. | | `OMNIROUTE_CHAT_HEAVY_MESSAGE_COUNT` | `200` | `src/shared/middleware/chatBodyAdmission.ts` | Message count that classifies a chat request as heavyweight even when its body is below the byte threshold. | | `OMNIROUTE_CHAT_HEAVY_TOOL_COUNT` | `64` | `src/shared/middleware/chatBodyAdmission.ts` | Tool count that classifies a chat request as heavyweight even when its body is below the byte threshold. | | `OMNIROUTE_CHAT_HEAVY_ESTIMATED_TOKENS` | `32000` | `src/shared/middleware/chatBodyAdmission.ts` | Conservative string-size token estimate that classifies a request as heavyweight; this is an admission-cost proxy, not provider billing tokenization. | -| `OMNIROUTE_CHAT_HARD_MAX_MESSAGES` | `800` | `src/shared/middleware/chatBodyAdmission.ts` | Hard chat history cap. Requests above it receive structured compact-required `413` before compression, translation, or provider dispatch. | +| `OMNIROUTE_CHAT_HARD_MAX_MESSAGES` | `0` (disabled) | `src/shared/middleware/chatBodyAdmission.ts` | Optional opt-in chat history cap. Disabled by default: a message count is deployment policy, not a universal property of a request, and capping here rejects conversations with a terminal `413` before the compression pipeline can make them servable. Heap growth is bounded by `OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT` and the heap-pressure shed. Set a positive value on memory-constrained deployments that need a hard ceiling; excess then receives structured compact-required `413`. | | `OMNIROUTE_MAX_NONSTREAMING_RESPONSE_BYTES` | `67108864` (64 MB) | `open-sse/handlers/chatCore/nonStreamingResponseBody.ts` | Hard cap for a non-streaming upstream response buffered fully into memory. Past this the upstream reader is cancelled and the request fails fast instead of growing an unbounded string until the heap is exhausted. | +| `OMNIROUTE_FORWARDING_HEADER_BUDGET_BYTES` | `768` | `open-sse/handlers/chatCore/responseHeaders.ts` | Max wire bytes forwarded from upstream response headers. When the budget is exceeded, lower-priority headers (e.g., custom `x-codex-*`, `x-oai-request-id`) are dropped to stay within common reverse-proxy header limits. Set higher to forward more upstream metadata at the cost of larger response header size. | | `CORS_ORIGIN` | _(unset)_ | `src/server/cors/origins.ts` | Legacy single-origin CORS allowlist. Prefer `CORS_ALLOWED_ORIGINS` for new deployments. CORS is only for cross-origin browser API clients; authenticated dashboard writes use same-origin requests plus session-bound CSRF protection instead. | | `CORS_ALLOWED_ORIGINS` | _(unset)_ | `src/server/cors/origins.ts` | Comma-separated CORS allowlist. No wildcard is sent unless `CORS_ALLOW_ALL=true` is explicitly configured. | | `CORS_ALLOW_ALL` | `false` | `src/server/cors/origins.ts` | Development-only escape hatch to echo any browser `Origin`. Do not enable on shared or production deployments. | | `OUTBOUND_SSRF_GUARD_ENABLED` | `true` | `src/shared/network/outboundUrlGuard.ts` | Block provider calls targeting private/loopback/link-local IP ranges. Disable only in isolated test envs. | | `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` | `false` | `src/shared/network/outboundUrlGuard.ts` | Allow provider URLs pointing to private/local networks (localhost, 192.168.x.x, 10.x.x.x, etc.). **REQUIRED for self-hosted providers** (LM Studio, Ollama, vLLM, Llamafile, Triton, SearXNG). When `false`, the dashboard rejects validation of local URLs. | | `OMNIROUTE_ALLOW_LOCAL_PROVIDER_URLS` | `true` | `src/shared/network/outboundUrlGuard.ts` | Allow adding/validating providers on local/private addresses (127.0.0.1, localhost, LAN, private ranges) — scoped to the provider validation path. **Default `true`** (local-first); set `false` to enforce strict public-only blocking. Cloud-metadata endpoints (169.254.169.254, metadata.google.internal) stay blocked regardless. (#5066) | +| `AUDIO_REMOTE_PROVIDER_NODES` | `false` | `src/app/api/v1/_shared/audioProviderNodes.ts` | Let the `/v1/audio/*` routes (transcriptions, speech, translations) use an OpenAI-compatible provider node hosted outside localhost. Off by default — routing audio to a remote host changes egress identity and must be an explicit operator decision. Loopback/private nodes (localhost, 127.0.0.1, 172.16-31.x) are always allowed and unaffected. (#3963) | ### Hardening Checklist @@ -265,6 +267,7 @@ OmniRoute provides a two-layer defense: request-side injection scanning and resp | `OMNIROUTE_PAYLOAD_RULES_PATH` | `./config/payloadRules.json` | `open-sse/services/payloadRules.ts` | Path to payload manipulation rules JSON file (per-model/protocol upstream tweaks). | | `OMNIROUTE_PAYLOAD_RULES_RELOAD_MS` | `5000` | `open-sse/services/payloadRules.ts` | Reload interval (ms) for hot-reloading the payload rules file. Minimum `1000`. | | `OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS` | `false` | `open-sse/services/model.ts` | Opt-in: route bare `claude-*` model IDs from Claude Code clients through the Claude Code OAuth account instead of requiring a provider prefix. Explicit provider prefixes still win. Also configurable via a dashboard toggle on the Claude provider page. | +| `COMBO_CONCURRENCY_PER_MODEL` | `3` | `open-sse/services/comboConfig.ts` | Per-model concurrency cap for round-robin combos (#9100). The round-robin combo semaphore was hard-capped at 3 concurrent requests per model with no override, serializing higher-concurrency traffic behind that cap. Validated to `>= 1`, clamped to `<= 32`. | --- @@ -378,6 +381,14 @@ Controls how OmniRoute discovers and launches CLI sidecars (Claude Code, Codex, | `CLI_QODER_BIN` | `qoder` | `src/shared/services/cliRuntime.ts` | Custom path to Qoder CLI binary. | | `CLI_QWEN_BIN` | `qwen` | `src/shared/services/cliRuntime.ts` | Custom path to the Qwen Code CLI binary. | | `CLI_DEVIN_BIN` | `devin` | `open-sse/executors/devin-cli.ts` | Custom path to the Devin CLI binary (v3.8.0). Used by the Windsurf/Devin executor. | +| `CLI_DEVIN_AGENTIC_BIN` | `devin` | `open-sse/executors/devin-cli-agentic.ts` | Agentic bridge-only Devin CLI override. The executor accepts only the local ACP stdio upstream. | +| `DEVIN_AGENTIC_HOME` | _(required)_ | `open-sse/executors/devin-cli-agentic.ts` | Absolute isolated home for the agentic Devin subprocess; accepted bridge paths are `/home/bridge` and task-local `.sandbox` paths. | +| `DEVIN_AGENTIC_ACP_TIMEOUT_MS` | `120000` | `open-sse/executors/devin-cli-agentic.ts` | Maximum duration of one Devin ACP turn before the bridge terminates the child and returns an explicit timeout. | +| `DEVIN_BRIDGE_MODEL` | `devin-cli-agentic/swe-1-7` | `docker/devin-bridge/compose.yml` | Main Claude Code model alias for the isolated bridge. The live harness replaces the example with a model returned by the current Devin account. | +| `DEVIN_BRIDGE_SONNET_MODEL` | `DEVIN_BRIDGE_MODEL` | `docker/devin-bridge/compose.yml` | Isolated bridge alias used when Claude Code requests its Sonnet default. | +| `DEVIN_BRIDGE_OPUS_MODEL` | `DEVIN_BRIDGE_MODEL` | `docker/devin-bridge/compose.yml` | Isolated bridge alias used when Claude Code requests its Opus default. | +| `DEVIN_BRIDGE_HAIKU_MODEL` | `DEVIN_BRIDGE_MODEL` | `docker/devin-bridge/compose.yml` | Isolated bridge alias used when Claude Code requests its Haiku default. | +| `DEVIN_BRIDGE_SUBAGENT_MODEL` | `DEVIN_BRIDGE_MODEL` | `docker/devin-bridge/compose.yml` | Isolated bridge alias used for Claude Code subagents. | | `AUGGIE_BIN` | `auggie` | `open-sse/executors/auggie.ts` | Absolute-path override for the Augment (Auggie) CLI binary used by the local `auggie` provider. Falls back to `CLI_AUGGIE_BIN`, then a PATH lookup. | | `CLI_AUGGIE_BIN` | `auggie` | `open-sse/executors/auggie.ts` | Alias override for the Augment (Auggie) CLI binary path (checked after `AUGGIE_BIN`). | | `HERMES_HOME` | `~/.hermes` | `src/lib/cli-helper/config-generator/hermesHome.ts` | Hermes Agent home directory where OmniRoute reads/writes the Hermes CLI config. Matches the env var the Hermes PowerShell installer sets on Windows (`%LOCALAPPDATA%\hermes`). | @@ -415,7 +426,6 @@ detection above). | `OMNIROUTE_HTTP_TIMEOUT_MS` | `30000` | `bin/cli/api.mjs` | Per-attempt HTTP timeout (ms) for CLI → server requests. | | `OMNIROUTE_VERBOSE` | `0` | `bin/cli/api.mjs` | Set to `1` to print retry/backoff diagnostics to stderr during CLI commands. | | `OMNIROUTE_PLUGIN_PATH` | _(unset)_ | `bin/cli/plugins.mjs` | Custom directory for CLI plugin discovery (`omniroute-cmd-*` packages). Defaults to `~/.omniroute/plugins/` when unset. | -| `OMNIROUTE_PLUGINS_ALLOW_EXEC` | `0` | `src/lib/plugins/pluginWorker.ts` | Set to `1` to allow plugins to request the `exec` permission (spawn child processes from the worker sandbox). Local operator only. | --- @@ -439,12 +449,6 @@ detection above). | `PROVIDER_LIMITS_SYNC_SPACING_MS` | `1500` | `src/lib/usage/providerLimits.ts` | Gap (ms) between consecutive OAuth quota fetches in a bulk sync; OAuth connections are fetched one at a time to avoid bursting an upstream. `0` opts out (concurrent). | | `OMNIROUTE_QUOTA_FETCH_MIN_INTERVAL_MS` | `250` | `open-sse/services/quotaFetchThrottle.ts` | Min interval (ms) between consecutive upstream quota fetches on the per-request preflight/monitor path; spaces concurrent network calls so many accounts on one IP don't burst the upstream. Wired into the Codex (`/wham/usage`), DeepSeek, Bailian (both fetch sites), OpenCode, and Crof quota fetchers (#6009, #6911). The generic `usage.ts::getUsageForProvider` dispatch path (github/glm/minimax/nanogpt/xai/etc.) is not yet covered — tracked separately. Cache hits unaffected. `0` disables; clamped `0..5000`. | | `PROVIDER_LIMITS_POST_USAGE_REFRESH_DELAY_MS` | `5000` | `src/lib/usage/providerLimits.ts` | Delay (ms) before refreshing provider limits after a real usage event, giving the upstream quota API time to register consumption. | -| `OMNIROUTE_LOGIN_BROWSER_PATH` | auto-detect | `open-sse/services/adobeFireflyBrowserLogin.ts` | Absolute path to a system Chrome or Edge executable used for interactive Adobe Firefly sign-in and off-screen renewal. | -| `ADOBE_FIREFLY_BROWSER_REFRESH` | enabled | `open-sse/services/adobeFireflySession.ts` | Keeps IMS and browser-risk state fresh with account-scoped Chrome CDP sessions. Set to `0` to disable browser renewal. | -| `ADOBE_FIREFLY_SESSION_DISK` | enabled | `open-sse/services/adobeFireflySession.ts` | Persists repaired Adobe sessions under `DATA_DIR` across process restarts. Set to `0` to keep sessions memory-only. | -| `ADOBE_FIREFLY_MIN_SUBMIT_GAP_MS` | `12000` | `open-sse/services/adobeFireflySession.ts` | Minimum spacing in milliseconds between Adobe Firefly generate submissions; `0` disables spacing. | -| `ADOBE_FIREFLY_BATCH_EXTRA_GAP_MS` | `15000` | `open-sse/services/adobeFireflySession.ts` | Extra quiet period in milliseconds after every third successful Adobe submission. | -| `ADOBE_FIREFLY_SUBMIT_BASE_DELAY_MS` | `8000` | `open-sse/services/adobeFireflyClient.ts` | Base backoff in milliseconds after transient Adobe 408 responses; combined with submit spacing across at most five attempts. | | `OMNIROUTE_DISABLE_BACKGROUND_SERVICES` | `false` | `src/instrumentation-node.ts` | Disable all background services (sync, pricing, model refresh). Useful for CI/test. | | `OMNIROUTE_ENABLE_RUNTIME_BACKGROUND_TASKS` | _(unset)_ | `src/lib/config/runtimeSettings.ts` | Force background tasks on under automated test detection. Set `1` to override the test heuristic. | | `OMNIROUTE_BUDGET_RESET_JOB_INTERVAL_MS` | `600000` | `src/lib/jobs/budgetResetJob.ts` | Budget reset check cadence (ms). Floor `10000`. | @@ -458,6 +462,7 @@ detection above). | `COMPRESSION_PIPELINE_BREAKER_THRESHOLD` | `3` | `open-sse/services/compression/pipelineEngineBreaker.ts` | Consecutive cross-request failures before an engine's breaker opens. | | `COMPRESSION_PIPELINE_BREAKER_COOLDOWN_MS` | `30000` | `open-sse/services/compression/pipelineEngineBreaker.ts` | Milliseconds an opened engine stays skipped before a half-open probe. | | `COMPRESSION_CCR_RETRIEVAL_RAMP_FACTOR` | `2` | `open-sse/services/compression/engines/ccr/index.ts` | T08/H8 CCR retrieval-feedback ramp: each prior retrieval of a stored block raises its effective `minChars` linearly (frequently-retrieved content compresses less; `>=3` retrievals = never compressed). `1` disables the ramp (binary skip at the threshold only). | +| `COMPRESSION_CCR_DURABLE_STORE` | `true` | `open-sse/services/compression/engines/ccr/index.ts` | CCR durable block store (#9061). Backs the in-memory store with SQLite so a block survives LRU eviction, the TTL, a restart, or a retrieve landing on another instance. Set `false` to keep blocks in memory only. Blocks over 512KB and cloud runtimes stay memory-only regardless. | | `COMPRESSION_PREFIX_FREEZE_ENABLED` | `false` | `open-sse/services/compression/prefixFreeze.ts` | T08/H5 usage-observed prefix freeze master switch. **Opt-in (default off)** — when on, a system prompt observed `>=` the threshold is treated as a stable cacheable prefix and preserved from compression even for providers the static cache heuristic misses (freeze only *preserves*, never mutates). | | `COMPRESSION_PREFIX_FREEZE_THRESHOLD` | `3` | `open-sse/services/compression/prefixFreeze.ts` | Observations of a system prompt before it is treated as a frozen stable prefix. | | `OMNIROUTE_BOOTSTRAPPED` | `false` | `src/app/(dashboard)/dashboard/page.tsx` | Set `true` by bootstrap script after initial setup. Controls setup wizard visibility. | @@ -513,8 +518,12 @@ Built-in credentials for **localhost development**. For remote deployments, regi | `OMNIROUTE_QODER_WORKSPACE` | Qoder | Alias for `QODER_CLI_WORKSPACE`. | | `QODER_CLI_CONFIG_DIR` | Qoder | Override the Qoder CLI config dir (isolated PAT session, avoids clobbering a browser login). | | `BLACKBOX_WEB_VALIDATED_TOKEN` | Blackbox Web | Frontend `tk` token to send as `validated` on `/api/chat`. Required when Blackbox enforces token matching; otherwise OmniRoute falls back to a random UUID. See issue #2252. | -| `VISION_BRIDGE_BASE_URL` | Vision Bridge guardrail | OpenAI-compatible base URL for non-Anthropic vision-bridge calls. Defaults to the legacy OpenAI URL env or api.openai.com. Point at OmniRoute's `/v1` self-loop or any OpenAI-compat endpoint (Gemini OpenAI-compat, OpenRouter). Issue #2232. | +| `VISION_BRIDGE_BASE_URL` | Vision Bridge guardrail | OpenAI-compatible base URL for non-Anthropic vision-bridge calls. Defaults to the legacy OpenAI URL env or api.openai.com. Point at OmniRoute's `/v1` self-loop or any OpenAI-compat endpoint (Gemini OpenAI-compat, OpenRouter). Issue #2232. When the URL is OmniRoute's own `/v1`, the describe sub-request sends `x-omniroute-admission-bypass: internal` and authenticates with the resolved self-loop credential (`sk_omniroute` sentinel in local mode, or `OMNIROUTE_API_KEY` / `ROUTER_API_KEY` — #1350) so `REQUIRE_API_KEY=true` deployments work. | | `VISION_BRIDGE_API_KEY` | Vision Bridge guardrail | API key for the URL above. Overrides per-provider OpenAI / Google env vars for non-Anthropic vision-bridge calls. Anthropic models keep their dedicated Anthropic key path. Issue #2232. | +| `RAYCAST_BEARER_TOKEN` | Raycast Pro | Optional manual override for the Raycast access token (normally captured via macOS Auto-Import). No OAuth client_id/secret — reverse-engineered, local/personal use only. | +| `RAYCAST_DEVICE_ID` | Raycast Pro | Optional manual override for the Raycast device ID used to sign requests. | +| `RAYCAST_AID` | Raycast Pro | Optional manual override for the Raycast account/app ID; falls back to the device ID when unset. | +| `RAYCAST_SIG_SECRET` | Raycast Pro | Optional override for the request-signing HMAC secret. Defaults to a community-extracted value in `open-sse/services/raycast.ts`. | > [!WARNING] > @@ -662,12 +671,13 @@ REQUEST_TIMEOUT_MS (global override) | `API_BRIDGE_SERVER_SOCKET_TIMEOUT_MS` | `0` | Raw socket timeout (0 = disabled). | | `SHUTDOWN_TIMEOUT_MS` | `30000` | Grace period on SIGTERM/SIGINT before force-exit. | | `OMNIROUTE_DEFAULT_FETCH_TIMEOUT_MS` | `120000` | Fallback used by `src/shared/utils/fetchTimeout.ts` when `FETCH_TIMEOUT_MS` is unset. | +| `OMNIROUTE_RELAY_FETCH_TIMEOUT_MS` | `25000` | Relay-specific fetch timeout in `open-sse/utils/proxyFetch.ts` (#9158). A hung relay must fail before the client/agent timeout (~30s) so callers see a relay-specific failure instead of a generic upstream timeout. Capped at `29000` so it always fires first. | +| `OMNIROUTE_RETRY_BACKOFF_MS` | `10` | Shared retry backoff for the direct/relay/proxy retry-once paths in `open-sse/utils/proxyFetch.ts` (#9158). `0` = retry immediately. | | `OMNIROUTE_CHATGPT_TLS_TIMEOUT_MS` | `60000` | Wire-level timeout for the bogdanfinn/tls-client koffi binding (`chatgptTlsClient.ts`). | | `OMNIROUTE_CHATGPT_TLS_GRACE_MS` | `10000` | JS-side grace added on top of the wire timeout when the native binding is wedged. | -| `OMNIROUTE_CHATGPT_STREAM_FIRST_BYTE_TIMEOUT_MS` | `30000` | Max wait for the first streamed byte from the ChatGPT TLS sidecar. | -| `OMNIROUTE_CLAUDE_TLS_TIMEOUT_MS` | `60000` | Wire-level timeout for the bogdanfinn/tls-client koffi binding. | -| `OMNIROUTE_CLAUDE_TLS_GRACE_MS` | `10000` | JS-side grace added on top of the wire timeout when the native binding is wedged. | -| `OMNIROUTE_RUNNOW_TIMEOUT_MS` | `30000` | Timeout for the `/api/jobs/:id/run-now` endpoint. Bounds how long a run-now call waits for an in-flight job to finish before starting the queued run. See `src/app/api/jobs/[id]/run-now/route.ts`. | +| `OMNIROUTE_CHATGPT_STREAM_FIRST_BYTE_TIMEOUT_MS` | `30000` (30s) | Max wait for the first streamed byte from the ChatGPT TLS sidecar (`chatgptTlsClient.ts`) before aborting a dead stream. Raise if upstream cold-starts exceed the window. | +| `OMNIROUTE_CLAUDE_TLS_TIMEOUT_MS` | `60000` | Wire-level timeout for the bogdanfinn/tls-client koffi binding (`claudeTlsClient.ts`). | +| `OMNIROUTE_CLAUDE_TLS_GRACE_MS` | `10000` | JS-side grace added on top of the wire timeout when the native binding is wedged. | | `OMNIROUTE_PPLX_TLS_TIMEOUT_MS` | `30000` | Wire-level timeout for the bogdanfinn/tls-client koffi binding (`perplexityTlsClient.ts`). | | `OMNIROUTE_PPLX_TLS_GRACE_MS` | `10000` | JS-side grace added on top of the wire timeout when the native binding is wedged. | | `OMNIROUTE_GROK_TLS_TIMEOUT_MS` | `60000` | Wire-level timeout for the bogdanfinn/tls-client koffi binding (`grokTlsClient.ts`). | @@ -676,6 +686,7 @@ REQUEST_TIMEOUT_MS (global override) | `OMNIROUTE_NOTION_TLS_GRACE_MS` | `10000` | JS-side grace added on top of the wire timeout when the native binding is wedged. | | `OMNIROUTE_BROWSER_POOL` | `on` | Shared Playwright browser pool for browser-backed web-cookie chat (`browserPool.ts`); set `off` to disable. | | `WEB_COOKIE_USE_BROWSER` | `0` | Opt a web-cookie chat request into the browser-backed path (`browserBackedChat.ts`); `1` to enable. | +| `OMNIROUTE_LOGIN_BROWSER_PATH` | _(auto-detected)_ | Path to a system Chrome/Edge executable for the Adobe Firefly interactive browser sign-in (`adobeFireflyBrowserLogin.ts`); overrides per-OS auto-detection. | Combo target attempts inherit the resolved upstream request timeout (`FETCH_TIMEOUT_MS`, or `REQUEST_TIMEOUT_MS` when it supplies the fetch default). Set `targetTimeoutMs` in a combo, @@ -723,6 +734,7 @@ The logging system writes to both stdout and rotated log files. All configuratio | `CALL_LOG_RETENTION_DAYS` | `7` | Days to keep request/call log entries in the database. | | `CALL_LOG_MAX_ENTRIES` | `10000` | Max call log entries in the in-memory buffer. | | `CALL_LOGS_TABLE_MAX_ROWS` | `100000` | Max rows in the `call_logs` SQLite table before pruning. | +| `ENABLE_REQUEST_LOGS` | _(unset)_ | Force detailed request logging on or off, overriding the dashboard setting. | | `MAX_PENDING_REQUEST_AGE_MS` | `3600000` (1 hour) | Max age for orphaned active request log entries before in-memory cleanup. | | `CALL_LOG_PIPELINE_CAPTURE_STREAM_CHUNKS` | `true` | Store stream chunks in pipeline artifacts when `call_log_pipeline_enabled=true`. | | `CALL_LOG_PIPELINE_MAX_SIZE_KB` | `512` | Max pipeline call log artifact size in KB when `call_log_pipeline_enabled=true`. | @@ -732,7 +744,6 @@ The logging system writes to both stdout and rotated log files. All configuratio | `CHAT_LOG_ARRAY_TAIL_ITEMS` | `128` | Number of array items retained from the tail when truncating chat log payloads. | | `CHAT_LOG_MAX_DEPTH` | `6` | Max nesting depth before chat log payloads are truncated. | | `CHAT_LOG_MAX_OBJECT_KEYS` | `80` | Max object keys retained in chat log payloads (0 = unlimited). | -| `CHAT_LOG_MAX_BODY_KB` | `1024` | Max request/response body size before `truncateForLog()` summarizes it, in KB. | | `CHAT_DEBUG_FILE` | `false` | When true, `serializeArtifactForStorage` skips size-based truncation. Debug only. | --- @@ -769,9 +780,13 @@ Embedding layer, vector store and reranking knobs for the persistent memory subs | `MEMORY_TRANSFORMERS_MODEL` | `Xenova/all-MiniLM-L6-v2` | HF repo id for the opt-in `@huggingface/transformers` local MiniLM pipeline (~23 MB int8, ~400 MB RAM). | | `MEMORY_STATIC_MODEL` | `minishlab/potion-base-8M` | HF repo id for the static potion/Model2Vec lookup-table embedder. Downloaded lazily into the cache dir. | | `MEMORY_STATIC_CACHE_DIR` | `/embeddings` | Directory used to cache the static potion model files. Defaults under `DATA_DIR` when unset. | +| `HF_HUB_ENDPOINT` | `https://huggingface.co` | Override Hugging Face Hub base URL used by `staticPotion.ts` (e.g. mirror endpoint for air-gapped setups). | | `MEMORY_VEC_TOP_K` | `20` | Default top-K used by the `sqlite-vec` brute-force vector search inside `src/lib/memory/vectorStore.ts`. | | `MEMORY_RRF_K` | `60` | Reciprocal Rank Fusion constant `k` for hybrid FTS5 + vector retrieval (sqlite-vec recipe). | -| `HF_HUB_ENDPOINT` | `https://huggingface.co` | Override Hugging Face Hub base URL used by `staticPotion.ts` (e.g. mirror endpoint for air-gapped setups). | +| `NOTION_API_KEY` | _(unset)_ | API key for Notion backend (used by `genericBackend.ts` known backend preset). | +| `NOTION_API_URL` | `https://api.notion.com/v1`| Base URL for Notion API (can override for self-hosted Notion alternatives). | +| `OBSIDIAN_API_KEY` | _(unset)_ | API key for Obsidian Vault backend (used by `genericBackend.ts` known backend preset). | +| `OBSIDIAN_API_URL` | `http://localhost:27123` | Base URL for Obsidian Vault API (can override for remote vault). | | `MEMORY_TYPED_DECAY_ENABLED` | `false` | TV6 typed memory decay master switch. **Opt-in (default off)** — the sweep **deletes** decayed memories. With it off, `access_count`/`last_accessed_at` are pure telemetry and nothing is ever deleted. | | `MEMORY_TYPED_DECAY_EPISODIC_DAYS` | `30` | TTL (days) after which an unused `episodic` memory decays. `0` makes episodic immune too. Durable types (`factual`/`procedural`/`semantic`) are always immune. The decay clock re-bases on `last_accessed_at`. | | `MEMORY_TYPED_DECAY_ACCESS_IMMUNITY` | `3` | A memory injected `>=` this many times becomes immune to decay regardless of type. `0` disables access immunity. | @@ -838,6 +853,7 @@ Reverse-engineered session bridge for hyperagent.com (`src/shared/constants/prov | Variable | Default | Source File | Description | | ----------------------------------- | ------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `MODELS_DEV_SYNC_ENABLED` | `false` | `src/lib/modelsDevSync.ts` | Opt-in switch for the models.dev capability sync. Set to anything non-empty it wins over the `modelsDevSyncEnabled` setting (Dashboard > Settings > AI) in either direction, so a deployment can pin the sync on or off without depending on database state surviving a rebuild; unset, it defers to that setting. On for `1`, `true`, `yes` or `on` in any casing; any other value is off. | | `MODELS_DEV_SYNC_INTERVAL` | `86400` (24h) | `src/lib/modelsDevSync.ts` | Development-time model catalog sync interval in seconds. | | `CONTEXT_WINDOW_RECONCILE_INTERVAL` | `86400` (24h) | `src/lib/contextWindowResolver.ts` | Interval (seconds) for the self-correcting context-window reconciler (5004): pins provider-declared windows from `/models` discovery as `auto:discovery` overrides when they diverge from the catalog. Set to `0` to disable. Reuses already-synced data (no new fetch); never overwrites `manual` overrides. | @@ -853,6 +869,7 @@ Reverse-engineered session bridge for hyperagent.com (`src/shared/constants/prov | `NANOBANANA_POLL_INTERVAL_MS` | `2500` | `open-sse/handlers/imageGeneration.ts` | NanoBanana job polling frequency. | | `DESIGNER_WEB_POLL_TIMEOUT_MS` | `60000` | `open-sse/handlers/imageGeneration/providers/designerWeb.ts` | Max wait for microsoft-designer-web image generation jobs. | | `DESIGNER_WEB_POLL_INTERVAL_MS` | `2000` | `open-sse/handlers/imageGeneration/providers/designerWeb.ts` | microsoft-designer-web job polling frequency. | +| `ADOBE_FIREFLY_SUBMIT_BASE_DELAY_MS` | `8000` | `open-sse/services/adobeFireflyUpscale.ts` | Base delay for the Adobe Firefly upscale submit-retry exponential backoff. | | `AWS_REGION` | _(unset)_ | `src/lib/providers/validation.ts`, `open-sse/handlers/audioSpeech.ts` | Region used to construct AWS Bedrock endpoints (Kiro, audio). | | `AWS_DEFAULT_REGION` | _(unset)_ | `src/lib/providers/validation.ts`, `open-sse/handlers/audioSpeech.ts` | Fallback when `AWS_REGION` is not set. | | `CLOUDFLARE_ACCOUNT_ID` | _(unset)_ | `open-sse/executors/cloudflare-ai.ts` | Account ID for Cloudflare Workers AI. | @@ -874,6 +891,10 @@ Reverse-engineered session bridge for hyperagent.com (`src/shared/constants/prov | `CLIPROXYAPI_PORT` | `5544` | `open-sse/executors/cliproxyapi.ts` | CLIProxyAPI bridge port. | | `CLIPROXYAPI_CONFIG_DIR` | `~/.cli-proxy-api` | `src/lib/versionManager/processManager.ts` | CLIProxyAPI config directory. | | `MUX_SERVICE_PORT` | `8322` | `src/lib/services/bootstrap.ts` | Override the port where the embedded Mux (coder/mux) agent-orchestration daemon listens (always 127.0.0.1). | +| `DARIO_HOST` | `127.0.0.1` | `open-sse/executors/dario.ts` | Dario embedded-service bind/connect host (loopback only by default). | +| `DARIO_PORT` | `3456` | `open-sse/executors/dario.ts` | Dario embedded-service port. | +| `DARIO_HOST` | `127.0.0.1` | `open-sse/executors/dario.ts` | Dario embedded-service bind/connect host (loopback only by default). | +| `DARIO_PORT` | `3456` | `open-sse/executors/dario.ts` | Dario embedded-service port. | | `LOCAL_HOSTNAMES` | _(empty)_ | `open-sse/config/providerRegistry.ts` | Comma-separated additional hostnames treated as "local" (Docker service names, etc.). | `ENABLE_CC_COMPATIBLE_PROVIDER` is only for third-party relays that accept Claude Code clients @@ -1154,6 +1175,13 @@ Provider quota endpoints, network tunnels (Tailscale, Ngrok, MITM debug proxy), | `OMNIROUTE_LOCAL_ENDPOINTS_TOKEN` | _(unset)_ | `src/lib/security/localEndpoints.ts` | Bearer token for `/api/local/*` callers that aren't on loopback (e.g. the desktop app). When set, requests from non-loopback IPs must carry `Authorization: Bearer `. Required when `OMNIROUTE_LOCAL_ENDPOINTS_ENABLED=1` in non-loopback deployments. | | `OMNIROUTE_REDIS_CONTAINER_NAME` | `omniroute-redis` | `bin/cli/commands/redis.mjs` | Container name for the 1-click Redis launcher (`omniroute redis up`). Used by both the CLI and the `RedisLauncherPanel` GUI. | | `OMNIROUTE_REDIS_HOST_PORT` | `6379` | `bin/cli/commands/redis.mjs` | Host port for the 1-click Redis launcher. Bump if the host already binds 6379. The container's internal port stays 6379. | +| `OMNIROUTE_REDIS_BIND_HOST` | `127.0.0.1` | `bin/cli/commands/redis.mjs` | Host interface the 1-click Redis launcher publishes on. The launcher starts Redis WITHOUT a password, so binding `0.0.0.0` hands every host on your LAN an unauthenticated Redis — only widen this if you also set a password on the instance yourself. | +| `REDIS_BIND_HOST` | `127.0.0.1` | `docker-compose.yml` | Host interface docker-compose publishes the Redis sidecar on (#9286). The compose Redis runs without `requirepass`; app containers reach it over the compose network (`redis:6379`) — the published port exists only for host-side tooling. `0.0.0.0` exposes an unauthenticated Redis to the whole LAN. | +| `REDIS_PORT` | `6379` | `docker-compose.yml` | Host port for the compose Redis sidecar. | +| `OMNIROUTE_INTERNAL_SERVICE_TOKEN` | _(unset — mechanism disabled)_ | `src/lib/api/internalServiceAuth.ts` | Shared secret for identity-preserving internal REST hops (#9260): OmniRoute components calling other local OmniRoute routes send it as `x-omniroute-internal-service-token` so the original caller identity is preserved. Compared with `timingSafeEqual`. | +| `OMNIROUTE_INTERNAL_SERVICE_TOKEN_FILE` | _(unset)_ | `src/lib/api/internalServiceAuth.ts` | Secret-file variant of the internal service token: path to a file whose trimmed content is the token. Only consulted when the inline var is unset. | +| `OPENROUTER_PROVIDER_STATS_ENABLED` | `true` | `src/lib/catalog/openrouterProviderStats.ts` | Enrich the dashboard providers list with OpenRouter weekly ranking stats (#9324). On by default; set `false` to skip the background fetch entirely (non-blocking, never fatal). | +| `OPENROUTER_PROVIDER_STATS_TTL_MS` | `86400000` (24h) | `src/lib/catalog/openrouterProviderStats.ts` | Cache TTL for the OpenRouter provider-stats snapshot, in milliseconds. | | `OMNIROUTE_REDIS_IMAGE` | `redis:7-alpine` | `bin/cli/commands/redis.mjs` | Redis image used by the 1-click Redis launcher. Override to `redis:8-alpine` or a private registry mirror as needed. | | `QDRANT_HOST` | `qdrant` | _(opt-in cluster profile)_ | Hostname of the Qdrant sidecar when `--profile memory` is active. Default points to the in-network qdrant service name; override for an external deployment. Only consumed when `qdrantEnabled` is `true` in code (`src/lib/memory/vectorStore.ts:108`). | | `QDRANT_PORT` | `6333` | _(opt-in cluster profile)_ | REST port of the Qdrant sidecar. | @@ -1179,6 +1207,17 @@ Provider quota endpoints, network tunnels (Tailscale, Ngrok, MITM debug proxy), | `OMNIROUTE_ROTATE_400_THRESHOLD` | `1` | `open-sse/services/rotationConfig.ts` | Number of `400` errors within `OMNIROUTE_ROTATE_400_WINDOW_SECONDS` required before the account is rotated (only consulted when `OMNIROUTE_ROTATE_ON_400=true`). | | `OMNIROUTE_ROTATE_400_WINDOW_SECONDS` | `120` | `open-sse/services/rotationConfig.ts` | Sliding window (seconds) over which `400` errors are counted toward `OMNIROUTE_ROTATE_400_THRESHOLD`. | +### Claude Warmup Scheduler + +Cron-driven warmup for opted-in Anthropic OAuth connections, so the 5-hour rate-limit window is opened by a trivial scheduled request instead of by the first real one (#8848). The scheduler is off unless `OMNIROUTE_WARMUP_ENABLED` is truthy **and** the connection is flagged in `settings.claudeWarmup.connections`; an empty connection list means nothing is warmed even with the env var on. + +| Variable | Default | Source File | Description | +| ----------------------------- | -------------------------------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `OMNIROUTE_WARMUP_ENABLED` | _(unset → off)_ | `src/lib/warmupScheduler.ts` | Master switch for the warmup scheduler. Accepts `1`/`true`/`yes`/`on` (case-insensitive, trimmed). Any other value, or unset, leaves the scheduler off. | +| `OMNIROUTE_WARMUP_CRON` | `0 7 * * *` | `src/lib/warmupScheduler.ts` | Five-field cron expression for the warmup tick, evaluated in `America/Los_Angeles` (Anthropic's reset timezone) regardless of the host clock. | +| `OMNIROUTE_WARMUP_CONCURRENCY` | `3` | `src/lib/warmupScheduler.ts` | How many connections are warmed in parallel per tick. Clamped to `1`-`10`; a non-numeric value falls back to `3`. | +| `OMNIROUTE_WARMUP_MODEL` | `claude-3-5-haiku-20241022` | `src/lib/warmupScheduler.ts` | Model used for the warmup request. Override only if the default is unavailable on your plan; pick the cheapest model that still opens the window. | + ### Browser-Login VNC Sessions & Data-Dir Alias Containerized Chromium+VNC used for interactive browser-login credential capture (`/api/vnc-session`), plus a legacy `DATA_DIR` alias. All optional — the VNC defaults target the bundled `omniroute-vnc-chromium:local` image and are only overridden for a custom container image, ports, or lifecycle tuning. @@ -1243,6 +1282,25 @@ that should be able to run the docs translator. --- +## 27. Radar Feed (Self-Hosting) + +Optional add-on gated by the RADAR_ENABLED feature flag (default off — a feature +flag toggled via Settings/DB, not an env var; see +[docs/frameworks/RADAR.md](../frameworks/RADAR.md#flag-radar_enabled-default-off)). +The four variables below are optional overrides used only to point the client at a +self-hosted or forked feed / supporter-key flow instead of the default OmniRoute +Radar service. See [docs/frameworks/RADAR.md](../frameworks/RADAR.md) for the full +module doc. + +| Variable | Default | Source File | Description | +| -------------------------------- | --------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------ | +| `RADAR_FEED_URL` | `https://radar.omniroute.online` | `src/lib/radar/sync.ts` | Base URL of the Radar feed service. Override to point at a self-hosted or forked feed. | +| `RADAR_FEED_PUBKEY` | _(pinned default key)_ | `src/lib/radar/pinnedKeys.ts` | Ed25519 public key (base64-DER SPKI or PEM) used to verify feed signatures from a custom feed. | +| `RADAR_CONTRIBUTOR_CLAIM_URL` | `https://radar.omniroute.online/auth/github` | `src/lib/radar/links.ts` | URL the "I'm a contributor" dashboard button opens (GitHub OAuth supporter-key claim flow). | +| `RADAR_SUPPORTER_PLANS_URL` | `https://radar.omniroute.online/planos` | `src/lib/radar/links.ts` | URL the "Support the project" dashboard button opens (payment/plans page). | + +--- + ## Audit: Removed / Dead Variables The following variables appeared in previous versions of `.env.example` but have **no runtime references** in the current codebase. They have been removed: @@ -1310,13 +1368,52 @@ Used by `src/lib/vncSession/manifest.ts` to configure Docker-based headless Chro | `OMNIROUTE_VNC_HARVEST_MS` | `20000` | `src/lib/vncSession/manifest.ts` | Harvest/cleanup timeout (ms). | | `VIBEPROXY_DATA_DIR` | _(unset)_ | `open-sse/services/notionThreadSessions.ts` | Directory for Notion thread session persistence. | -### Telegram Mini App +### Internal service auth -Used by `src/lib/telegram/*` and `src/app/api/telegram/update/route.ts` for the inbound bot webhook and Mini App chat proxy. All optional — the endpoint returns 503 when `TELEGRAM_BOT_TOKEN` is unset. +| Variable | Default | Description | +| --- | --- | --- | +| `OMNIROUTE_INTERNAL_SERVICE_TOKEN` | – | Inline token for management-plane service-to-service authentication. | +| `OMNIROUTE_INTERNAL_SERVICE_TOKEN_FILE` | – | Path to a file containing the internal service token (preferred in containers; overrides the inline variable). | -| Variable | Default | Source File | Description | -| ------------------------------ | -------------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------- | -| `TELEGRAM_BOT_TOKEN` | _(unset)_ | `src/lib/telegram/config.ts` | Bot token from @BotFather (`:`). Enables the inbound webhook; doubles as the HMAC secret for Mini App `initData` verification. | -| `TELEGRAM_DEFAULT_MODEL` | `auto/chat` | `src/lib/telegram/chatProxy.ts` | Model used for Telegram chat replies. | -| `TELEGRAM_BOT_API_BASE` | `https://api.telegram.org` | `src/lib/telegram/config.ts` | Bot API base URL override (proxies / self-hosted Bot API servers). | -| `TELEGRAM_WEBHOOK_TIMEOUT_MS` | `60000` | `src/lib/telegram/config.ts` | Timeout (ms) for outbound Bot API calls (`sendMessage`/`setWebhook`). | +### OpenRouter provider stats + +| Variable | Default | Description | +| --- | --- | --- | +| `OPENROUTER_PROVIDER_STATS_ENABLED` | `true` | Set to `false` to skip fetching OpenRouter per-provider stats for catalog enrichment. | +| `OPENROUTER_PROVIDER_STATS_TTL_MS` | `3600000` | Cache TTL (ms) for the fetched OpenRouter provider stats. | + +### Embedded Redis binding + +| Variable | Default | Description | +| --- | --- | --- | +| `REDIS_BIND_HOST` | `127.0.0.1` | Bind address for the embedded Redis service. | +| `REDIS_PORT` | `6379` | Port for the embedded Redis service. | +| `OMNIROUTE_REDIS_BIND_HOST` | – | OmniRoute-scoped override for the embedded Redis bind address. | + +--- + +## 24. Release v3.8.50 additions + +These settings were introduced after the previous environment-contract snapshot. + +| Variable | Default | Source File | Description | +| --- | --- | --- | --- | +| `OMNIROUTE_CHAT_ADMISSION_QUEUE_MS` | `5000` | `src/shared/middleware/chatBodyAdmission.ts` | Maximum wait for a heavyweight chat admission slot before a retryable `503`; `0` restores immediate rejection. | +| `OMNIROUTE_RUNNOW_TIMEOUT_MS` | `30000` | `src/app/api/jobs/[id]/run-now/route.ts` | Bounds how long a run-now call waits for an in-flight job before starting the queued run. | +| `CHAT_LOG_MAX_BODY_KB` | `1024` | `src/lib/logEnv.ts` | Maximum request or response body size before log summarization, in KiB. | +| `ADOBE_FIREFLY_BROWSER_REFRESH` | enabled | `open-sse/services/adobeFireflySession.ts` | Keeps IMS and browser-risk state fresh through account-scoped Chrome CDP sessions; set `0` to disable. | +| `ADOBE_FIREFLY_SESSION_DISK` | enabled | `open-sse/services/adobeFireflySession.ts` | Persists repaired Adobe sessions under `DATA_DIR`; set `0` for memory-only state. | +| `ADOBE_FIREFLY_MIN_SUBMIT_GAP_MS` | `12000` | `open-sse/services/adobeFireflySession.ts` | Minimum spacing between Adobe Firefly generate submissions. | +| `ADOBE_FIREFLY_BATCH_EXTRA_GAP_MS` | `15000` | `open-sse/services/adobeFireflySession.ts` | Extra quiet period after every third successful Adobe submission. | +| `ADOBE_FIREFLY_CHROME_CDP_PORT` | `9334` | `open-sse/services/adobeFireflyChromeRuntime.ts` | CDP port for the account-scoped Chrome runtime. | +| `ADOBE_FIREFLY_CHROME_VISIBLE` | `0` | `open-sse/services/adobeFireflyChromeRuntime.ts` | Set `1` to keep the Adobe renewal browser visible; the default parks a headed window off-screen. | +| `ADOBE_FIREFLY_CHROME_HEADLESS` | `0` | `open-sse/services/adobeFireflyChromeRuntime.ts` | Debug-only true-headless mode; Adobe colligo normally rejects the resulting risk session. | +| `ADOBE_FIREFLY_CHROME_FORCE_RESTART` | `0` | `open-sse/services/adobeFireflyChromeRuntime.ts` | Set `1` to restart the account-scoped Chrome runtime before renewal. | +| `ADOBE_FIREFLY_CHROME_PING` | automatic | `open-sse/services/adobeFireflyChromeRuntime.ts` | `1` forces, and `0` disables, the in-page generate probe used to prove the renewed ARP session. | +| `ADOBE_FIREFLY_LOGIN_WAIT_MS` | context-dependent | `open-sse/services/adobeFireflyChromeRuntime.ts` | Interactive-login wait budget: `0` on background renewal and `300000` on the explicit login flow unless overridden. | +| `ADOBE_FIREFLY_FORTER_WAIT_MS` | `45000` | `open-sse/services/adobeFireflyChromeRuntime.ts` | Maximum wait for a fresh Forter token during session renewal. | +| `CHROME_PATH` | auto-detect | `open-sse/services/adobeFireflyChromeRuntime.ts` | Optional absolute Chrome executable used when platform auto-detection is insufficient. | +| `TELEGRAM_BOT_TOKEN` | _(unset)_ | `src/lib/telegram/config.ts` | BotFather token that enables the inbound webhook and signs Mini App `initData`. | +| `TELEGRAM_DEFAULT_MODEL` | `auto/chat` | `src/lib/telegram/chatProxy.ts` | Model used for Telegram chat replies. | +| `TELEGRAM_BOT_API_BASE` | `https://api.telegram.org` | `src/lib/telegram/config.ts` | Bot API base URL override for proxies or self-hosted Bot API servers. | +| `TELEGRAM_WEBHOOK_TIMEOUT_MS` | `60000` | `src/lib/telegram/config.ts` | Timeout in milliseconds for outbound Bot API calls. | diff --git a/open-sse/config/constants.ts b/open-sse/config/constants.ts index 1aae014a7a..24210c56a6 100644 --- a/open-sse/config/constants.ts +++ b/open-sse/config/constants.ts @@ -1,4 +1,5 @@ import { getUpstreamTimeoutConfig } from "@/shared/utils/runtimeTimeouts"; +import { resolvePublicCred } from "../utils/publicCreds.ts"; import type { LegacyProvider } from "./providerRegistry.ts"; import { loadProviderCredentials } from "./credentialLoader.ts"; import { generateLegacyProviders } from "./providerRegistry.ts"; @@ -136,7 +137,7 @@ export const OAUTH_ENDPOINTS = { openference: { token: "https://openference.com/oauth/token", auth: "https://openference.com/app/oauth/authorize", - clientId: "omniroute", + clientId: resolvePublicCred("openference_id"), }, }; diff --git a/open-sse/config/providers/registry/openference/index.ts b/open-sse/config/providers/registry/openference/index.ts index 87af280dcb..fe5f50025e 100644 --- a/open-sse/config/providers/registry/openference/index.ts +++ b/open-sse/config/providers/registry/openference/index.ts @@ -1,4 +1,4 @@ -import type { RegistryEntry } from "../../shared.ts"; +import { resolvePublicCred, type RegistryEntry } from "../../shared.ts"; /** * Openference — OpenAI-compatible AI inference gateway (https://openference.com/). @@ -18,7 +18,7 @@ export const openferenceProvider: RegistryEntry = { authHeader: "bearer", passthroughModels: true, oauth: { - clientIdDefault: "omniroute", + clientIdDefault: resolvePublicCred("openference_id"), tokenUrl: "https://openference.com/oauth/token", }, models: [{ id: "GLM-5.2", name: "GLM 5.2", contextLength: 850000 }], diff --git a/open-sse/services/compression/engines/cavemanAdapter.ts b/open-sse/services/compression/engines/cavemanAdapter.ts index ccfcd723f9..0fa8e5bb9e 100644 --- a/open-sse/services/compression/engines/cavemanAdapter.ts +++ b/open-sse/services/compression/engines/cavemanAdapter.ts @@ -262,6 +262,7 @@ export const liteEngine: CompressionEngine = { }, apply(body, options) { const adapter = adaptBodyForCompression(body); + const stepCompressToolResults = options?.stepConfig?.compressToolResults; const result = applyLiteCompression(adapter.body, { ...options, preserveSystemPrompt: options?.config?.preserveSystemPrompt !== false, @@ -269,9 +270,9 @@ export const liteEngine: CompressionEngine = { // (step wins) into stepConfig, so consume that single effective value instead of // AND-ing root and step values — an explicit step `true` must override a global `false`. compressToolResults: - options?.stepConfig?.compressToolResults ?? - options?.config?.lite?.compressToolResults ?? - true, + typeof stepCompressToolResults === "boolean" + ? stepCompressToolResults + : (options?.config?.lite?.compressToolResults ?? true), }); return adapter.adapted ? { ...result, body: adapter.restore(result.body) } : result; }, diff --git a/open-sse/utils/publicCreds.ts b/open-sse/utils/publicCreds.ts index 688cd759ac..a5288ff738 100644 --- a/open-sse/utils/publicCreds.ts +++ b/open-sse/utils/publicCreds.ts @@ -177,6 +177,9 @@ const EMBEDDED_DEFAULTS = { 13, 92, 15, 89, 66, 91, 76, 70, 72, 29, 71, 70, 3, 65, 93, 84, 72, 23, 28, 87, 92, 88, 15, 95, 91, 22, 71, 87, 20, 66, 67, 86, 13, 81, 81, 21, ], + // Openference OAuth — public PKCE client id. The plaintext equals the first + // nine bytes of MASK, so its XOR-masked representation is nine zero bytes. + openference_id: [0, 0, 0, 0, 0, 0, 0, 0, 0], // Trae Cloud IDE — public oauth client id trae_id: [10, 3, 95, 6, 10, 22, 66, 3, 11, 90, 72, 31, 91, 2], // Microsoft Designer web app — public ClientId header sent by the diff --git a/package-lock.json b/package-lock.json index 95985d2f8a..02db692d69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "omniroute", - "version": "3.8.49", + "version": "3.8.50", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "omniroute", - "version": "3.8.49", + "version": "3.8.50", "hasInstallScript": true, "license": "MIT", "workspaces": [ @@ -81,7 +81,7 @@ "sqlite-vec": "^0.1.9", "tailwind-merge": "^3.6.0", "tsx": "^4.23.0", - "undici": "^8.3.0", + "undici": "^8.10.0", "update-notifier": "^7.3.1", "uuid": "^14.0.0", "ws": "^8.18.0", @@ -134,6 +134,7 @@ "lint-staged": "^17.0.8", "lockfile-lint": "^5.0.0", "node-loader": "^2.1.0", + "opencode-ai": "1.18.8", "playwright-ctrf-json-reporter": "^0.0.29", "prettier": "^3.8.3", "promptfoo": "^0.121.18", @@ -153,7 +154,7 @@ "@atjsh/llmlingua-2": "2.0.3", "@huggingface/transformers": "3.5.2", "@tensorflow/tfjs": "4.22.0", - "better-sqlite3": "^13.0.1", + "better-sqlite3": "^13.0.2", "js-tiktoken": "^1.0.20", "keytar": "^7.9.0", "tls-client-node": "^0.2.0", @@ -13757,10 +13758,9 @@ } }, "node_modules/better-sqlite3": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-13.0.1.tgz", - "integrity": "sha512-LYpmOXdkpQYf4wmlxkdzW01XGlOXNIbjLg45yNkh0FQ4814VbK9PdOFmhZpYbej+EZtR/i3FDdhEG98HqZdgnA==", - "hasInstallScript": true, + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-13.0.3.tgz", + "integrity": "sha512-RbOBxmLBG8uvFUc15X9+9SFemKcQ0WBuISBVkpuiaUB2qblC8UWlHEjdWVoZ8AdhSwmoEgsiXKfopX0CQxaACQ==", "license": "MIT", "optional": true, "dependencies": { @@ -28809,6 +28809,205 @@ } } }, + "node_modules/opencode-ai": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/opencode-ai/-/opencode-ai-1.18.8.tgz", + "integrity": "sha512-eZvYK0rIc/NUDQ+s3LsO9gyUU3MswsbNOLZz06iPwVhbg/2jF6bkTaroBgiIdFWKwUn5sj+kSMc4TBYxFkMrNQ==", + "cpu": [ + "arm64", + "x64" + ], + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "os": [ + "darwin", + "linux", + "win32" + ], + "bin": { + "opencode": "bin/opencode.exe" + }, + "optionalDependencies": { + "opencode-darwin-arm64": "1.18.8", + "opencode-darwin-x64": "1.18.8", + "opencode-darwin-x64-baseline": "1.18.8", + "opencode-linux-arm64": "1.18.8", + "opencode-linux-arm64-musl": "1.18.8", + "opencode-linux-x64": "1.18.8", + "opencode-linux-x64-baseline": "1.18.8", + "opencode-linux-x64-baseline-musl": "1.18.8", + "opencode-linux-x64-musl": "1.18.8", + "opencode-windows-arm64": "1.18.8", + "opencode-windows-x64": "1.18.8", + "opencode-windows-x64-baseline": "1.18.8" + } + }, + "node_modules/opencode-darwin-arm64": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/opencode-darwin-arm64/-/opencode-darwin-arm64-1.18.8.tgz", + "integrity": "sha512-ZZCIEgTvHxOHk52Aeqhq59t/R0aqs29bPIgu45XE4rkgjmn/XCkTWalCPtyzJHipdcEbq/g0lqsE1OlJV0oNbA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/opencode-darwin-x64": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/opencode-darwin-x64/-/opencode-darwin-x64-1.18.8.tgz", + "integrity": "sha512-2EXRMJbRKnFPWI9oDU9tb7jDGmKiPmfjCLtwJMe3EF57h5wfcdEH9sP25bR3Og5NbE2M+PtMcJm0jMeHn2XoLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/opencode-darwin-x64-baseline": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/opencode-darwin-x64-baseline/-/opencode-darwin-x64-baseline-1.18.8.tgz", + "integrity": "sha512-eLXa2tK9LRuZ5e20QG2k4dmWAA5xnLgJ1afRTSD0/ybE6CAeK02i8vFCnFFDaxuBo+gnq+yqO8AkqvN1m64V/Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/opencode-linux-arm64": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/opencode-linux-arm64/-/opencode-linux-arm64-1.18.8.tgz", + "integrity": "sha512-7kj3c9JEdryHgK+o8zE/N9KzTOdbiDn6KpY8dl+hM9n5Cnmxezx4IAlgJeC9QxpIx8Omop6CYuZ+17KfrKdKLw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/opencode-linux-arm64-musl": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/opencode-linux-arm64-musl/-/opencode-linux-arm64-musl-1.18.8.tgz", + "integrity": "sha512-tww5TF/LIOv/GoTNyzGYgqDRhbJrhoMu8R+p5yD/SpnXPg3rcfYREw2wRy9yikyPU9sAQksuIIteTsyGerPjlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/opencode-linux-x64": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/opencode-linux-x64/-/opencode-linux-x64-1.18.8.tgz", + "integrity": "sha512-Sm4fbQ9BdLI6hgN6FYYX8Nql+Sqe/2EKHJu3iWg0UYs93AXN4ROi0rvOmRbMk+ycYgOchb0hL6Ti2opxLx17sg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/opencode-linux-x64-baseline": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/opencode-linux-x64-baseline/-/opencode-linux-x64-baseline-1.18.8.tgz", + "integrity": "sha512-egeEF4tk1rK9flIQjjeSVB9cR/X3zUti0pNAHW6ROJkNkj72z2C2FmjK1hZbfjtteCueMXPLptS23JROHGWL1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/opencode-linux-x64-baseline-musl": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/opencode-linux-x64-baseline-musl/-/opencode-linux-x64-baseline-musl-1.18.8.tgz", + "integrity": "sha512-S+438BXs48gLeXX/ya4TSNytDy9mliU3sOAf6j9rfFjzGiF/S08LedemSAnHkr0riBtamik1aRPSmTjhQ0dOBg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/opencode-linux-x64-musl": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/opencode-linux-x64-musl/-/opencode-linux-x64-musl-1.18.8.tgz", + "integrity": "sha512-c+E4Zsp0DYVcuqcDtgxw/4YcFLrVYWdGBR8x4CzpW48ga3RshaH+BlmUiy+GY0yr1x6UR+e2V3w4uzvzm/L9UQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/opencode-windows-arm64": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/opencode-windows-arm64/-/opencode-windows-arm64-1.18.8.tgz", + "integrity": "sha512-7NjdtEIiX28kmsKD9jHbFG4bbwBB5T4dAe2UwdnOqCBb2cl+ETV5eO6kbdC/xWxrgOghgZM1Wtw791T5pQPyag==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/opencode-windows-x64": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/opencode-windows-x64/-/opencode-windows-x64-1.18.8.tgz", + "integrity": "sha512-G+NEgEMvu/dEYshH5IaqHVTmsHVuGdORBvVmgphFiknT7q/NXPuoZCMtMIdfNlEFbu54BlzRDdJCR3Mqe98gUw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/opencode-windows-x64-baseline": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/opencode-windows-x64-baseline/-/opencode-windows-x64-baseline-1.18.8.tgz", + "integrity": "sha512-IGbjFyWoSN9rdGUJX7TWkQ1Yl673Q3dDna54b5NtqeRcZ839p+Z47zzM5m883HKAxrdKCC6Z22HYuDcXLV0laA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/opener": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", @@ -35019,9 +35218,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-8.9.0.tgz", - "integrity": "sha512-aWZpUj7XoGonMClx4gdDRfgBjqeA+F473aDmROQQbM9n6PRfK/u1q/a0X4wMTgcHfT8H6fpbt98PFuDUwFg2YA==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.0.tgz", + "integrity": "sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==", "license": "MIT", "engines": { "node": ">=22.19.0" @@ -36812,12 +37011,7 @@ }, "open-sse": { "name": "@omniroute/open-sse", - "version": "3.8.49", - "dependencies": { - "@toon-format/toon": "^4.1.0", - "safe-regex": "^2.1.1", - "smol-toml": "1.7.1" - } + "version": "3.8.50" } } } diff --git a/package.json b/package.json index 734d171780..d0e6b13c25 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "omniroute", - "version": "3.8.49", - "description": "Unified AI router with 160+ providers, RTK+Caveman compression, auto fallback, MCP/A2A, desktop, PWA, and OpenAI-compatible APIs.", + "version": "3.8.50", + "description": "Unified AI router with 291 providers, RTK+Caveman compression, auto fallback, MCP/A2A, desktop, PWA, and OpenAI-compatible APIs.", "type": "module", "bin": { "omniroute": "bin/omniroute.mjs", @@ -23,6 +23,7 @@ ".env.example", "scripts/build/postinstall.mjs", "scripts/build/fixTlsClientNodeBinary.mjs", + "scripts/build/fixPlaywrightAndroid.mjs", "bin/cli/runtime/", "scripts/postinstall.mjs", "scripts/build/postinstallSupport.mjs", @@ -33,11 +34,15 @@ "scripts/dev/tls-options.mjs", "scripts/check/check-supported-node-runtime.ts", "scripts/dev/sync-env.mjs", + "scripts/build/assembleStandalone.mjs", + "scripts/build/backendOnlyPages.mjs", + "scripts/build/build-tproxy-native.mjs", "scripts/build/native-binary-compat.mjs", "scripts/build/build-next-isolated.mjs", "scripts/build/runtime-env.mjs", "README.md", "LICENSE", + "!**/node_modules/**", "!**/__tests__/**", "!**/*.test.ts", "!**/*.test.tsx", @@ -110,6 +115,8 @@ "test:unit:ci": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=4 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=4 \"tests/unit/dashboard/**/*.test.ts\" && npm run test:unit:serial", "test:unit:ci:shard": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=4096 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=4 --test-shard=$TEST_SHARD tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=4096 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=4 --test-shard=$TEST_SHARD \"tests/unit/dashboard/**/*.test.ts\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=4096 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=1 --test-shard=$TEST_SHARD \"tests/unit/serial/**/*.test.ts\"", "test:unit:fast": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-isolation=none tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-isolation=none \"tests/unit/dashboard/**/*.test.ts\" && npm run test:unit:serial", + "test:scoped": "bash scripts/quality/test-scoped.sh", + "test:scoped:staged": "bash scripts/quality/test-scoped.sh --staged", "test:unit:shard": "concurrently --kill-others-on-fail -n s1,s2 \"npm:test:unit:shard:1\" \"npm:test:unit:shard:2\"", "test:unit:shard:1": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=10 --test-shard=1/2 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=10 --test-shard=1/2 \"tests/unit/dashboard/**/*.test.ts\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=1 --test-shard=1/2 \"tests/unit/serial/**/*.test.ts\"", "test:unit:shard:2": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=10 --test-shard=2/2 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=10 --test-shard=2/2 \"tests/unit/dashboard/**/*.test.ts\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=1 --test-shard=2/2 \"tests/unit/serial/**/*.test.ts\"", @@ -143,6 +150,7 @@ "check:node-runtime": "node --import tsx scripts/check/check-supported-node-runtime.ts", "check:pack-artifact": "node --import tsx scripts/build/validate-pack-artifact.ts", "check:pack-boot": "node scripts/check/check-pack-boot.mjs", + "check:install-upgrade": "node scripts/check/check-install-upgrade.mjs", "check:pack-policy": "node --import tsx scripts/build/validate-pack-artifact.ts --policy-only", "check:cli-i18n": "node scripts/check/check-cli-i18n.mjs", "check:openapi-coverage": "node scripts/check/check-openapi-coverage.mjs", @@ -161,6 +169,7 @@ "check:test-masking": "node scripts/check/check-test-masking.mjs", "check:test-runner-api": "node scripts/check/check-test-runner-api.mjs", "check:changelog-integrity": "node scripts/check/check-changelog-integrity.mjs", + "sweep:stale-fragments": "node scripts/release/sweep-stale-fragments.mjs", "changelog:aggregate": "node scripts/release/aggregate-changelog.mjs", "check:agent-skills-sync": "node --import tsx/esm scripts/skills/generate-agent-skills.mjs", "check:build-scope": "node scripts/check/check-build-scope.mjs", @@ -184,6 +193,7 @@ "check:bundle-size": "node scripts/check/check-bundle-size.mjs", "check:circular-deps": "node scripts/check/check-circular-deps.mjs", "check:mutation-ratchet": "node scripts/check/check-mutation-ratchet.mjs", + "check:rtl-ratchet": "node scripts/check/check-rtl-ratchet.mjs", "check:licenses": "node scripts/check/check-licenses.mjs", "check:pr-evidence": "node scripts/check/check-pr-evidence.mjs", "check:vuln-ratchet": "node scripts/check/check-vuln-ratchet.mjs", @@ -200,9 +210,11 @@ "typecheck:core": "tsc --pretty false -p tsconfig.typecheck-core.json", "typecheck:noimplicit:core": "tsc --pretty false -p tsconfig.typecheck-noimplicit-core.json", "check:dashboard-typecheck": "node scripts/check/check-dashboard-typecheck.mjs", + "check:open-sse-typecheck": "node scripts/check/check-open-sse-typecheck.mjs", "backfill-aggregation": "node --import tsx src/scripts/backfillAggregation.ts", "env:sync": "node scripts/dev/sync-env.mjs", "test:integration": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=1 tests/integration/*.test.ts \"tests/integration/combo-matrix/*.test.ts\"", + "test:integration:ci": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=1 --test-shard=$TEST_SHARD tests/integration/*.test.ts \"tests/integration/combo-matrix/*.test.ts\"", "test:combo:matrix": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=1 \"tests/integration/combo-matrix/*.test.ts\"", "test:combo:live": "cross-env RUN_COMBO_LIVE=1 DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=1 \"tests/integration/combo-live/*.live.test.ts\"", "test:combo:live:vps": "node scripts/test/combo-live-vps.mjs", @@ -232,6 +244,7 @@ "prepare": "husky", "system-info": "node scripts/dev/system-info.mjs", "build:cli-api": "node --import tsx/esm scripts/cli/generate-api-commands.mjs", + "postbuild": "node scripts/build/colocate-standalone.mjs", "release:contributors": "node scripts/release/gen-contributors.mjs", "release:uncovered": "node scripts/release/list-uncovered-commits.mjs", "test:coverage:runner": "node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=8 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true NODE_OPTIONS=--max-old-space-size=8192 c8 --merge-async --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov --check-coverage --statements 60 --lines 60 --functions 60 --branches 60 node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=8 \"tests/unit/dashboard/**/*.test.ts\" && npm run test:unit:serial", @@ -306,7 +319,7 @@ "sqlite-vec": "^0.1.9", "tailwind-merge": "^3.6.0", "tsx": "^4.23.0", - "undici": "^8.3.0", + "undici": "^8.10.0", "update-notifier": "^7.3.1", "uuid": "^14.0.0", "ws": "^8.18.0", @@ -319,7 +332,7 @@ "@atjsh/llmlingua-2": "2.0.3", "@huggingface/transformers": "3.5.2", "@tensorflow/tfjs": "4.22.0", - "better-sqlite3": "^13.0.1", + "better-sqlite3": "^13.0.2", "js-tiktoken": "^1.0.20", "keytar": "^7.9.0", "tls-client-node": "^0.2.0", @@ -365,6 +378,7 @@ "lint-staged": "^17.0.8", "lockfile-lint": "^5.0.0", "node-loader": "^2.1.0", + "opencode-ai": "1.18.8", "playwright-ctrf-json-reporter": "^0.0.29", "prettier": "^3.8.3", "promptfoo": "^0.121.18", @@ -396,9 +410,18 @@ "sharp" ] }, + "allowScripts": { + "better-sqlite3": true, + "esbuild": true, + "@swc/core": true, + "@parcel/watcher": true, + "keytar": true, + "protobufjs": true, + "unrs-resolver": true + }, "overrides": { "fast-xml-parser": "^5.10.1", - "sharp": "^0.35.0", + "sharp": "^0.35.3", "postcss": "^8.5.18", "ip-address": "^10.3.1", "qs": "^6.15.2", diff --git a/scripts/check/check-db-rules.mjs b/scripts/check/check-db-rules.mjs index 2c65c2f6dd..76da82fb9e 100644 --- a/scripts/check/check-db-rules.mjs +++ b/scripts/check/check-db-rules.mjs @@ -49,6 +49,7 @@ export const INTENTIONALLY_INTERNAL = new Set([ "commandCodeAuth", // intentionally-internal: 5 API routes em /api/providers/command-code/auth/* "compression", // intentionally-internal: 2 API routes (settings/compression, context/rtk/config) "compressionDetailNormalizers", // db-internal: importado só por db/compression.ts (normalizeSessionDedupConfig/normalizeCcrConfig/buildDetailConfigDefaults/applyDetailConfigUpdate — normalizadores do detail-config split do compression.ts, #8404) + "connectionRuntimeState", // intentionally-internal: warmupScheduler sqlite/redis stores importam diretamente de @/lib/db/connectionRuntimeState (Rule #2) "vacuumScheduler", // intentionally-internal: src/instrumentation-node.ts (dynamic import, lifecycle wiring per Rule #2) "detailedLogs", // intentionally-internal: 3 callers (callLogs.ts, logs/detail route, embeddings handler) "discovery", // DEAD?: 0 importers na auditoria de 2026-06-11; lib/discovery/index.ts não usa db/discovery diff --git a/scripts/check/check-migration-numbering.mjs b/scripts/check/check-migration-numbering.mjs index 5e174bf0dc..35f9ffca60 100644 --- a/scripts/check/check-migration-numbering.mjs +++ b/scripts/check/check-migration-numbering.mjs @@ -42,12 +42,14 @@ export const KNOWN_DUPLICATE_VERSIONS = new Set([ // --------------------------------------------------------------------------- // ALLOWLIST 2 — gaps de sequência CONHECIDOS. -// Fonte: auditoria do disco (src/lib/db/migrations/) — a sequência pula 026 e 055. -// Estes números nunca tiveram arquivo físico (slots legados que viraram outros -// números via RENAMED_MIGRATION_COMPATIBILITY em migrationRunner.ts). Congelados -// para que o gate bloqueie apenas NOVOS buracos inexplicados na sequência. +// Fonte: auditoria do disco (src/lib/db/migrations/). Além dos slots legados, +// 143–145 estão reservados pelas migrations Radar que já existem na série +// empilhada. O job registry foi promovido de 139 para 146 pela tabela +// RENAMED_MIGRATION_COMPATIBILITY para não ocupar esses slots em trânsito. +// O stale-enforcement remove automaticamente cada reserva quando o arquivo +// correspondente aterrissar na release. // --------------------------------------------------------------------------- -export const KNOWN_GAPS = new Set(["026", "055", "121"]); // 121: número queimado no ciclo v3.8.47 — 122 (#6909) mergeou antes e 121 nunca aterrissou (validação e2e 2026-07-12) +export const KNOWN_GAPS = new Set(["026", "055", "121", "143", "144", "145"]); // 121: número queimado no ciclo v3.8.47 — 122 (#6909) mergeou antes e 121 nunca aterrissou (validação e2e 2026-07-12) function pad3(n) { return String(n).padStart(3, "0"); diff --git a/src/app/api/telegram/update/route.ts b/src/app/api/telegram/update/route.ts index cc0676106a..1fd3582da9 100644 --- a/src/app/api/telegram/update/route.ts +++ b/src/app/api/telegram/update/route.ts @@ -21,6 +21,7 @@ import { extractChatMessage, sendTelegramMessage } from "@/lib/telegram/botApi"; import { getTelegramBotToken, isTelegramEnabled } from "@/lib/telegram/config"; import { verifyInitData, parseInitData } from "@/lib/telegram/initData"; import { proxyChat } from "@/lib/telegram/chatProxy"; +import { formatTelegramGatewayError } from "@/lib/telegram/errorMessage"; import { resolveOmniRouteBaseUrl } from "@/shared/utils/resolveOmniRouteBaseUrl"; /** @@ -151,7 +152,7 @@ async function handleAndReply(chatId: number, text: string, messageId?: number): try { await sendTelegramMessage({ chat_id: chatId, - text: `⚠️ Gateway error: ${(err as Error)?.message || "unknown"}`, + text: formatTelegramGatewayError(err), }); } catch { // Nothing more we can do — the reply channel is down. diff --git a/src/i18n/messages/ar.json b/src/i18n/messages/ar.json index 72bd72dfc3..396e678b03 100644 --- a/src/i18n/messages/ar.json +++ b/src/i18n/messages/ar.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "لم تتم إضافة أي نماذج جديدة (كلها موجودة بالفعل).", "importDoneCount": "✓ تم! {count, plural, one {استُورد نموذج واحد.} other {استُورد # من النماذج.}}", "unexpectedErrorOccurred": "حدث خطأ غير متوقع", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "عدد الاتصالات: {count, plural, one {اتصال واحد} other {# اتصالات}}", "messagesPath": "الرسائل", "responsesPath": "الردود", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) هو الصديق المؤسس للمصادر المفتوحة لـ OmniRoute", "cheaperInferenceSupporterBadge": "صديق مفتوح المصدر", "cheaperInferenceSupporterTooltip": "‏Cheaper Inference تدعم OmniRoute كصديق للمصادر المفتوحة", - "kimiPartnerLinkNote": "رابط شريك — يدعم OmniRoute دون أي تكلفة إضافية عليك" + "kimiPartnerLinkNote": "رابط شريك — يدعم OmniRoute دون أي تكلفة إضافية عليك", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "الإعدادات", @@ -7812,10 +7819,6 @@ "label": "الحد الأدنى للصفوف لضغطها", "description": "الحد الأدنى للصفوف في مصفوفة JSON متجانسة المطلوبة لتشغيل الضغط الجدولي. الافتراضي: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "الحفاظ على توجيه النظام" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "الحد الأدنى لطول الرسالة" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "منسوخ!", "run": "تشغيل", "running": "جارٍ...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "الاستجابة", "tunnel": "نفق", "send": "إرسال", diff --git a/src/i18n/messages/az.json b/src/i18n/messages/az.json index b9d92929cb..8deb80c81c 100644 --- a/src/i18n/messages/az.json +++ b/src/i18n/messages/az.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "No new models were added (all already exist).", "importDoneCount": "✓ Done! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "An unexpected error occurred", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "messages", "responsesPath": "responses", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) OmniRoute-un təsisçi Açıq Mənbə Dostudur", "cheaperInferenceSupporterBadge": "Açıq Mənbə Dostu", "cheaperInferenceSupporterTooltip": "Cheaper Inference OmniRoute-u Açıq Mənbə Dostu kimi dəstəkləyir", - "kimiPartnerLinkNote": "Tərəfdaş linki — sizə heç bir əlavə xərc olmadan OmniRoute-u dəstəkləyir" + "kimiPartnerLinkNote": "Tərəfdaş linki — sizə heç bir əlavə xərc olmadan OmniRoute-u dəstəkləyir", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Settings", @@ -7812,10 +7819,6 @@ "label": "Kompaktlaşdırmaq üçün minimum sətir sayı", "description": "Cədvəl kompaktlaşdırmasını işə salmaq üçün tələb olunan bircins JSON massivindəki minimum sətir sayı. Standart: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Sistem promptunu qoru" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Minimum mesaj uzunluğu" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Kopyalandı!", "run": "İşə sal", "running": "İcra olunur...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Cavab", "tunnel": "Tunel", "send": "Göndər", diff --git a/src/i18n/messages/bg.json b/src/i18n/messages/bg.json index 0db69ab00d..f04ab0b42b 100644 --- a/src/i18n/messages/bg.json +++ b/src/i18n/messages/bg.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Не са добавени нови модели (всички вече съществуват).", "importDoneCount": "✓ Готово! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Възникна неочаквана грешка", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "съобщения", "responsesPath": "отговори", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) е основаващият приятел на отворения код на OmniRoute", "cheaperInferenceSupporterBadge": "Приятел на отворения код", "cheaperInferenceSupporterTooltip": "Cheaper Inference подкрепя OmniRoute като приятел на отворения код", - "kimiPartnerLinkNote": "Партньорска връзка — поддържа OmniRoute без допълнителни разходи за вас" + "kimiPartnerLinkNote": "Партньорска връзка — поддържа OmniRoute без допълнителни разходи за вас", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Настройки", @@ -7812,10 +7819,6 @@ "label": "Минимален брой редове за компактизиране", "description": "Минимален брой редове в хомогенен JSON масив, необходими за задействане на таблично компактизиране. По подразбиране: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Запазване на системната подкана" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Минимална дължина на съобщението" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Копирано!", "run": "Изпълнение", "running": "Изпълнява се...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Отговор", "tunnel": "Тунел", "send": "Изпращане", diff --git a/src/i18n/messages/bn.json b/src/i18n/messages/bn.json index 4e6cc55b4d..cb478b1a1a 100644 --- a/src/i18n/messages/bn.json +++ b/src/i18n/messages/bn.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "No new models were added (all already exist).", "importDoneCount": "✓ Done! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "An unexpected error occurred", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "messages", "responsesPath": "responses", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) হল OmniRoute-এর প্রতিষ্ঠাতা ওপেন সোর্স বন্ধু", "cheaperInferenceSupporterBadge": "ওপেন সোর্স বন্ধু", "cheaperInferenceSupporterTooltip": "Cheaper Inference একজন ওপেন সোর্স বন্ধু হিসেবে OmniRoute-কে সমর্থন করে", - "kimiPartnerLinkNote": "পার্টনার লিঙ্ক — আপনার কোনো অতিরিক্ত খরচ ছাড়াই OmniRoute-কে সমর্থন করে" + "kimiPartnerLinkNote": "পার্টনার লিঙ্ক — আপনার কোনো অতিরিক্ত খরচ ছাড়াই OmniRoute-কে সমর্থন করে", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Settings", @@ -7812,10 +7819,6 @@ "label": "কম্প্যাক্ট করার জন্য ন্যূনতম সারি", "description": "ট্যাবুলার কম্প্যাকশন ট্রিগার করার জন্য একটি সমজাতীয় JSON অ্যারেতে প্রয়োজনীয় ন্যূনতম সারি। ডিফল্ট: 8।" }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "সিস্টেম প্রম্পট সংরক্ষণ করুন" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "বার্তার ন্যূনতম দৈর্ঘ্য" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "কপি করা হয়েছে!", "run": "চালান", "running": "চলছে...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "প্রতিক্রিয়া", "tunnel": "টানেল", "send": "পাঠান", diff --git a/src/i18n/messages/cs.json b/src/i18n/messages/cs.json index 721e18a434..ca4d2ae5b6 100644 --- a/src/i18n/messages/cs.json +++ b/src/i18n/messages/cs.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Nebyly přidány žádné nové modely (všechny již existují).", "importDoneCount": "✓ Hotovo! {count, plural, one {# importován model.} other {# importováno modelů.}}", "unexpectedErrorOccurred": "Došlo k neočekávané chybě", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# spojení} other {# spojení}}", "messagesPath": "messages", "responsesPath": "responses", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) je zakládající open source přítel OmniRoute", "cheaperInferenceSupporterBadge": "Přítel open source", "cheaperInferenceSupporterTooltip": "Cheaper Inference podporuje OmniRoute jako přítel open source", - "kimiPartnerLinkNote": "Partnerský odkaz — podporuje OmniRoute bez jakýchkoli dalších nákladů pro vás" + "kimiPartnerLinkNote": "Partnerský odkaz — podporuje OmniRoute bez jakýchkoli dalších nákladů pro vás", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Nastavení", @@ -7812,10 +7819,6 @@ "label": "Minimální počet řádků ke komprimaci", "description": "Minimální počet řádků v homogenním poli JSON vyžadovaný ke spuštění tabulkové komprimace. Výchozí: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Zachovat systémový prompt" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Minimální délka zprávy" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Zkopírováno!", "run": "Spustit", "running": "Spouští se...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Odpověď", "tunnel": "Tunel", "send": "Odeslat", diff --git a/src/i18n/messages/da.json b/src/i18n/messages/da.json index 476a9762a4..ecf62abaa9 100644 --- a/src/i18n/messages/da.json +++ b/src/i18n/messages/da.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Ingen nye modeller blev tilføjet (alle findes allerede).", "importDoneCount": "✓ Færdig! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Der opstod en uventet fejl", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "beskeder", "responsesPath": "svar", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) er OmniRoutes grundlæggende open source-ven", "cheaperInferenceSupporterBadge": "Open source-ven", "cheaperInferenceSupporterTooltip": "Cheaper Inference støtter OmniRoute som open source-ven", - "kimiPartnerLinkNote": "Partnerlink — understøtter OmniRoute uden ekstra omkostninger for dig" + "kimiPartnerLinkNote": "Partnerlink — understøtter OmniRoute uden ekstra omkostninger for dig", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Indstillinger", @@ -7812,10 +7819,6 @@ "label": "Minimum rækker til komprimering", "description": "Minimum antal rækker i et homogent JSON-array, der kræves for at udløse tabelkomprimering. Standard: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Bevar systemprompt" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Minimum meddelelseslængde" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Kopieret!", "run": "Kør", "running": "Kører...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Svar", "tunnel": "Tunnel", "send": "Send", diff --git a/src/i18n/messages/de.json b/src/i18n/messages/de.json index cf4fe18287..8c5bdbc2a5 100644 --- a/src/i18n/messages/de.json +++ b/src/i18n/messages/de.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Es wurden keine neuen Modelle hinzugefügt (alle bereits vorhanden).", "importDoneCount": "✓ Fertig! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Es ist ein unerwarteter Fehler aufgetreten", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "Nachrichten", "responsesPath": "Antworten", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) ist OmniRoutes Gründungs-Open-Source-Freund", "cheaperInferenceSupporterBadge": "Open-Source-Freund", "cheaperInferenceSupporterTooltip": "Cheaper Inference unterstützt OmniRoute als Open-Source-Freund", - "kimiPartnerLinkNote": "Partnerlink — unterstützt OmniRoute ohne zusätzliche Kosten für Sie" + "kimiPartnerLinkNote": "Partnerlink — unterstützt OmniRoute ohne zusätzliche Kosten für Sie", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Einstellungen", @@ -7812,10 +7819,6 @@ "label": "Minimale Zeilen zum Komprimieren", "description": "Mindestanzahl an Zeilen in einem homogenen JSON-Array, die erforderlich ist, um eine tabellarische Komprimierung auszulösen. Standard: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "System-Prompt beibehalten" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Mindestlänge der Nachricht" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Kopiert!", "run": "Ausführen", "running": "Wird ausgeführt...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Antwort", "tunnel": "Tunnel", "send": "Senden", diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 7803e8eeea..f55671d00c 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -1094,6 +1094,8 @@ "costsFreeTiersSubtitle": "Monthly free-token allowances", "freeProviderRankings": "Free Provider Rankings", "freeProviderRankingsSubtitle": "Best free providers ranked by model ELO scores", + "radar": "Radar Catalog", + "radarSubtitle": "Community-enriched free model catalog", "costsQuotaShare": "Quota Sharing", "costsPricing": "Pricing", "logsProxy": "Proxy Logs", @@ -5027,11 +5029,6 @@ "hideFailedAuto": "Auto-hide failed models", "selectAllModels": "Select all", "hideAllModels": "Hide all", - "anonymousFallbackTitle": "Anonymous fallback", - "anonymousFallbackDesc": "When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", - "anonymousFallbackEnabled": "Anonymous fallback enabled for {provider}", - "anonymousFallbackDisabled": "Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", - "anonymousFallbackUpdateFailed": "Failed to update anonymous fallback setting", "modelsActive": "Active", "showModel": "Show model", "hideModel": "Hide model", @@ -5076,6 +5073,8 @@ "noNewModelsAddedExisting": "No new models were added (all already exist).", "importDoneCount": "✓ Done! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "An unexpected error occurred", + "getApiKey": "Get API key", + "getApiKeyDescription": "Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "messages", "responsesPath": "responses", @@ -5492,6 +5491,13 @@ "newApiUserIdLabel": "New-API User ID", "newApiUserIdPlaceholder": "e.g. 12345", "newApiUserIdHint": "AgentRouter New-Api-User header value, used together with the console API key to fetch quota balance.", + "newApiAggregatorToggleLabel": "Aggregator Gateway", + "newApiAggregatorToggleHint": "Enable balance detection for New-API / One-API / Sub2API aggregator nodes. The dashboard will show the balance badge and quota-preflight routing will skip exhausted accounts.", + "newApiAggregatorConsoleApiKeyHint": "System Access Token for the aggregator's /api/user/self endpoint. Not the routing API key.", + "newApiAggregatorUserIdHint": "New-Api-User header value used to fetch the aggregator user's quota balance.", + "newApiAggregatorQuotaPerUnitLabel": "Quota Per Unit", + "newApiAggregatorQuotaPerUnitHint": "New-API credit units per $1 (default: 500000). Override if your aggregator uses a different rate.", + "featureFlagNewApiAggregatorBalanceDescription": "Enable balance detection for New-API / One-API / Sub2API aggregator compatible nodes", "cpaModeDisabledTitle": "CLIProxyAPI compatibility mode is disabled", "cpaModeEnabledTitle": "CLIProxyAPI compatibility mode is enabled", "customUserAgentHint": "Custom User Agent Hint", @@ -5607,6 +5613,7 @@ "tagGroupPlaceholder": "Tag Group Placeholder", "testModel": "Test Model", "testingModel": "Testing Model", + "modelTestQuotaTooltip": "Quota exhausted — resets tomorrow or needs a top-up", "toggleOffShort": "Off", "toggleOnShort": "On", "tokenExpiredBadge": "Token Expired Badge", @@ -5776,6 +5783,7 @@ "onboardingProviderDescriptions": { "360ai": "Get API key at ai.360.cn", "agentrouter": "Get $200 free credits at https://agentrouter.org/register — no credit card required.", + "unorouter": "Create an API key at https://unorouter.ai, then paste it here as a Bearer token.", "agnes": "Get API key at agnes-ai.com", "aimlapi": "Free tier paused (2026) — AI/ML API is now pay-as-you-go only (min $20 top-up); no recurring free credits.", "ai21": "$10 trial credits on signup (valid 3 months), no credit card required", @@ -6024,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) is OmniRoute's founding Open Source Friend", "cheaperInferenceSupporterBadge": "Open Source Friend", "cheaperInferenceSupporterTooltip": "Cheaper Inference backs OmniRoute as an Open Source Friend", - "kimiPartnerLinkNote": "Partner link — supports OmniRoute at no extra cost to you" + "kimiPartnerLinkNote": "Partner link — supports OmniRoute at no extra cost to you", + "anonymousFallbackTitle": "Anonymous fallback", + "anonymousFallbackDesc": "When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "Failed to update anonymous fallback setting" }, "settings": { "title": "Settings", @@ -7806,10 +7819,6 @@ "label": "Minimum rows to compact", "description": "Minimum rows in a homogeneous JSON array required to trigger tabular compaction. Default: 8." }, - "compressToolResults": { - "label": "Proactively truncate long tool results", - "description": "Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Preserve system prompt" }, @@ -7833,6 +7842,10 @@ }, "minMessageLength": { "label": "Minimum message length" + }, + "compressToolResults": { + "label": "Proactively truncate long tool results", + "description": "Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10189,6 +10202,8 @@ "copied": "Copied!", "run": "Run", "running": "Running...", + "loading": "Loading...", + "retry": "Retry", "response": "Response", "tunnel": "Tunnel", "send": "Send", @@ -10788,6 +10803,8 @@ "sourceModel": "Source model (agent native)", "targetModel": "Target model (OmniRoute)", "noMappings": "No model mappings configured. Run setup wizard to auto-detect models.", + "noMappingsDesc": "No model mappings configured yet. Add mappings to route agent requests through OmniRoute.", + "addMapping": "Add mapping", "selectModel": "Select…", "saveMappings": "Save mappings", "setupWizard": "Setup wizard", @@ -11535,7 +11552,10 @@ "noSavedProxiesError": "No saved proxies found. Add proxies in Settings → Proxy first.", "updateProviderFailed": "Failed to update provider", "providerEnabled": "{provider} enabled", - "providerDisabled": "{provider} disabled" + "providerDisabled": "{provider} disabled", + "providerAdded": "{provider} added", + "add": "Add", + "manualApiKey": "Use a manual API key" }, "gamification": { "leaderboardScopes": { @@ -12232,6 +12252,87 @@ "dismissAriaLabel": "Dismiss" }, "featureFlagExposeFunctionalGatewayMirrorsDescription": "Advertise / 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.", + "radarPage": { + "title": "Radar Catalog", + "subtitle": "Free model catalog enriched with community intelligence", + "loading": "Loading catalog...", + "errorLoading": "Failed to load Radar catalog", + "emptyState": "No catalog data yet. Sync to download the latest feed.", + "syncNow": "Sync now", + "syncing": "Syncing...", + "syncCta": "Sync now", + "syncFailed": "Sync failed", + "flagDisabled": "Radar is disabled", + "activationFailed": "Activation failed", + "feedVersion": "Feed version", + "feedTier": "Tier", + "feedFetched": "Last fetched", + "tierLive": "Live (real-time)", + "tierCommunity": "Community (30-day delay)", + "activateTitle": "Activate Radar", + "activateDescription": "Radar enriches the free model catalog with community-sourced intelligence — updated model availability, quotas, and setup guides.", + "privacyNoUpload": "Nothing is uploaded — your data stays local", + "privacyOnlySigned": "Only cryptographically signed metadata is downloaded", + "privacyLocalOnly": "All processing happens on your OmniRoute instance", + "activateButton": "Activate", + "activating": "Activating...", + "keySectionTitle": "Already have a supporter key?", + "keyInvalidFormatError": "Invalid key format. It must start with \"omr_\" followed by 40 hex characters.", + "activateWithKeyButton": "Activate supporter", + "changeKeyButton": "Change key", + "claimSectionTitle": "Don't have a supporter key yet?", + "contributorButton": "I'm a contributor", + "contributorHint": "Verify your GitHub account — 5+ merged pull requests or a top-100 contributor spot unlocks a free supporter key.", + "supporterButton": "Support the project", + "supporterHint": "Support OmniRoute to get a supporter key with the live catalog and extra perks.", + "colProvider": "Provider", + "colModel": "Model", + "colQuota": "Quota", + "colContext": "Context", + "colCapabilities": "Capabilities", + "colTos": "ToS Risk", + "newBadge": "new", + "setupGuide": "Setup guide", + "disabledByFeed": "Disabled by Radar feed", + "capTools": "Tools", + "capVision": "Vision", + "capThinking": "Thinking", + "catalogTab": "Catalog", + "freeCreditsTab": "Free credits", + "freeCreditsSubtitle": "Referral links from Radar-tracked providers — using them costs you nothing extra and helps support OmniRoute.", + "fixedLinksEmpty": "No referral links available yet. Sync Radar to check for updates.", + "requiredActionLabel": "What to do:", + "claimButton": "Claim credits", + "campaignsTitle": "Limited-time campaigns", + "campaignsEmpty": "No active campaigns right now — check back later.", + "campaignsUpsellCommunity": "Limited-time campaigns are a supporter extra. Everything on this page's fixed links stays free for everyone.", + "campaignsValidUntil": "Valid until {date}" + }, + "radarSetupPage": { + "title": "Provider Setup", + "setupTitle": "Setup: {provider}", + "setupSubtitle": "Follow the steps below to configure this provider", + "loading": "Loading...", + "loadFailed": "Failed to load setup data", + "flagDisabled": "Radar is disabled", + "providerNotFound": "Provider \"{provider}\" not found in catalog", + "noProvider": "No provider specified. Return to the catalog and select a provider.", + "backToCatalog": "Back to catalog", + "providerConfigured": "Provider is configured and ready", + "getApiKey": "Get your API key", + "setupSteps": "Setup steps", + "noGuide": "No setup guide available for this provider.", + "visitDocs": "Visit provider docs", + "testConnection": "Test connection", + "testDescription": "Verify that your connection is working correctly.", + "testButton": "Test connection", + "testing": "Testing...", + "testSuccess": "Connection successful!", + "testFailed": "Connection test failed", + "addConnection": "Add connection", + "addConnectionDescription": "Don't have a connection yet? Add one in the providers dashboard.", + "addConnectionLink": "Go to providers →" + }, "resilienceConnections": { "title": "Connection Resilience", "table": { diff --git a/src/i18n/messages/es.json b/src/i18n/messages/es.json index d4f6d28224..59a09ed8b9 100644 --- a/src/i18n/messages/es.json +++ b/src/i18n/messages/es.json @@ -3730,7 +3730,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Superficie de integración", "sectionDescription": "API compatibles con OpenAI y puntos finales de protocolo operativo", - "tabApis": "__MISSING__:APIs", + "tabApis": "API", "tabProtocols": "Protocolos", "tabsAria": "Secciones de punto final", "protocolsTitle": "Protocolos", @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "No se agregaron nuevos modelos (todos ya existen).", "importDoneCount": "✓ ¡Listo! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Ocurrió un error inesperado", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "mensajes", "responsesPath": "respuestas", @@ -5449,8 +5451,8 @@ "t3ChatWebCookieHint": "Abra t3.chat → DevTools → Aplicación → Almacenamiento local → https://t3.chat, copie 'convex-session-id'. Luego abra DevTools → Red, copie el encabezado completo de la cookie de cualquier solicitud de chat. Pegue ambos valores en los campos siguientes.", "t3ChatWebCookiePlaceholder": "ID-sesión-convexa=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", - "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", + "blockClaudeExtraUsageDescription": "Cuando está activado, OmniRoute marca esta conexión de Claude como no disponible tan pronto como la API de uso informe de uso adicional en cola, para que el fallback cambie a otra conexión en lugar de continuar con la facturación adicional de pago por uso.", + "blockClaudeExtraUsageLabel": "Bloquear el uso adicional de Claude", "disableCoolingDescription": "Skip the transient cooldown so this connection stays eligible even after recoverable errors (terminal states like banned/expired still apply).", "disableCoolingLabel": "Disable cooldown for this connection", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5637,13 +5639,13 @@ "importGrokAuth": "Import Grok Build auth", "zedImportTitle": "Import from Zed Keychain", "zedImportDescription": "Discover AI provider credentials (OpenAI, Anthropic, Google, Mistral, xAI) stored by Zed IDE in the OS keychain and import them as connections. Zed IDE must be installed on this machine.", - "zedImportButton": "__MISSING__:Import from Zed", - "zedImportFailed": "__MISSING__:Zed import failed", + "zedImportButton": "Importar desde Zed", + "zedImportFailed": "Error al importar desde Zed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", "zedImportSuccess": "Se han importado {credentials} credencial(es) de Zed para {providers} proveedor(es)", - "zedImporting": "__MISSING__:Importing…", + "zedImporting": "Importando…", "zedNoCredentials": "No Zed credentials found in the keychain", "zedUnsupportedCredentials": "Found {count} keychain credential(s), but none matched supported providers", "zedManualTitle": "Manual Token Import", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) is an official OmniRoute launch partner", "cheaperInferenceSupporterBadge": "Amigo del código abierto", "cheaperInferenceSupporterTooltip": "Cheaper Inference apoya a OmniRoute como amigo del código abierto", - "kimiPartnerLinkNote": "Partner link — supports OmniRoute at no extra cost to you" + "kimiPartnerLinkNote": "Partner link — supports OmniRoute at no extra cost to you", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Configuración", @@ -7812,10 +7819,6 @@ "label": "Minimum rows to compact", "description": "Minimum rows in a homogeneous JSON array required to trigger tabular compaction. Default: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Preserve system prompt" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Minimum message length" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Copied!", "run": "Run", "running": "Running...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Response", "tunnel": "Tunnel", "send": "Send", diff --git a/src/i18n/messages/fa.json b/src/i18n/messages/fa.json index a3571a5f56..063daa3e84 100644 --- a/src/i18n/messages/fa.json +++ b/src/i18n/messages/fa.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "No new models were added (all already exist).", "importDoneCount": "✓ Done! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "An unexpected error occurred", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "messages", "responsesPath": "responses", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) دوست بنیان‌گذار متن‌باز OmniRoute است", "cheaperInferenceSupporterBadge": "دوست متن‌باز", "cheaperInferenceSupporterTooltip": "‏Cheaper Inference از OmniRoute به‌عنوان دوست متن‌باز حمایت می‌کند", - "kimiPartnerLinkNote": "لینک همکاری — پشتیبانی از OmniRoute بدون هزینه اضافی برای شما" + "kimiPartnerLinkNote": "لینک همکاری — پشتیبانی از OmniRoute بدون هزینه اضافی برای شما", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Settings", @@ -7812,10 +7819,6 @@ "label": "حداقل ردیف‌ها برای فشرده‌سازی", "description": "حداقل ردیف‌ها در یک آرایه همگن JSON که برای فعال‌سازی فشرده‌سازی جدولی لازم است. پیش‌فرض: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "حفظ پرامپت سیستم" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "حداقل طول پیام" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "کپی شد!", "run": "اجرا", "running": "در حال اجرا...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "پاسخ", "tunnel": "تونل", "send": "ارسال", diff --git a/src/i18n/messages/fi.json b/src/i18n/messages/fi.json index ffb6762c00..f7b26554d0 100644 --- a/src/i18n/messages/fi.json +++ b/src/i18n/messages/fi.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Uusia malleja ei lisätty (kaikki on jo olemassa).", "importDoneCount": "✓ Valmis! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Tapahtui odottamaton virhe", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "viestejä", "responsesPath": "vastaukset", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) on OmniRouten perustajan avoimen lähdekoodin ystävä", "cheaperInferenceSupporterBadge": "Avoimen lähdekoodin ystävä", "cheaperInferenceSupporterTooltip": "Cheaper Inference tukee OmniRoutea avoimen lähdekoodin ystävänä", - "kimiPartnerLinkNote": "Kumppanilinkki — tukee OmniRoutea ilman lisäkustannuksia sinulle" + "kimiPartnerLinkNote": "Kumppanilinkki — tukee OmniRoutea ilman lisäkustannuksia sinulle", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Asetukset", @@ -7812,10 +7819,6 @@ "label": "Tiivistettävien rivien vähimmäismäärä", "description": "Homogeenisen JSON-taulukon rivien vähimmäismäärä taulukkomaisen tiivistämisen käynnistämiseksi. Oletus: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Säilytä järjestelmäkehote" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Viestin vähimmäispituus" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Kopioitu!", "run": "Suorita", "running": "Suoritetaan...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Vastaus", "tunnel": "Tunneli", "send": "Lähetä", diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json index 802b5f0af0..d8b4e78ef0 100644 --- a/src/i18n/messages/fr.json +++ b/src/i18n/messages/fr.json @@ -937,7 +937,7 @@ "disabled": "Désactivé", "featureFlagOmnirouteEmergencyFallbackDescription": "Router les requêtes ayant épuisé leur budget vers le fournisseur/modèle de secours gratuit d'urgence.", "featureFlagArenaEloSyncEnabledDescription": "Activer la synchronisation périodique de l'ELO du classement Arena AI pour les classements d'intelligence des modèles.", - "featureFlagExposeCcDiscoveryAliasesDescription": "__MISSING__: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.", + "featureFlagExposeCcDiscoveryAliasesDescription": "Afficher les identifiants miroir claude// dans /v1/models afin que la découverte de modèles de la passerelle Claude Code répertorie les modèles non-Claude. Attention : cette option double les entrées du catalogue pour tous les clients lorsqu'elle est activée globalement.", "sidebar": { "home": "Accueil", "dashboard": "Tableau de bord", @@ -1055,7 +1055,7 @@ "combosLive": "Combo Studio", "combosLiveSubtitle": "Cascade de routage en direct", "compressionStudio": "Compression Studio", - "compressionExclusions": "__MISSING__:Exclusions", + "compressionExclusions": "Exclusions", "contextSettingsSubtitle": "Valeurs par défaut globales", "contextHeadroomSubtitle": "Compactage tabulaire", "contextSessionDedupSubtitle": "Déduplication inter-tours", @@ -1066,7 +1066,7 @@ "contextUltraSubtitle": "Élagage heuristique", "contextOmniglyphSubtitle": "Contexte sous forme d'images", "compressionStudioSubtitle": "Cascade de moteurs en direct", - "compressionExclusionsSubtitle": "__MISSING__:Per-model/endpoint bypass", + "compressionExclusionsSubtitle": "Contournement par modèle ou point de terminaison", "chaosConfigSubtitle": "Exécution parallèle multi-modèles", "routingSection": "Routing", "protocolsSection": "Protocols", @@ -1109,7 +1109,7 @@ "settingsSecurity": "Security", "settingsAccessTokens": "Jetons d'accès", "settingsFeatureFlags": "Indicateurs de fonctionnalités", - "settingsCache": "__MISSING__:Cache", + "settingsCache": "Cache", "settingsAuthz": "Authz", "settingsRouting": "Routing", "settingsResilience": "Resilience", @@ -1121,7 +1121,7 @@ "runtime": "Runtime", "consoleLogs": "Console Logs", "logsTimeline": "Timeline", - "logsTimelineSubtitle": "__MISSING__:Visual request timeline", + "logsTimelineSubtitle": "Chronologie visuelle des requêtes", "globalRouting": "Global Routing", "mitmProxy": "MITM Proxy", "oneProxy": "1Proxy", @@ -1196,7 +1196,7 @@ "settingsSecuritySubtitle": "Auth and encryption", "settingsAccessTokensSubtitle": "Jetons CLI restreints pour le mode distant", "settingsFeatureFlagsSubtitle": "Basculer les capacités du système", - "settingsCacheSubtitle": "__MISSING__:Model catalog and response caching", + "settingsCacheSubtitle": "Mise en cache du catalogue de modèles et des réponses", "settingsSidebar": "Sidebar", "settingsSidebarSubtitle": "Customize sidebar layout", "settingsAuthzSubtitle": "Inventaire des routes et politique de contournement", @@ -1561,7 +1561,7 @@ "settingsGeneralDescription": "Storage, database, and general instance configuration", "settingsAppearanceDescription": "Theme, branding, and visual customization", "settingsAiDescription": "AI behaviors, thinking budgets, vision, and memory settings", - "settingsCacheDescription": "__MISSING__:TTL for model catalog cache entries", + "settingsCacheDescription": "Durée de vie (TTL) des entrées du cache du catalogue de modèles", "settingsSecurityDescription": "Authentication, authorization, and access control settings", "featureFlags": "Indicateurs de fonctionnalités", "featureFlagsDescription": "Capacités du système de contrôle et fonctionnalités expérimentales", @@ -2515,14 +2515,14 @@ "auto": "Auto", "always": "Toujours" }, - "ccDiscoveryInfoButton": "__MISSING__:How to enable discovery in Claude Code", - "ccDiscoveryInfoTooltip": "__MISSING__:Advertise non-Claude models under claude/<provider>/<model> mirror ids so Claude Code's gateway model discovery can list them. Doubles catalog entries for all clients when enabled globally.", - "ccDiscoveryInfoLink": "__MISSING__:Open Feature Flags", - "ccOnboardingTitle": "__MISSING__:settings.json for gateway model discovery", - "ccOnboardingCopy": "__MISSING__:Copy", - "ccOnboardingCopied": "__MISSING__:Copied", - "ccOnboardingKeyPlaceholder": "__MISSING__:", - "ccOnboardingWindowNote": "__MISSING__:Claude Code assumes a 200K context window for any model id it does not recognize. For a model with a different real window, add CLAUDE_CODE_AUTO_COMPACT_WINDOW just under it so auto-compaction does not fire too early.", + "ccDiscoveryInfoButton": "Comment activer la découverte dans Claude Code", + "ccDiscoveryInfoTooltip": "Afficher les modèles non-Claude sous forme d'identifiants miroir claude// afin que la découverte de modèles de la passerelle Claude Code puisse les répertorier. Cette option double les entrées du catalogue pour tous les clients lorsqu'elle est activée globalement.", + "ccDiscoveryInfoLink": "Ouvrir les indicateurs de fonctionnalités", + "ccOnboardingTitle": "settings.json pour la découverte des modèles de la passerelle", + "ccOnboardingCopy": "Copier", + "ccOnboardingCopied": "Copié", + "ccOnboardingKeyPlaceholder": "", + "ccOnboardingWindowNote": "Claude Code suppose une fenêtre de contexte de 200K pour tout identifiant de modèle qu'il ne reconnaît pas. Pour un modèle dont la fenêtre réelle est différente, ajoutez CLAUDE_CODE_AUTO_COMPACT_WINDOW juste en dessous afin que le compactage automatique ne se déclenche pas trop tôt.", "failedSave": "Échec de l'enregistrement", "profileSyncTitle": "Synchronisation automatique des profils CLI", "profileSyncDescription": "Une fois les modèles de fournisseurs synchronisés, régénérer automatiquement les profils d'outils CLI à partir du catalogue en direct. Désactivé par défaut — seuls les fichiers de profil sont écrits ; la configuration active/par défaut n'est jamais modifiée.", @@ -3730,7 +3730,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Surface d'intégration", "sectionDescription": "API compatibles OpenAI et points de terminaison du protocole opérationnel", - "tabApis": "__MISSING__:APIs", + "tabApis": "API", "tabProtocols": "Protocoles", "tabsAria": "Sections de point de terminaison", "protocolsTitle": "Protocoles", @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Aucun nouveau modèle n'a été ajouté (tous existent déjà).", "importDoneCount": "✓ C'est fait ! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Une erreur inattendue s'est produite", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "messages", "responsesPath": "réponses", @@ -5203,18 +5205,18 @@ "interceptFetchHint": "Réécrire les appels d'outils natifs web_fetch vers le point de terminaison /v1/web/fetch d'OmniRoute.", "interceptionLoadError": "Échec du chargement des paramètres d'interception : {error}", "interceptionSaveError": "Échec de l'enregistrement des paramètres d'interception : {error}", - "ccAliasSectionTitle": "__MISSING__:Expose in Claude Code (claude/…)", - "ccAliasSectionHint": "__MISSING__:Advertise this provider's models under claude/<provider>/<model> mirror ids so Claude Code's gateway model discovery can list them. Off by default — enabling this doubles catalog entries for all clients.", - "ccAliasProviderLevelLabel": "__MISSING__:Provider default", - "ccAliasModelOverridesLabel": "__MISSING__:Per-model overrides", - "ccAliasModelOverrideAriaLabel": "__MISSING__:Override for {modelId}", - "ccAliasStateInherit": "__MISSING__:Inherit", - "ccAliasStateOn": "__MISSING__:On", - "ccAliasStateOff": "__MISSING__:Off", - "ccAliasAddModelPlaceholder": "__MISSING__:Model id (e.g. gpt-4o)", - "ccAliasAddModelButton": "__MISSING__:Add override", - "ccAliasLoadError": "__MISSING__:Failed to load discovery-alias settings: {error}", - "ccAliasSaveError": "__MISSING__:Failed to save discovery-alias setting: {error}", + "ccAliasSectionTitle": "Exposer dans Claude Code (claude/…)", + "ccAliasSectionHint": "Afficher les modèles de ce fournisseur sous forme d'identifiants miroir claude// afin que la découverte de modèles de la passerelle Claude Code puisse les répertorier. Cette option est désactivée par défaut ; son activation double les entrées du catalogue pour tous les clients.", + "ccAliasProviderLevelLabel": "Valeur par défaut du fournisseur", + "ccAliasModelOverridesLabel": "Surcharges par modèle", + "ccAliasModelOverrideAriaLabel": "Surcharge pour {modelId}", + "ccAliasStateInherit": "Hériter", + "ccAliasStateOn": "Activé", + "ccAliasStateOff": "Désactivé", + "ccAliasAddModelPlaceholder": "ID du modèle (par ex. gpt-4o)", + "ccAliasAddModelButton": "Ajouter une surcharge", + "ccAliasLoadError": "Échec du chargement des paramètres d'alias de découverte : {error}", + "ccAliasSaveError": "Échec de l'enregistrement du paramètre d'alias de découverte : {error}", "compatUpstreamHeadersLabel": "Extra upstream headers", "compatUpstreamHeadersHint": "High-privilege setting — same trust level as editing provider API credentials; only trusted admins should use it. Merged after OmniRoute adds auth from the provider API key. If a custom header uses the same name as an existing one (e.g. Authorization), your value fully replaces the auto-generated header (including the Bearer token) — the upstream only sees what you typed, not the key from settings. Misconfiguration can cause 401 or broken upstream auth. One row per header (e.g. extra Authentication for some gateways). Hover or focus the value to preview. Saves on blur, outside click, or closing this panel.", "compatUpstreamHeaderName": "Header name", @@ -5449,8 +5451,8 @@ "t3ChatWebCookieHint": "Ouvrez t3.chat → DevTools → Application → Stockage local → https://t3.chat, copiez 'convex-session-id'. Ensuite, ouvrez DevTools → Réseau, copiez l'en-tête complet du cookie de toute demande de chat. Collez les deux valeurs dans les champs ci-dessous.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", - "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", + "blockClaudeExtraUsageDescription": "Lorsqu'elle est activée, OmniRoute marque cette connexion Claude comme indisponible dès que l'API d'utilisation signale une consommation supplémentaire en attente. Le mécanisme de secours bascule alors vers une autre connexion au lieu de poursuivre avec une facturation supplémentaire à l'usage.", + "blockClaudeExtraUsageLabel": "Bloquer l'utilisation supplémentaire de Claude", "disableCoolingDescription": "Ignorer le délai de récupération temporaire pour que cette connexion reste éligible même après des erreurs récupérables (les états terminaux comme banni/expiré s'appliquent toujours).", "disableCoolingLabel": "Désactiver le délai de récupération pour cette connexion", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5637,13 +5639,13 @@ "importGrokAuth": "Importer l'authentification Grok Build", "zedImportTitle": "Importer depuis le trousseau Zed", "zedImportDescription": "Détectez les identifiants de fournisseurs d'IA (OpenAI, Anthropic, Google, Mistral, xAI) stockés par Zed IDE dans le trousseau d'accès du système d'exploitation et importez-les en tant que connexions. Zed IDE doit être installé sur cette machine.", - "zedImportButton": "__MISSING__:Import from Zed", - "zedImportFailed": "__MISSING__:Zed import failed", + "zedImportButton": "Importer depuis Zed", + "zedImportFailed": "Échec de l'importation depuis Zed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", - "zedImporting": "__MISSING__:Importing…", + "zedImportSuccess": "{credentials} identifiant(s) importé(s) depuis Zed pour {providers} fournisseur(s)", + "zedImporting": "Importation…", "zedNoCredentials": "Aucun identifiant Zed trouvé dans le trousseau d'accès", "zedUnsupportedCredentials": "Trouvé {count} identifiant(s) dans le trousseau d'accès, mais aucun ne correspond aux fournisseurs pris en charge", "zedManualTitle": "Importation manuelle de jeton", @@ -5790,7 +5792,7 @@ "bailian-coding-plan": "Connectez Alibaba Coding Plan avec une clé API.", "bedrock": "Intégration native Bedrock : la découverte de modèles utilise les modèles de fondation et les profils d'inférence Bedrock, tandis que le chat utilise les API régionales Bedrock Runtime Converse/ConverseStream.", "anthropic": "Connectez Anthropic avec une clé API.", - "ant-ling": "__MISSING__:Register and create an API key at the Ant Ling API console (https://chat.ant-ling.com/open), then paste it here. OmniRoute routes chat traffic to https://api.ant-ling.com/v1/chat/completions; the provider is OpenAI-compatible and also exposes an Anthropic-compatible surface.", + "ant-ling": "Inscrivez-vous et créez une clé API dans la console API d'Ant Ling (https://chat.ant-ling.com/open), puis collez-la ici. OmniRoute achemine le trafic de chat vers https://api.ant-ling.com/v1/chat/completions ; le fournisseur est compatible avec OpenAI et expose également une interface compatible avec Anthropic.", "api-airforce": "Obtenez votre clé API sur https://panel.api.airforce — point de terminaison compatible OpenAI sur https://api.airforce/v1", "arcee-ai": "Obtenez une clé API sur arcee.ai", "azure-ai": "Foundry utilise la surface OpenAI v1 avec les noms de déploiement comme modèles. OmniRoute normalise les URL des ressources racines vers les points de terminaison v1 chat et /models.", @@ -5811,7 +5813,7 @@ "chutes": "Clé API Bearer pour la passerelle compatible OpenAI de Chutes.", "clarifai": "Clarifai expose un chat, des réponses et /models compatibles avec OpenAI sur /v2/ext/openai/v1. Les modèles publics/communautaires nécessitent généralement un PAT ; les clés limitées à l'application ne fonctionnent que pour les ressources au sein de cette application.", "cloudflare-ai": "Nécessite un jeton API ET un ID de compte (disponible sur dash.cloudflare.com)", - "clova-studio": "__MISSING__:CLOVA Studio (HyperCLOVA X) is OpenAI-compatible on /v1/openai. OmniRoute probes /v1/openai/models and routes chat traffic to /v1/openai/chat/completions. Uses the current clovastudio.stream.ntruss.com host — the legacy clovastudio.apigw.ntruss.com endpoint is being deprecated.", + "clova-studio": "CLOVA Studio (HyperCLOVA X) est compatible avec OpenAI sur /v1/openai. OmniRoute interroge /v1/openai/models et achemine le trafic de chat vers /v1/openai/chat/completions. Il utilise l'hôte actuel clovastudio.stream.ntruss.com ; l'ancien point de terminaison clovastudio.apigw.ntruss.com est en cours d'abandon.", "codestral": "Connectez Codestral avec une clé API.", "cohere": "Essai gratuit : 1 000 appels API/mois pour les tests, aucune carte de crédit requise", "command-code": "Créez ou copiez une clé API depuis Command Code, puis collez-la ici en tant que jeton Bearer.", @@ -5856,9 +5858,9 @@ "watsonx": "La passerelle de modèles watsonx expose des points de terminaison /chat/completions et /models compatibles OpenAI sous /ml/gateway/v1.", "ideogram": "Obtenir une clé API sur ideogram.ai/docs/api", "iflytek": "Obtenir une clé API sur console.xfyun.cn", - "inception": "__MISSING__:Inception Labs is OpenAI-compatible at https://api.inceptionlabs.ai/v1. mercury-2 is the first diffusion LLM (dLLM) in the catalog — 5-10x faster generation than comparable autoregressive models, with tool calling, json_mode, and structured outputs.", + "inception": "Inception Labs est compatible avec OpenAI à l'adresse https://api.inceptionlabs.ai/v1. mercury-2 est le premier LLM à diffusion (dLLM) du catalogue : sa génération est 5 à 10 fois plus rapide que celle de modèles autorégressifs comparables, avec prise en charge des appels d'outils, de json_mode et des sorties structurées.", "inference-net": "25 $ de crédits gratuits à l'inscription, plus des subventions de recherche disponibles", - "internlm": "__MISSING__:Free monthly quota ~1M input / 3M output tokens (~10 RPM)", + "internlm": "Quota mensuel gratuit : environ 1 M de tokens en entrée / 3 M en sortie (environ 10 RPM)", "jina-ai": "Clé API Bearer pour l'API de reranking Jina AI.", "jina-reader": "Connecter Jina Reader avec une clé API.", "kenari": "Kenari expose un point de terminaison de complétion de chat compatible OpenAI sur https://kenari.id/v1/chat/completions, ainsi qu'un catalogue /v1/models en direct couvrant Claude, GPT, DeepSeek, GLM, Kimi et plus encore. OmniRoute utilise le protocole OpenAI et liste les modèles via passthrough.", @@ -5905,7 +5907,7 @@ "perplexity": "Connecter Perplexity avec une clé API.", "piapi": "Connecter PiAPI avec une clé API.", "pioneer": "75 $ de crédits d'utilisation gratuits — aucune carte de crédit requise", - "plamo": "__MISSING__:PLaMo is OpenAI-compatible at https://api.platform.preferredai.jp/v1. Built by Preferred Networks and optimized for Japanese. Docs are primarily in Japanese.", + "plamo": "PLaMo est compatible avec OpenAI à l'adresse https://api.platform.preferredai.jp/v1. Développé par Preferred Networks, il est optimisé pour le japonais. La documentation est principalement en japonais.", "poe": "Poe expose un chat et des réponses compatibles avec OpenAI sur https://api.poe.com/v1, avec des vérifications de solde authentifiées sur /usage/current_balance.", "pollinations": "Niveau gratuit sans clé : openai, openai-fast, openai-large, qwen-coder, mistral, deepseek, grok, gemini-flash-lite-3.1, perplexity-fast, perplexity-reasoning. Les modèles Premium (claude, gemini, midijourney) nécessitent une clé API Pollinations provenant de enter.pollinations.ai.", "publicai": "Nécessite une clé API — crédit d'inscription unique, puis payant", @@ -5917,7 +5919,7 @@ "runwayml": "La génération de vidéos Runway est basée sur des tâches. OmniRoute soumet des tâches text-to-video ou image-to-video, interroge /v1/tasks/[id] et normalise les sorties vidéo terminées dans la réponse de type OpenAI /v1/videos/generations.", "sambanova": "5 $ de crédits gratuits à l'inscription (validité de 30 jours), aucune carte de crédit requise", "sap": "La découverte de modèles utilise /v2/lm/scenarios/foundation-models/models sur AI_API_URL. Les requêtes de chat utilisent deploymentUrl/chat/completions et nécessitent AI-Resource-Group.", - "sarvam": "__MISSING__:Sarvam AI is OpenAI-compatible on /v1. OmniRoute probes /v1/models and routes chat traffic to /v1/chat/completions. Models are tuned for Indic languages.", + "sarvam": "Sarvam AI est compatible avec OpenAI sur /v1. OmniRoute interroge /v1/models et achemine le trafic de chat vers /v1/chat/completions. Les modèles sont optimisés pour les langues indiennes.", "scaleway": "1M de tokens gratuits pour les nouveaux comptes — conforme UE/RGPD (Paris), Qwen3 235B & Llama 70B", "sensenova": "Obtenez la clé API sur platform.sensenova.cn", "siliconflow": "1 $ de crédits gratuits plus des modèles gratuits en permanence après vérification de l'identité", @@ -5934,7 +5936,7 @@ "together": "Connecter Together AI avec une clé API.", "tokenrouter": "TokenRouter expose un point de terminaison de complétion de chat compatible avec OpenAI à l'adresse https://api.tokenrouter.com/v1/chat/completions, ainsi qu'un catalogue /v1/models fonctionnel. OmniRoute utilise le protocole OpenAI.", "topaz": "Connecter Topaz avec une clé API.", - "typhoon": "__MISSING__:Typhoon is OpenAI-compatible on /v1. Built by SCB 10X (Thailand); typhoon-v2.5-30b-a3b-instruct is a thai-first, multilingual model.", + "typhoon": "Typhoon est compatible avec OpenAI sur /v1. Développé par SCB 10X (Thaïlande), typhoon-v2.5-30b-a3b-instruct est un modèle multilingue conçu en priorité pour le thaï.", "udio": "Coller le cookie de session depuis udio.com (authentification Supabase)", "uncloseai": "Aucune authentification requise. L'API accepte n'importe quelle chaîne non vide comme clé d'identification.", "upstage": "Connecter Upstage avec une clé API.", @@ -5947,7 +5949,7 @@ "voyage-ai": "Clé API Bearer pour les API d'embeddings et de rerank de Voyage AI.", "wafer": "Clé API depuis https://wafer.ai", "wandb": "Connecter Weights & Biases Inference avec une clé API.", - "writer": "__MISSING__:Writer Palmyra is OpenAI-compatible at https://api.writer.com/v1. palmyra-x5 offers a 1M-token context window.", + "writer": "Writer Palmyra est compatible avec OpenAI à l'adresse https://api.writer.com/v1. palmyra-x5 offre une fenêtre de contexte de 1 M de tokens.", "x5lab": "X5Lab expose un point de terminaison de complétion de chat compatible OpenAI à l'adresse https://api.x5lab.dev/v1/chat/completions, ainsi qu'un catalogue /v1/models en direct. OmniRoute utilise le protocole OpenAI et liste les modèles via passthrough.", "xai": "Connecter xAI (Grok) avec une clé API.", "xiaomi-mimo": "Connecter Xiaomi MiMo avec une clé API.", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) est l'ami open source fondateur d'OmniRoute", "cheaperInferenceSupporterBadge": "Ami open source", "cheaperInferenceSupporterTooltip": "Cheaper Inference soutient OmniRoute en tant qu'ami open source", - "kimiPartnerLinkNote": "Lien partenaire — soutient OmniRoute sans frais supplémentaires pour vous" + "kimiPartnerLinkNote": "Lien partenaire — soutient OmniRoute sans frais supplémentaires pour vous", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Paramètres", @@ -6125,18 +6132,18 @@ "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", "requestBodyLimitCurrent": "Current: {value}", - "cacheConfigLoadFailed": "__MISSING__:Failed to load cache settings", - "cacheConfigSaveSuccess": "__MISSING__:Cache settings saved", - "cacheConfigSaveFailed": "__MISSING__:Failed to save cache settings", - "modelCatalogTtlWholeNumberError": "__MISSING__:Use a whole number", - "modelCatalogTtlMinimumError": "__MISSING__:Minimum is {min} ms", - "modelCatalogTtlMaximumError": "__MISSING__:Maximum is {max} ms", - "modelCatalogCacheTtl": "__MISSING__:Model Catalog Cache TTL", - "modelCatalogCacheTtlDescription": "__MISSING__:How long model catalog responses are cached before refreshing", - "modelCatalogCacheTtlLabel": "__MISSING__:Model catalog cache TTL in milliseconds", - "modelCatalogCacheTtlSaving": "__MISSING__:Saving...", - "modelCatalogCacheTtlSave": "__MISSING__:Save", - "modelCatalogCacheTtlCurrent": "__MISSING__:Current: {value} ms", + "cacheConfigLoadFailed": "Échec du chargement des paramètres du cache", + "cacheConfigSaveSuccess": "Paramètres du cache enregistrés", + "cacheConfigSaveFailed": "Échec de l'enregistrement des paramètres du cache", + "modelCatalogTtlWholeNumberError": "Utilisez un nombre entier", + "modelCatalogTtlMinimumError": "Le minimum est de {min} ms", + "modelCatalogTtlMaximumError": "Le maximum est de {max} ms", + "modelCatalogCacheTtl": "TTL du cache du catalogue de modèles", + "modelCatalogCacheTtlDescription": "Durée de mise en cache des réponses du catalogue de modèles avant actualisation", + "modelCatalogCacheTtlLabel": "TTL du cache du catalogue de modèles en millisecondes", + "modelCatalogCacheTtlSaving": "Enregistrement...", + "modelCatalogCacheTtlSave": "Enregistrer", + "modelCatalogCacheTtlCurrent": "Valeur actuelle : {value} ms", "mitmProxy": "Proxy MITM", "pricing": "Tarifs", "storage": "Stockage", @@ -6790,7 +6797,7 @@ "howPricingWorks": "Comment fonctionne la tarification", "cacheWrite": "Écriture du cache", "unsaved": "non enregistré", - "resetDefaults": "__MISSING__:Reset defaults", + "resetDefaults": "Rétablir les valeurs par défaut", "saveProvider": "Enregistrer le fournisseur", "model": "Modèle", "models": "modèles", @@ -6970,13 +6977,13 @@ "compressionPreserveSystemNever": "Jamais", "compressionLiveZoneTitle": "Zone active alignée sur le cache", "compressionLiveZoneDesc": "Maintenir stable le préfixe de conversation compressé et traiter uniquement les nouveaux éléments ajoutés.", - "compressionExclusionsTitle": "__MISSING__:Compression Exclusions", - "compressionExclusionsDesc": "__MISSING__:Model ids or provider/model patterns that must never be compressed. `*` is the only wildcard (e.g. `openai/*`, `*embedding*`). A matching request passes through byte-identical — no compression engine runs.", - "compressionExclusionsPlaceholder": "__MISSING__:One pattern per line, e.g.\nopenai/text-embedding-3-large\nanthropic/*", - "compressionExclusionsSave": "__MISSING__:Save", - "compressionExclusionsSaved": "__MISSING__:Saved", - "compressionExclusionsCount": "__MISSING__:{count, plural, one {# exclusion} other {# exclusions}} configured", - "compressionExclusionsEmpty": "__MISSING__:No exclusions configured — every model/endpoint is eligible for compression (default behavior).", + "compressionExclusionsTitle": "Exclusions de la compression", + "compressionExclusionsDesc": "Identifiants de modèles ou motifs fournisseur/modèle qui ne doivent jamais être compressés. `*` est le seul caractère générique (par ex. `openai/*`, `*embedding*`). Une requête correspondante est transmise à l'identique, octet pour octet : aucun moteur de compression ne s'exécute.", + "compressionExclusionsPlaceholder": "Un motif par ligne, par ex.\nopenai/text-embedding-3-large\nanthropic/*", + "compressionExclusionsSave": "Enregistrer", + "compressionExclusionsSaved": "Enregistré", + "compressionExclusionsCount": "{count, plural, one {# exclusion configurée} other {# exclusions configurées}}", + "compressionExclusionsEmpty": "Aucune exclusion configurée : chaque modèle ou point de terminaison peut être compressé (comportement par défaut).", "compressionCavemanConfig": "Caveman Engine Configuration", "compressionCavemanConfigDesc": "Fine-tune the rule-based compression engine", "compressionCavemanPanelHint": "Son activation/désactivation et son niveau sont définis dans le panneau :", @@ -7812,10 +7819,6 @@ "label": "Lignes minimales à compacter", "description": "Nombre minimum de lignes dans un tableau JSON homogène requis pour déclencher le compactage tabulaire. Par défaut : 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Préserver le prompt système" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Longueur minimale du message" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -9775,23 +9782,23 @@ "deviceCodeVerificationUrl": "URL de vérification", "deviceCodeYourCode": "Votre code", "deviceCodeWaiting": "En attente d'autorisation...", - "googleLoopbackTitle": "__MISSING__:Google sign-in can't complete from this address", - "googleLoopbackWhatHappens": "__MISSING__:Google only releases the authorization code once {redirectUri} is reachable from the browser that approves the sign-in. Here that address points at this computer, not at the OmniRoute server — so the consent screen hangs instead of redirecting, and there is no callback URL to copy.", - "googleLoopbackRecommended": "__MISSING__:Recommended — run this on your own computer, then paste the result below:", - "googleLoopbackHelperNote": "__MISSING__:It opens the Google consent locally (where 127.0.0.1 works) and prints a one-line omniroute-cred-v1.… blob. Paste that blob into the Step 2 field below — it accepts a credential blob as well as a callback URL.", - "googleLoopbackTunnelLabel": "__MISSING__:Or forward the dashboard port over SSH and reload OmniRoute through the tunnel:", - "googleLoopbackTunnelNote": "__MISSING__:Replace {userPlaceholder} with your SSH username, keep the terminal open, then open {localUrl} and connect again from there.", - "googleLoopbackHeadlessAlt": "__MISSING__:For fully headless use with no local callback at all, configure your own Google OAuth credentials plus a public base URL.", + "googleLoopbackTitle": "La connexion Google ne peut pas aboutir depuis cette adresse", + "googleLoopbackWhatHappens": "Google ne transmet le code d'autorisation que lorsque {redirectUri} est accessible depuis le navigateur qui approuve la connexion. Ici, cette adresse désigne cet ordinateur et non le serveur OmniRoute : l'écran de consentement reste donc bloqué au lieu d'effectuer la redirection, et aucune URL de rappel ne peut être copiée.", + "googleLoopbackRecommended": "Recommandé : exécutez cette commande sur votre propre ordinateur, puis collez le résultat ci-dessous :", + "googleLoopbackHelperNote": "La commande ouvre localement l'écran de consentement Google (où 127.0.0.1 fonctionne) et affiche un blob omniroute-cred-v1.… sur une seule ligne. Collez ce blob dans le champ de l'étape 2 ci-dessous ; celui-ci accepte aussi bien un blob d'identifiants qu'une URL de rappel.", + "googleLoopbackTunnelLabel": "Vous pouvez également transférer le port du tableau de bord via SSH et recharger OmniRoute à travers le tunnel :", + "googleLoopbackTunnelNote": "Remplacez {userPlaceholder} par votre nom d'utilisateur SSH, gardez le terminal ouvert, puis ouvrez {localUrl} et reconnectez-vous depuis cette adresse.", + "googleLoopbackHeadlessAlt": "Pour une utilisation entièrement sans interface graphique ni rappel local, configurez vos propres identifiants Google OAuth ainsi qu'une URL de base publique.", "remoteAccessInfo": "Accès à distance : puisque vous accédez à OmniRoute à distance, après autorisation, vous verrez une page d'erreur (localhost introuvable). C'est normal : copiez simplement l'URL complète depuis la barre d'adresse de votre navigateur et collez-la ci-dessous.", - "loopbackMismatchTitle": "__MISSING__:Sign-in can't complete from this address", - "loopbackMismatchWhatHappened": "__MISSING__:What's happening", - "loopbackMismatchExplanation": "__MISSING__:After you approve the login, {providerName} always sends the browser back to {redirectUri}. That address points at the computer running this browser, not at the OmniRoute server — so the authorization code never reaches OmniRoute and the provider fails the sign-in without showing an error.", - "loopbackMismatchHowToFix": "__MISSING__:How to fix it", - "loopbackMismatchStep1": "__MISSING__:On this computer, open a terminal and start an SSH tunnel to the OmniRoute server:", - "loopbackMismatchStep1Note": "__MISSING__:Replace {userPlaceholder} with your SSH username. Keep this terminal open until the connection shows as active — both ports are needed: one serves the dashboard, the other receives the callback.", - "loopbackMismatchStep2": "__MISSING__:In this browser, reopen OmniRoute through the tunnel:", - "loopbackMismatchStep3": "__MISSING__:Then connect {providerName} again from the new tab. The callback now reaches the server and the login completes normally.", - "loopbackMismatchAlternative": "__MISSING__:No SSH access? If this provider offers a token import tab, connect with a token instead — that path doesn't use a loopback callback.", + "loopbackMismatchTitle": "La connexion ne peut pas aboutir depuis cette adresse", + "loopbackMismatchWhatHappened": "Ce qui se passe", + "loopbackMismatchExplanation": "Après l'approbation de la connexion, {providerName} renvoie toujours le navigateur vers {redirectUri}. Cette adresse désigne l'ordinateur qui exécute ce navigateur et non le serveur OmniRoute : le code d'autorisation ne parvient donc jamais à OmniRoute et la connexion au fournisseur échoue sans afficher d'erreur.", + "loopbackMismatchHowToFix": "Comment résoudre le problème", + "loopbackMismatchStep1": "Sur cet ordinateur, ouvrez un terminal et démarrez un tunnel SSH vers le serveur OmniRoute :", + "loopbackMismatchStep1Note": "Remplacez {userPlaceholder} par votre nom d'utilisateur SSH. Gardez ce terminal ouvert jusqu'à ce que la connexion soit indiquée comme active ; les deux ports sont nécessaires : l'un sert le tableau de bord et l'autre reçoit le rappel.", + "loopbackMismatchStep2": "Dans ce navigateur, rouvrez OmniRoute à travers le tunnel :", + "loopbackMismatchStep3": "Reconnectez ensuite {providerName} depuis le nouvel onglet. Le rappel atteint désormais le serveur et la connexion aboutit normalement.", + "loopbackMismatchAlternative": "Vous n'avez pas d'accès SSH ? Si ce fournisseur propose un onglet d'importation de jeton, connectez-vous plutôt avec un jeton ; cette méthode n'utilise pas de rappel local.", "step1OpenUrl": "Étape 1 : ouvrez cette URL dans votre navigateur", "copy": "Copier", "step2PasteCallback": "Étape 2 : Collez l'URL de rappel ou le code d'autorisation ici", @@ -10195,6 +10202,8 @@ "copied": "Copié !", "run": "Exécuter", "running": "Exécution en cours...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Réponse", "tunnel": "Tunnel", "send": "Envoyer", @@ -11737,7 +11746,7 @@ "danger": "Danger", "requiresRestart": "Nécessite un redémarrage", "source": "Source", - "ccDiscoveryAliasesEnvWarning": "__MISSING__:Active via environment variable (EXPOSE_CC_DISCOVERY_ALIASES) — this overrides any dashboard toggle below.", + "ccDiscoveryAliasesEnvWarning": "Actif via la variable d'environnement EXPOSE_CC_DISCOVERY_ALIASES : cette valeur remplace tout réglage du tableau de bord ci-dessous.", "resetFlag": "Réinitialiser {label} à la valeur par défaut", "reset": "Réinitialiser", "loadFailed": "Échec du chargement des indicateurs de fonctionnalité", diff --git a/src/i18n/messages/gu.json b/src/i18n/messages/gu.json index 1035db923d..fdd7362abf 100644 --- a/src/i18n/messages/gu.json +++ b/src/i18n/messages/gu.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "No new models were added (all already exist).", "importDoneCount": "✓ Done! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "An unexpected error occurred", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "messages", "responsesPath": "responses", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) એ OmniRoute નો સ્થાપક ઓપન સોર્સ મિત્ર છે", "cheaperInferenceSupporterBadge": "ઓપન સોર્સ મિત્ર", "cheaperInferenceSupporterTooltip": "Cheaper Inference ઓપન સોર્સ મિત્ર તરીકે OmniRoute ને સમર્થન આપે છે", - "kimiPartnerLinkNote": "પાર્ટનર લિંક — તમારા માટે કોઈ વધારાના ખર્ચ વિના OmniRoute ને સપોર્ટ કરે છે" + "kimiPartnerLinkNote": "પાર્ટનર લિંક — તમારા માટે કોઈ વધારાના ખર્ચ વિના OmniRoute ને સપોર્ટ કરે છે", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Settings", @@ -7812,10 +7819,6 @@ "label": "કમ્પેક્ટ કરવા માટે ન્યૂનતમ પંક્તિઓ", "description": "ટેબ્યુલર કમ્પેક્શન ટ્રિગર કરવા માટે સજાતીય JSON એરેમાં જરૂરી ન્યૂનતમ પંક્તિઓ. ડિફોલ્ટ: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "સિસ્ટમ પ્રોમ્પ્ટ સાચવો" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "ન્યૂનતમ સંદેશ લંબાઈ" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "કૉપિ કર્યું!", "run": "ચલાવો", "running": "ચાલી રહ્યું છે...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "પ્રતિસાદ", "tunnel": "ટનલ", "send": "મોકલો", diff --git a/src/i18n/messages/he.json b/src/i18n/messages/he.json index 1d8cb4679c..d4a50aa87d 100644 --- a/src/i18n/messages/he.json +++ b/src/i18n/messages/he.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "לא נוספו דגמים חדשים (כולם כבר קיימים).", "importDoneCount": "✓ בוצע! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "אירעה שגיאה בלתי צפויה", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "הודעות", "responsesPath": "תגובות", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) הוא חבר הקוד הפתוח המייסד של OmniRoute", "cheaperInferenceSupporterBadge": "ידיד קוד פתוח", "cheaperInferenceSupporterTooltip": "‏Cheaper Inference תומכת ב-OmniRoute כידידת קוד פתוח", - "kimiPartnerLinkNote": "קישור שותף — תומך ב-OmniRoute ללא עלות נוספת עבורך" + "kimiPartnerLinkNote": "קישור שותף — תומך ב-OmniRoute ללא עלות נוספת עבורך", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "הגדרות", @@ -7812,10 +7819,6 @@ "label": "מינימום שורות לכיווץ", "description": "מספר השורות המינימלי במערך JSON הומוגני הנדרש להפעלת כיווץ טבלאי. ברירת מחדל: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "שמור על הנחיית המערכת" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "אורך הודעה מינימלי" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "הועתק!", "run": "הפעל", "running": "מריץ...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "תגובה", "tunnel": "מנהרה", "send": "שלח", diff --git a/src/i18n/messages/hi.json b/src/i18n/messages/hi.json index 5c6e92f1ff..f720ed1f73 100644 --- a/src/i18n/messages/hi.json +++ b/src/i18n/messages/hi.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "कोई नया मॉडल नहीं जोड़ा गया (सभी पहले से मौजूद हैं)।", "importDoneCount": "✓ हो गया! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "एक अप्रत्याशित त्रुटि उत्पन्न हुई", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "संदेश", "responsesPath": "प्रतिक्रियाएं", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI), OmniRoute का संस्थापक ओपन सोर्स मित्र है", "cheaperInferenceSupporterBadge": "ओपन सोर्स मित्र", "cheaperInferenceSupporterTooltip": "Cheaper Inference एक ओपन सोर्स मित्र के रूप में OmniRoute का समर्थन करता है", - "kimiPartnerLinkNote": "पार्टनर लिंक — बिना किसी अतिरिक्त लागत के OmniRoute का समर्थन करता है" + "kimiPartnerLinkNote": "पार्टनर लिंक — बिना किसी अतिरिक्त लागत के OmniRoute का समर्थन करता है", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "सेटिंग्स", @@ -7812,10 +7819,6 @@ "label": "कॉम्पैक्ट करने के लिए न्यूनतम पंक्तियाँ", "description": "सारणीबद्ध कॉम्पैक्शन को ट्रिगर करने के लिए सजातीय JSON ऐरे में आवश्यक न्यूनतम पंक्तियाँ। डिफ़ॉल्ट: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "सिस्टम प्रॉम्प्ट सुरक्षित रखें" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "न्यूनतम संदेश लंबाई" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "कॉपी किया गया!", "run": "चलाएं", "running": "चल रहा है...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "रिस्पॉन्स", "tunnel": "टनल", "send": "भेजें", diff --git a/src/i18n/messages/hu.json b/src/i18n/messages/hu.json index e86fc50a90..a00d583432 100644 --- a/src/i18n/messages/hu.json +++ b/src/i18n/messages/hu.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Nem adtak hozzá új modelleket (már mindegyik létezik).", "importDoneCount": "✓ Kész! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Váratlan hiba történt", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "üzeneteket", "responsesPath": "válaszokat", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "A Kimi (Moonshot AI) az OmniRoute alapító nyílt forráskódú barátja", "cheaperInferenceSupporterBadge": "Nyílt forráskódú barát", "cheaperInferenceSupporterTooltip": "A Cheaper Inference nyílt forráskódú barátként támogatja az OmniRoute-ot", - "kimiPartnerLinkNote": "Partnerhivatkozás — az Ön számára további költség nélkül támogatja az OmniRoute-ot" + "kimiPartnerLinkNote": "Partnerhivatkozás — az Ön számára további költség nélkül támogatja az OmniRoute-ot", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Beállítások elemre", @@ -7812,10 +7819,6 @@ "label": "Tömörítendő sorok minimális száma", "description": "Egy homogén JSON-tömb minimális sorszáma a táblázatos tömörítés indításához. Alapértelmezett: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Rendszerüzenet megőrzése" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Minimális üzenethossz" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Másolva!", "run": "Futtatás", "running": "Futtatás...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Válasz", "tunnel": "Alagút", "send": "Küldés", diff --git a/src/i18n/messages/id.json b/src/i18n/messages/id.json index 570e308419..823f0c51a0 100644 --- a/src/i18n/messages/id.json +++ b/src/i18n/messages/id.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Tidak ada model baru yang ditambahkan (semua sudah ada).", "importDoneCount": "✓ Selesai! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Terjadi kesalahan yang tidak terduga", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "pesan", "responsesPath": "tanggapan", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) adalah sahabat open source pendiri OmniRoute", "cheaperInferenceSupporterBadge": "Teman Open Source", "cheaperInferenceSupporterTooltip": "Cheaper Inference mendukung OmniRoute sebagai Teman Open Source", - "kimiPartnerLinkNote": "Tautan mitra — mendukung OmniRoute tanpa biaya tambahan bagi Anda" + "kimiPartnerLinkNote": "Tautan mitra — mendukung OmniRoute tanpa biaya tambahan bagi Anda", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Pengaturan", @@ -7812,10 +7819,6 @@ "label": "Baris minimum untuk dipadatkan", "description": "Jumlah baris minimum dalam array JSON homogen yang diperlukan untuk memicu pemadatan tabular. Default: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Pertahankan prompt sistem" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Panjang pesan minimum" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Disalin!", "run": "Jalankan", "running": "Menjalankan...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Respons", "tunnel": "Tunnel", "send": "Kirim", diff --git a/src/i18n/messages/in.json b/src/i18n/messages/in.json index 78f5e27275..1b39dda04e 100644 --- a/src/i18n/messages/in.json +++ b/src/i18n/messages/in.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "No new models were added (all already exist).", "importDoneCount": "✓ Done! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "An unexpected error occurred", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "messages", "responsesPath": "responses", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) adalah sahabat open source pendiri OmniRoute", "cheaperInferenceSupporterBadge": "Teman Open Source", "cheaperInferenceSupporterTooltip": "Cheaper Inference mendukung OmniRoute sebagai Teman Open Source", - "kimiPartnerLinkNote": "Tautan mitra — mendukung OmniRoute tanpa biaya tambahan bagi Anda" + "kimiPartnerLinkNote": "Tautan mitra — mendukung OmniRoute tanpa biaya tambahan bagi Anda", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Settings", @@ -7812,10 +7819,6 @@ "label": "Baris minimum untuk dipadatkan", "description": "Jumlah baris minimum dalam larik JSON homogen yang diperlukan untuk memicu pemadatan tabular. Default: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Pertahankan prompt sistem" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Panjang pesan minimum" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Tersalin!", "run": "Jalankan", "running": "Menjalankan...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Respons", "tunnel": "Tunnel", "send": "Kirim", diff --git a/src/i18n/messages/it.json b/src/i18n/messages/it.json index d6d556eb2a..6802980f58 100644 --- a/src/i18n/messages/it.json +++ b/src/i18n/messages/it.json @@ -937,7 +937,7 @@ "disabled": "Disabilitato", "featureFlagOmnirouteEmergencyFallbackDescription": "Indirizza le richieste con budget esaurito al provider/modello di fallback gratuito di emergenza.", "featureFlagArenaEloSyncEnabledDescription": "Abilita la sincronizzazione periodica dell'ELO della classifica Arena AI per le graduatorie di intelligenza dei modelli.", - "featureFlagExposeCcDiscoveryAliasesDescription": "__MISSING__: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.", + "featureFlagExposeCcDiscoveryAliasesDescription": "Mostra gli id specchio claude// su /v1/models in modo che la scoperta dei modelli gateway di Claude Code elenchi i modelli non-Claude. Attenzione: raddoppia le voci nel catalogo per tutti i client quando abilitato globalmente.", "sidebar": { "home": "Casa", "dashboard": "Pannello di controllo", @@ -1055,7 +1055,7 @@ "combosLive": "Combo Studio", "combosLiveSubtitle": "Cascata di routing in tempo reale", "compressionStudio": "Compression Studio", - "compressionExclusions": "__MISSING__:Exclusions", + "compressionExclusions": "Esclusioni", "contextSettingsSubtitle": "Impostazioni predefinite globali", "contextHeadroomSubtitle": "Compattazione tabellare", "contextSessionDedupSubtitle": "Deduplicazione cross-turn", @@ -1066,7 +1066,7 @@ "contextUltraSubtitle": "Potatura euristica", "contextOmniglyphSubtitle": "Contesto come immagini", "compressionStudioSubtitle": "Cascata del motore in tempo reale", - "compressionExclusionsSubtitle": "__MISSING__:Per-model/endpoint bypass", + "compressionExclusionsSubtitle": "Bypass per-modello/endpoint", "chaosConfigSubtitle": "Esecuzione parallela multi-modello", "routingSection": "Routing", "protocolsSection": "Protocols", @@ -1109,7 +1109,7 @@ "settingsSecurity": "Security", "settingsAccessTokens": "Token di accesso", "settingsFeatureFlags": "Flag di funzionalità", - "settingsCache": "__MISSING__:Cache", + "settingsCache": "Cache", "settingsAuthz": "Authz", "settingsRouting": "Routing", "settingsResilience": "Resilience", @@ -1121,7 +1121,7 @@ "runtime": "Runtime", "consoleLogs": "Console Logs", "logsTimeline": "Timeline", - "logsTimelineSubtitle": "__MISSING__:Visual request timeline", + "logsTimelineSubtitle": "Timeline visiva delle richieste", "globalRouting": "Global Routing", "mitmProxy": "MITM Proxy", "oneProxy": "1Proxy", @@ -1196,7 +1196,7 @@ "settingsSecuritySubtitle": "Auth and encryption", "settingsAccessTokensSubtitle": "Token CLI con ambito per la modalità remota", "settingsFeatureFlagsSubtitle": "Attiva/disattiva le funzionalità del sistema", - "settingsCacheSubtitle": "__MISSING__:Model catalog and response caching", + "settingsCacheSubtitle": "Catalogo modelli e caching delle risposte", "settingsSidebar": "Sidebar", "settingsSidebarSubtitle": "Customize sidebar layout", "settingsAuthzSubtitle": "Inventario delle route e criteri di bypass", @@ -1561,7 +1561,7 @@ "settingsGeneralDescription": "Storage, database, and general instance configuration", "settingsAppearanceDescription": "Theme, branding, and visual customization", "settingsAiDescription": "AI behaviors, thinking budgets, vision, and memory settings", - "settingsCacheDescription": "__MISSING__:TTL for model catalog cache entries", + "settingsCacheDescription": "TTL per le voci di cache del catalogo modelli", "settingsSecurityDescription": "Authentication, authorization, and access control settings", "featureFlags": "Flag di funzionalità", "featureFlagsDescription": "Capacità del sistema di controllo e caratteristiche sperimentali", @@ -2515,14 +2515,14 @@ "auto": "Auto", "always": "Sempre" }, - "ccDiscoveryInfoButton": "__MISSING__:How to enable discovery in Claude Code", - "ccDiscoveryInfoTooltip": "__MISSING__:Advertise non-Claude models under claude/<provider>/<model> mirror ids so Claude Code's gateway model discovery can list them. Doubles catalog entries for all clients when enabled globally.", - "ccDiscoveryInfoLink": "__MISSING__:Open Feature Flags", - "ccOnboardingTitle": "__MISSING__:settings.json for gateway model discovery", - "ccOnboardingCopy": "__MISSING__:Copy", - "ccOnboardingCopied": "__MISSING__:Copied", - "ccOnboardingKeyPlaceholder": "__MISSING__:", - "ccOnboardingWindowNote": "__MISSING__:Claude Code assumes a 200K context window for any model id it does not recognize. For a model with a different real window, add CLAUDE_CODE_AUTO_COMPACT_WINDOW just under it so auto-compaction does not fire too early.", + "ccDiscoveryInfoButton": "Come abilitare la scoperta in Claude Code", + "ccDiscoveryInfoTooltip": "Mostra i modelli non-Claude sotto gli id specchio claude// così la scoperta modelli gateway di Claude Code può elencarli. Raddoppia le voci nel catalogo per tutti i client quando abilitato globalmente.", + "ccDiscoveryInfoLink": "Apri le Flag Funzionalità", + "ccOnboardingTitle": "settings.json per la scoperta modelli gateway", + "ccOnboardingCopy": "Copia", + "ccOnboardingCopied": "Copiato", + "ccOnboardingKeyPlaceholder": "", + "ccOnboardingWindowNote": "Claude Code assume una finestra di contesto di 200K per qualsiasi id modello non riconosciuto. Per un modello con una finestra reale diversa, aggiungi CLAUDE_CODE_AUTO_COMPACT_WINDOW subito sotto in modo che l'auto-compattazione non si attivi troppo presto.", "failedSave": "Impossibile salvare", "profileSyncTitle": "Sincronizzazione automatica profili CLI", "profileSyncDescription": "Dopo la sincronizzazione dei modelli del provider, rigenera automaticamente i profili degli strumenti CLI dal catalogo live. Disattivato per impostazione predefinita — vengono scritti solo i file di profilo; la configurazione attiva/predefinita non viene mai modificata.", @@ -3730,7 +3730,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "__MISSING__:APIs", + "tabApis": "API", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Non sono stati aggiunti nuovi modelli (esistono già tutti).", "importDoneCount": "✓ Fatto! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Si è verificato un errore imprevisto", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "messaggi", "responsesPath": "risposte", @@ -5203,18 +5205,18 @@ "interceptFetchHint": "Riscrivi le chiamate dello strumento nativo web_fetch verso /v1/web/fetch di OmniRoute.", "interceptionLoadError": "Impossibile caricare le impostazioni di intercettazione: {error}", "interceptionSaveError": "Impossibile salvare le impostazioni di intercettazione: {error}", - "ccAliasSectionTitle": "__MISSING__:Expose in Claude Code (claude/…)", - "ccAliasSectionHint": "__MISSING__:Advertise this provider's models under claude/<provider>/<model> mirror ids so Claude Code's gateway model discovery can list them. Off by default — enabling this doubles catalog entries for all clients.", - "ccAliasProviderLevelLabel": "__MISSING__:Provider default", - "ccAliasModelOverridesLabel": "__MISSING__:Per-model overrides", - "ccAliasModelOverrideAriaLabel": "__MISSING__:Override for {modelId}", - "ccAliasStateInherit": "__MISSING__:Inherit", - "ccAliasStateOn": "__MISSING__:On", - "ccAliasStateOff": "__MISSING__:Off", - "ccAliasAddModelPlaceholder": "__MISSING__:Model id (e.g. gpt-4o)", - "ccAliasAddModelButton": "__MISSING__:Add override", - "ccAliasLoadError": "__MISSING__:Failed to load discovery-alias settings: {error}", - "ccAliasSaveError": "__MISSING__:Failed to save discovery-alias setting: {error}", + "ccAliasSectionTitle": "Esponi in Claude Code (claude/…)", + "ccAliasSectionHint": "Mostra i modelli di questo provider sotto gli id specchio claude// così la scoperta modelli gateway di Claude Code può elencarli. Disattivato per impostazione predefinita — abilitarlo raddoppia le voci nel catalogo per tutti i client.", + "ccAliasProviderLevelLabel": "Impostazione predefinita del provider", + "ccAliasModelOverridesLabel": "Sostituzioni per modello", + "ccAliasModelOverrideAriaLabel": "Sostituzione per {modelId}", + "ccAliasStateInherit": "Eredita", + "ccAliasStateOn": "On", + "ccAliasStateOff": "Off", + "ccAliasAddModelPlaceholder": "Id modello (es. gpt-4o)", + "ccAliasAddModelButton": "Aggiungi sostituzione", + "ccAliasLoadError": "Impossibile caricare le impostazioni discovery-alias: {error}", + "ccAliasSaveError": "Impossibile salvare l'impostazione discovery-alias: {error}", "compatUpstreamHeadersLabel": "Extra upstream headers", "compatUpstreamHeadersHint": "High-privilege setting — same trust level as editing provider API credentials; only trusted admins should use it. Merged after OmniRoute adds auth from the provider API key. If a custom header uses the same name as an existing one (e.g. Authorization), your value fully replaces the auto-generated header (including the Bearer token) — the upstream only sees what you typed, not the key from settings. Misconfiguration can cause 401 or broken upstream auth. One row per header (e.g. extra Authentication for some gateways). Hover or focus the value to preview. Saves on blur, outside click, or closing this panel.", "compatUpstreamHeaderName": "Header name", @@ -5449,8 +5451,8 @@ "t3ChatWebCookieHint": "Apri t3.chat → DevTools → Applicazione → Archiviazione locale → https://t3.chat, copia 'convex-session-id'. Quindi apri DevTools → Rete, copia l'intestazione completa del cookie da qualsiasi richiesta di chat. Incolla entrambi i valori nei campi sottostanti.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", - "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", + "blockClaudeExtraUsageDescription": "Se abilitato, OmniRoute segna questa connessione Claude come non disponibile non appena l'API di utilizzo segnala extra usage in coda, in modo che il fallback passi a un'altra connessione invece di continuare con una fatturazione extra pay-as-you-go.", + "blockClaudeExtraUsageLabel": "Blocca l'extra usage di Claude", "disableCoolingDescription": "Salta il cooldown transitorio in modo che questa connessione rimanga idonea anche dopo errori ripristinabili (gli stati terminali come bannato/scaduto si applicano ancora).", "disableCoolingLabel": "Disabilita il cooldown per questa connessione", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5637,13 +5639,13 @@ "importGrokAuth": "Importa autenticazione Grok Build", "zedImportTitle": "Importa da Zed Keychain", "zedImportDescription": "Trova le credenziali dei provider AI (OpenAI, Anthropic, Google, Mistral, xAI) memorizzate da Zed IDE nel portachiavi del sistema operativo e importale come connessioni. Zed IDE deve essere installato su questa macchina.", - "zedImportButton": "__MISSING__:Import from Zed", - "zedImportFailed": "__MISSING__:Zed import failed", + "zedImportButton": "Importa da Zed", + "zedImportFailed": "Importazione da Zed fallita", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", - "zedImporting": "__MISSING__:Importing…", + "zedImportSuccess": "Importate {credentials} credenziali da Zed per {providers} provider", + "zedImporting": "Importazione in corso…", "zedNoCredentials": "Nessuna credenziale Zed trovata nel portachiavi", "zedUnsupportedCredentials": "Trovate {count} credenziali nel portachiavi, ma nessuna corrisponde ai provider supportati", "zedManualTitle": "Importazione manuale del token", @@ -5790,7 +5792,7 @@ "bailian-coding-plan": "Connetti Alibaba Coding Plan con una chiave API.", "bedrock": "Integrazione nativa di Bedrock: l'individuazione dei modelli utilizza i modelli di base e i profili di inferenza di Bedrock, mentre la chat utilizza le API regionali Bedrock Runtime Converse/ConverseStream.", "anthropic": "Connetti Anthropic con una chiave API.", - "ant-ling": "__MISSING__:Register and create an API key at the Ant Ling API console (https://chat.ant-ling.com/open), then paste it here. OmniRoute routes chat traffic to https://api.ant-ling.com/v1/chat/completions; the provider is OpenAI-compatible and also exposes an Anthropic-compatible surface.", + "ant-ling": "Registrati e crea una chiave API nella console API di Ant Ling (https://chat.ant-ling.com/open), poi incollala qui. OmniRoute instrada il traffico chat verso https://api.ant-ling.com/v1/chat/completions; il provider è compatibile con OpenAI ed espone anche una superficie compatibile con Anthropic.", "api-airforce": "Ottieni la tua chiave API da https://panel.api.airforce — endpoint compatibile con OpenAI su https://api.airforce/v1", "arcee-ai": "Ottieni la chiave API su arcee.ai", "azure-ai": "Foundry utilizza l'interfaccia OpenAI v1 con i nomi di deployment come modelli. OmniRoute normalizza gli URL delle risorse radice agli endpoint chat v1 e /models.", @@ -5811,7 +5813,7 @@ "chutes": "Chiave API Bearer per il gateway compatibile con OpenAI di Chutes.", "clarifai": "Clarifai espone chat, risposte e /models compatibili con OpenAI su /v2/ext/openai/v1. I modelli pubblici/della community richiedono in genere un PAT; le chiavi con ambito app funzionano solo per le risorse all'interno di quell'app.", "cloudflare-ai": "Richiede un token API E un ID account (disponibile su dash.cloudflare.com)", - "clova-studio": "__MISSING__:CLOVA Studio (HyperCLOVA X) is OpenAI-compatible on /v1/openai. OmniRoute probes /v1/openai/models and routes chat traffic to /v1/openai/chat/completions. Uses the current clovastudio.stream.ntruss.com host — the legacy clovastudio.apigw.ntruss.com endpoint is being deprecated.", + "clova-studio": "CLOVA Studio (HyperCLOVA X) è compatibile con OpenAI su /v1/openai. OmniRoute controlla /v1/openai/models e instrada il traffico chat verso /v1/openai/chat/completions. Usa l'attuale host clovastudio.stream.ntruss.com — il vecchio endpoint clovastudio.apigw.ntruss.com è in fase di deprecazione.", "codestral": "Connetti Codestral con una chiave API.", "cohere": "Prova gratuita: 1.000 chiamate API/mese per i test, nessuna carta di credito richiesta", "command-code": "Crea o copia una chiave API da Command Code, quindi incollala qui come token Bearer.", @@ -5856,9 +5858,9 @@ "watsonx": "Il model gateway watsonx espone /chat/completions e /models compatibili con OpenAI sotto /ml/gateway/v1.", "ideogram": "Ottieni la chiave API su ideogram.ai/docs/api", "iflytek": "Ottieni la chiave API su console.xfyun.cn", - "inception": "__MISSING__:Inception Labs is OpenAI-compatible at https://api.inceptionlabs.ai/v1. mercury-2 is the first diffusion LLM (dLLM) in the catalog — 5-10x faster generation than comparable autoregressive models, with tool calling, json_mode, and structured outputs.", + "inception": "Inception Labs è compatibile con OpenAI all'indirizzo https://api.inceptionlabs.ai/v1. mercury-2 è il primo LLM di diffusione (dLLM) nel catalogo — generazione 5-10x più veloce rispetto ai modelli autoregressivi comparabili, con tool calling, json_mode e structured outputs.", "inference-net": "25 $ di crediti gratuiti alla registrazione più borse di ricerca disponibili", - "internlm": "__MISSING__:Free monthly quota ~1M input / 3M output tokens (~10 RPM)", + "internlm": "Quota mensile gratuita ~1M token input / 3M output (~10 RPM)", "jina-ai": "Chiave API Bearer per l'API di rerank di Jina AI.", "jina-reader": "Connetti Jina Reader con una chiave API.", "kenari": "Kenari espone un endpoint di completamento chat compatibile con OpenAI all'indirizzo https://kenari.id/v1/chat/completions, oltre a un catalogo live /v1/models che copre Claude, GPT, DeepSeek, GLM, Kimi e altri. OmniRoute utilizza il protocollo OpenAI ed elenca i modelli tramite passthrough.", @@ -5905,7 +5907,7 @@ "perplexity": "Connetti Perplexity con una chiave API.", "piapi": "Connetti PiAPI con una chiave API.", "pioneer": "$75 di crediti di utilizzo gratuiti — nessuna carta di credito richiesta", - "plamo": "__MISSING__:PLaMo is OpenAI-compatible at https://api.platform.preferredai.jp/v1. Built by Preferred Networks and optimized for Japanese. Docs are primarily in Japanese.", + "plamo": "PLaMo è compatibile con OpenAI all'indirizzo https://api.platform.preferredai.jp/v1. Sviluppato da Preferred Networks e ottimizzato per il giapponese. La documentazione è principalmente in giapponese.", "poe": "Poe espone chat e risposte compatibili con OpenAI su https://api.poe.com/v1, con controlli del saldo autenticati su /usage/current_balance.", "pollinations": "Livello gratuito senza chiave: openai, openai-fast, openai-large, qwen-coder, mistral, deepseek, grok, gemini-flash-lite-3.1, perplexity-fast, perplexity-reasoning. I modelli premium (claude, gemini, midijourney) richiedono una chiave API Pollinations da enter.pollinations.ai.", "publicai": "Richiede una chiave API — credito di registrazione una tantum, poi a pagamento", @@ -5917,7 +5919,7 @@ "runwayml": "La generazione video di Runway è basata su task. OmniRoute invia lavori text-to-video o image-to-video, interroga /v1/tasks/[id] e normalizza gli output video completati nella risposta simile a OpenAI /v1/videos/generations.", "sambanova": "$5 di crediti gratuiti alla registrazione (validità 30 giorni), nessuna carta di credito richiesta", "sap": "La scoperta dei modelli utilizza /v2/lm/scenarios/foundation-models/models su AI_API_URL. Le richieste di chat utilizzano deploymentUrl/chat/completions e richiedono AI-Resource-Group.", - "sarvam": "__MISSING__:Sarvam AI is OpenAI-compatible on /v1. OmniRoute probes /v1/models and routes chat traffic to /v1/chat/completions. Models are tuned for Indic languages.", + "sarvam": "Sarvam AI è compatibile con OpenAI su /v1. OmniRoute controlla /v1/models e instrada il traffico chat verso /v1/chat/completions. I modelli sono ottimizzati per le lingue indiane.", "scaleway": "1M di token gratuiti per i nuovi account — conforme a UE/GDPR (Parigi), Qwen3 235B & Llama 70B", "sensenova": "Ottieni la chiave API su platform.sensenova.cn", "siliconflow": "$1 di crediti gratuiti più modelli permanentemente gratuiti dopo la verifica dell'identità", @@ -5934,7 +5936,7 @@ "together": "Connetti Together AI con una chiave API.", "tokenrouter": "TokenRouter espone un endpoint di completamento chat compatibile con OpenAI all'indirizzo https://api.tokenrouter.com/v1/chat/completions, oltre a un catalogo /v1/models funzionante. OmniRoute utilizza il protocollo OpenAI.", "topaz": "Connetti Topaz con una chiave API.", - "typhoon": "__MISSING__:Typhoon is OpenAI-compatible on /v1. Built by SCB 10X (Thailand); typhoon-v2.5-30b-a3b-instruct is a thai-first, multilingual model.", + "typhoon": "Typhoon è compatibile con OpenAI su /v1. Creato da SCB 10X (Thailandia); typhoon-v2.5-30b-a3b-instruct è un modello multilingue con priorità al thailandese.", "udio": "Incolla il cookie di sessione da udio.com (autenticazione Supabase)", "uncloseai": "Nessuna autenticazione richiesta. L'API accetta qualsiasi stringa non vuota come chiave per l'identificazione.", "upstage": "Connetti Upstage con una chiave API.", @@ -5947,7 +5949,7 @@ "voyage-ai": "Chiave API Bearer per le API di embedding e rerank di Voyage AI.", "wafer": "Chiave API da https://wafer.ai", "wandb": "Connetti Weights & Biases Inference con una chiave API.", - "writer": "__MISSING__:Writer Palmyra is OpenAI-compatible at https://api.writer.com/v1. palmyra-x5 offers a 1M-token context window.", + "writer": "Writer Palmyra è compatibile con OpenAI all'indirizzo https://api.writer.com/v1. palmyra-x5 offre una finestra di contesto di 1M di token.", "x5lab": "X5Lab espone un endpoint di completamento chat compatibile con OpenAI all'indirizzo https://api.x5lab.dev/v1/chat/completions, oltre a un catalogo live /v1/models. OmniRoute utilizza il protocollo OpenAI ed elenca i modelli tramite passthrough.", "xai": "Connetti xAI (Grok) con una chiave API.", "xiaomi-mimo": "Connetti Xiaomi MiMo con una chiave API.", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) è l'amico open source fondatore di OmniRoute", "cheaperInferenceSupporterBadge": "Amico open source", "cheaperInferenceSupporterTooltip": "Cheaper Inference sostiene OmniRoute come amico open source", - "kimiPartnerLinkNote": "Link partner — supporta OmniRoute senza costi aggiuntivi per te" + "kimiPartnerLinkNote": "Link partner — supporta OmniRoute senza costi aggiuntivi per te", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Impostazioni", @@ -6125,18 +6132,18 @@ "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", "requestBodyLimitCurrent": "Current: {value}", - "cacheConfigLoadFailed": "__MISSING__:Failed to load cache settings", - "cacheConfigSaveSuccess": "__MISSING__:Cache settings saved", - "cacheConfigSaveFailed": "__MISSING__:Failed to save cache settings", - "modelCatalogTtlWholeNumberError": "__MISSING__:Use a whole number", - "modelCatalogTtlMinimumError": "__MISSING__:Minimum is {min} ms", - "modelCatalogTtlMaximumError": "__MISSING__:Maximum is {max} ms", - "modelCatalogCacheTtl": "__MISSING__:Model Catalog Cache TTL", - "modelCatalogCacheTtlDescription": "__MISSING__:How long model catalog responses are cached before refreshing", - "modelCatalogCacheTtlLabel": "__MISSING__:Model catalog cache TTL in milliseconds", - "modelCatalogCacheTtlSaving": "__MISSING__:Saving...", - "modelCatalogCacheTtlSave": "__MISSING__:Save", - "modelCatalogCacheTtlCurrent": "__MISSING__:Current: {value} ms", + "cacheConfigLoadFailed": "Impossibile caricare le impostazioni della cache", + "cacheConfigSaveSuccess": "Impostazioni della cache salvate", + "cacheConfigSaveFailed": "Impossibile salvare le impostazioni della cache", + "modelCatalogTtlWholeNumberError": "Usa un numero intero", + "modelCatalogTtlMinimumError": "Il minimo è {min} ms", + "modelCatalogTtlMaximumError": "Il massimo è {max} ms", + "modelCatalogCacheTtl": "TTL Cache Catalogo Modelli", + "modelCatalogCacheTtlDescription": "Per quanto tempo le risposte del catalogo modelli vengono memorizzate nella cache prima di essere aggiornate", + "modelCatalogCacheTtlLabel": "TTL cache catalogo modelli in millisecondi", + "modelCatalogCacheTtlSaving": "Salvataggio in corso...", + "modelCatalogCacheTtlSave": "Salva", + "modelCatalogCacheTtlCurrent": "Attuale: {value} ms", "mitmProxy": "Procura MITM", "pricing": "Prezzi", "storage": "Magazzinaggio", @@ -6790,7 +6797,7 @@ "howPricingWorks": "Come funzionano i prezzi", "cacheWrite": "Scrittura nella cache", "unsaved": "non salvato", - "resetDefaults": "__MISSING__:Reset defaults", + "resetDefaults": "Ripristina impostazioni predefinite", "saveProvider": "Salva fornitore", "model": "Modello", "models": "modelli", @@ -6844,7 +6851,7 @@ "purgeLogsFailed": "Failed to purge logs", "logsDeleted": "{count, plural, =0 {Nessun log scaduto eliminato} one {Eliminato # log scaduto} other {Eliminati # log scaduti}}", "resetUsageData": "Ripristina Dati di Utilizzo", - "resetUsageDataDesc": "__MISSING__:Select how far back you want to delete usage, request logs, and analytics data. Provider configuration, connections, API keys, combos, and settings are preserved. This action cannot be undone.", + "resetUsageDataDesc": "Scegli da quanto tempo fa vuoi eliminare l'uso, i log delle richieste e i dati di analisi. Configurazione dei provider, connessioni, chiavi API, combo e impostazioni vengono conservati. Questa azione non può essere annullata.", "resetUsagePeriod_5m": "5 minuti", "resetUsagePeriod_1h": "1 ora", "resetUsagePeriod_3h": "3 ore", @@ -6970,13 +6977,13 @@ "compressionPreserveSystemNever": "Mai", "compressionLiveZoneTitle": "Live Zone allineata alla cache", "compressionLiveZoneDesc": "Mantieni stabile il prefisso della conversazione compressa ed elabora solo gli elementi aggiunti di recente.", - "compressionExclusionsTitle": "__MISSING__:Compression Exclusions", - "compressionExclusionsDesc": "__MISSING__:Model ids or provider/model patterns that must never be compressed. `*` is the only wildcard (e.g. `openai/*`, `*embedding*`). A matching request passes through byte-identical — no compression engine runs.", - "compressionExclusionsPlaceholder": "__MISSING__:One pattern per line, e.g.\nopenai/text-embedding-3-large\nanthropic/*", - "compressionExclusionsSave": "__MISSING__:Save", - "compressionExclusionsSaved": "__MISSING__:Saved", - "compressionExclusionsCount": "__MISSING__:{count, plural, one {# exclusion} other {# exclusions}} configured", - "compressionExclusionsEmpty": "__MISSING__:No exclusions configured — every model/endpoint is eligible for compression (default behavior).", + "compressionExclusionsTitle": "Esclusioni Compressione", + "compressionExclusionsDesc": "Id di modelli o pattern provider/modello che non devono mai essere compressi. `*` è l'unico jolly (es. `openai/*`, `*embedding*`). Una richiesta corrispondente passa identica byte per byte — nessun motore di compressione viene eseguito.", + "compressionExclusionsPlaceholder": "Un pattern per riga, es.\nopenai/text-embedding-3-large\nanthropic/*", + "compressionExclusionsSave": "Salva", + "compressionExclusionsSaved": "Salvato", + "compressionExclusionsCount": "{count, plural, one {# esclusione} other {# esclusioni}} configurate", + "compressionExclusionsEmpty": "Nessuna esclusione configurata — ogni modello/endpoint è idoneo alla compressione (comportamento predefinito).", "compressionCavemanConfig": "Caveman Engine Configuration", "compressionCavemanConfigDesc": "Fine-tune the rule-based compression engine", "compressionCavemanPanelHint": "L'attivazione e il livello si impostano nel panel:", @@ -7531,9 +7538,9 @@ "resilienceEnableServerWaitDesc": "Quando abilitato, OmniRoute attende la scadenza del primo tempo di recupero e riprova automaticamente.", "resilienceMaxAttempts": "Tentativi massimi", "resilienceMaxWaitPerAttempt": "Attesa massima per tentativo", - "resilienceComboCooldownWaitTitle": "__MISSING__:Combo cooldown wait", - "resilienceComboCooldownWaitDesc": "__MISSING__:For all combo strategies: wait out a short transient cooldown and re-dispatch instead of returning a 429 immediately. Never waits on quota_exhausted.", - "resilienceComboCooldownWaitToggleDesc": "__MISSING__:All combo strategies; never waits on quota_exhausted.", + "resilienceComboCooldownWaitTitle": "Attesa di cooldown della combo", + "resilienceComboCooldownWaitDesc": "Per tutte le strategie combo: attendi un breve cooldown temporaneo e inoltra nuovamente invece di restituire immediatamente un 429. Non attende mai per quota_exhausted.", + "resilienceComboCooldownWaitToggleDesc": "Tutte le strategie combo; non attende mai per quota_exhausted.", "resilienceComboCooldownMaxWaitMs": "Attesa massima per tentativo", "resilienceComboCooldownBudgetMs": "Budget attesa totale", "resilienceQuotaShareConcurrencyTitle": "Concorrenza per connessione quota-share", @@ -7812,10 +7819,6 @@ "label": "Righe minime da compattare", "description": "Numero minimo di righe in un array JSON omogeneo richiesto per attivare la compattazione tabulare. Predefinito: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Preserva prompt di sistema" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Lunghezza minima del messaggio" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -9775,23 +9782,23 @@ "deviceCodeVerificationUrl": "URL di verifica", "deviceCodeYourCode": "Il tuo codice", "deviceCodeWaiting": "In attesa di autorizzazione...", - "googleLoopbackTitle": "__MISSING__:Google sign-in can't complete from this address", - "googleLoopbackWhatHappens": "__MISSING__:Google only releases the authorization code once {redirectUri} is reachable from the browser that approves the sign-in. Here that address points at this computer, not at the OmniRoute server — so the consent screen hangs instead of redirecting, and there is no callback URL to copy.", - "googleLoopbackRecommended": "__MISSING__:Recommended — run this on your own computer, then paste the result below:", - "googleLoopbackHelperNote": "__MISSING__:It opens the Google consent locally (where 127.0.0.1 works) and prints a one-line omniroute-cred-v1.… blob. Paste that blob into the Step 2 field below — it accepts a credential blob as well as a callback URL.", - "googleLoopbackTunnelLabel": "__MISSING__:Or forward the dashboard port over SSH and reload OmniRoute through the tunnel:", - "googleLoopbackTunnelNote": "__MISSING__:Replace {userPlaceholder} with your SSH username, keep the terminal open, then open {localUrl} and connect again from there.", - "googleLoopbackHeadlessAlt": "__MISSING__:For fully headless use with no local callback at all, configure your own Google OAuth credentials plus a public base URL.", + "googleLoopbackTitle": "L'accesso con Google non può essere completato da questo indirizzo", + "googleLoopbackWhatHappens": "Google rilascia il codice di autorizzazione solo una volta che {redirectUri} è raggiungibile dal browser che approva l'accesso. Qui quell'indirizzo punta a questo computer, non al server OmniRoute — quindi la schermata di consenso si blocca invece di reindirizzare, e non c'è nessun URL di callback da copiare.", + "googleLoopbackRecommended": "Consigliato — esegui questo sul tuo computer, poi incolla il risultato qui sotto:", + "googleLoopbackHelperNote": "Apre il consenso di Google localmente (dove 127.0.0.1 funziona) e stampa un blocco omniroute-cred-v1.… su una sola riga. Incolla quel blocco nel campo Step 2 qui sotto — accetta un blocco di credenziali così come un URL di callback.", + "googleLoopbackTunnelLabel": "Oppure inoltra la porta della dashboard tramite SSH e ricarica OmniRoute attraverso il tunnel:", + "googleLoopbackTunnelNote": "Sostituisci {userPlaceholder} con il tuo username SSH, tieni il terminale aperto, quindi apri {localUrl} e connettiti di nuovo da lì.", + "googleLoopbackHeadlessAlt": "Per un uso completamente headless senza alcun callback locale, configura le tue credenziali Google OAuth più un URL di base pubblico.", "remoteAccessInfo": "Accesso remoto: poiché stai accedendo a OmniRoute da remoto, dopo l'autorizzazione vedrai una pagina di errore (localhost non trovato). Questo è normale: basta copiare l'URL completo dalla barra degli indirizzi del browser e incollarlo di seguito.", - "loopbackMismatchTitle": "__MISSING__:Sign-in can't complete from this address", - "loopbackMismatchWhatHappened": "__MISSING__:What's happening", - "loopbackMismatchExplanation": "__MISSING__:After you approve the login, {providerName} always sends the browser back to {redirectUri}. That address points at the computer running this browser, not at the OmniRoute server — so the authorization code never reaches OmniRoute and the provider fails the sign-in without showing an error.", - "loopbackMismatchHowToFix": "__MISSING__:How to fix it", - "loopbackMismatchStep1": "__MISSING__:On this computer, open a terminal and start an SSH tunnel to the OmniRoute server:", - "loopbackMismatchStep1Note": "__MISSING__:Replace {userPlaceholder} with your SSH username. Keep this terminal open until the connection shows as active — both ports are needed: one serves the dashboard, the other receives the callback.", - "loopbackMismatchStep2": "__MISSING__:In this browser, reopen OmniRoute through the tunnel:", - "loopbackMismatchStep3": "__MISSING__:Then connect {providerName} again from the new tab. The callback now reaches the server and the login completes normally.", - "loopbackMismatchAlternative": "__MISSING__:No SSH access? If this provider offers a token import tab, connect with a token instead — that path doesn't use a loopback callback.", + "loopbackMismatchTitle": "L'accesso non può essere completato da questo indirizzo", + "loopbackMismatchWhatHappened": "Cosa sta succedendo", + "loopbackMismatchExplanation": "Dopo che hai approvato l'accesso, {providerName} rimanda sempre il browser a {redirectUri}. Quell'indirizzo punta al computer che esegue questo browser, non al server OmniRoute — quindi il codice di autorizzazione non raggiunge mai OmniRoute e il provider fa fallire l'accesso senza mostrare un errore.", + "loopbackMismatchHowToFix": "Come risolvere", + "loopbackMismatchStep1": "Su questo computer, apri un terminale e avvia un tunnel SSH verso il server OmniRoute:", + "loopbackMismatchStep1Note": "Sostituisci {userPlaceholder} con il tuo username SSH. Tieni questo terminale aperto finché la connessione non risulta attiva — sono necessarie entrambe le porte: una serve la dashboard, l'altra riceve il callback.", + "loopbackMismatchStep2": "In questo browser, riapri OmniRoute attraverso il tunnel:", + "loopbackMismatchStep3": "Quindi connetti di nuovo {providerName} dalla nuova scheda. Il callback ora raggiunge il server e l'accesso si completa normalmente.", + "loopbackMismatchAlternative": "Nessun accesso SSH? Se questo provider offre una scheda per importare un token, connettiti con un token invece — quel percorso non usa un callback loopback.", "step1OpenUrl": "Passaggio 1: apri questo URL nel tuo browser", "copy": "Copia", "step2PasteCallback": "Passaggio 2: incolla qui l'URL di richiamata o il codice di autorizzazione", @@ -10195,6 +10202,8 @@ "copied": "Copiato!", "run": "Esegui", "running": "Esecuzione in corso...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Risposta", "tunnel": "Tunnel", "send": "Invia", @@ -11737,7 +11746,7 @@ "danger": "Pericolo", "requiresRestart": "Richiede il riavvio", "source": "Origine", - "ccDiscoveryAliasesEnvWarning": "__MISSING__:Active via environment variable (EXPOSE_CC_DISCOVERY_ALIASES) — this overrides any dashboard toggle below.", + "ccDiscoveryAliasesEnvWarning": "Attivo tramite variabile d'ambiente (EXPOSE_CC_DISCOVERY_ALIASES) — questo sovrascrive qualsiasi toggle della dashboard qui sotto.", "resetFlag": "Ripristina {label} al valore predefinito", "reset": "Ripristina", "loadFailed": "Impossibile caricare i feature flag", @@ -12242,7 +12251,7 @@ "partnerLinkNote": "Link partner", "dismissAriaLabel": "Ignora" }, - "featureFlagExposeFunctionalGatewayMirrorsDescription": "__MISSING__:Advertise / 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.", + "featureFlagExposeFunctionalGatewayMirrorsDescription": "Mostra gli id specchio / su /v1/models per i modelli il cui proprietario canonico non ha credenziali attive ma un gateway di transito con una credenziale attiva li instrada. Attenzione: aggiunge voci nel catalogo per tutti i client quando abilitato globalmente.", "radarPage": { "title": "Catalogo Radar", "subtitle": "Catalogo di modelli gratuito arricchito con intelligenza della comunità", diff --git a/src/i18n/messages/ja.json b/src/i18n/messages/ja.json index b6a60691c7..a9eb79f43c 100644 --- a/src/i18n/messages/ja.json +++ b/src/i18n/messages/ja.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "新しいモデルは追加されませんでした (すべてすでに存在しています)。", "importDoneCount": "✓ 完了! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "予期しないエラーが発生しました", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "メッセージ", "responsesPath": "応答", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi(Moonshot AI)は OmniRoute の創設オープンソースフレンドです", "cheaperInferenceSupporterBadge": "オープンソースフレンド", "cheaperInferenceSupporterTooltip": "Cheaper Inference は OmniRoute をオープンソースフレンドとして支援しています", - "kimiPartnerLinkNote": "パートナーリンク — 追加費用なしで OmniRoute をサポートします" + "kimiPartnerLinkNote": "パートナーリンク — 追加費用なしで OmniRoute をサポートします", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "設定", @@ -7812,10 +7819,6 @@ "label": "圧縮する最小行数", "description": "表形式の圧縮をトリガーするために必要な、同質なJSON配列の最小行数。デフォルト: 8。" }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "システムプロンプトを保持" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "最小メッセージ長" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "コピーしました!", "run": "実行", "running": "実行中...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "レスポンス", "tunnel": "トンネル", "send": "送信", diff --git a/src/i18n/messages/ko.json b/src/i18n/messages/ko.json index 49648edb0a..89066b675e 100644 --- a/src/i18n/messages/ko.json +++ b/src/i18n/messages/ko.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "새로운 모델이 추가되지 않았습니다(모두 이미 존재함).", "importDoneCount": "✓ 완료! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "예상치 못한 오류가 발생했습니다.", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "messages", "responsesPath": "responses", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi(Moonshot AI)는 OmniRoute의 창립 오픈소스 프렌드입니다", "cheaperInferenceSupporterBadge": "오픈 소스 친구", "cheaperInferenceSupporterTooltip": "Cheaper Inference는 오픈 소스 친구로서 OmniRoute를 후원합니다", - "kimiPartnerLinkNote": "파트너 링크 — 추가 비용 없이 OmniRoute를 지원합니다" + "kimiPartnerLinkNote": "파트너 링크 — 추가 비용 없이 OmniRoute를 지원합니다", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "설정", @@ -7812,10 +7819,6 @@ "label": "압축할 최소 행 수", "description": "테이블 형식 압축을 트리거하는 데 필요한 동질적 JSON 배열의 최소 행 수입니다. 기본값: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "시스템 프롬프트 유지" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "최소 메시지 길이" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "복사되었습니다!", "run": "실행", "running": "실행 중...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "응답", "tunnel": "터널", "send": "전송", diff --git a/src/i18n/messages/mr.json b/src/i18n/messages/mr.json index fd3648c190..35cffdd0a2 100644 --- a/src/i18n/messages/mr.json +++ b/src/i18n/messages/mr.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "No new models were added (all already exist).", "importDoneCount": "✓ Done! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "An unexpected error occurred", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "messages", "responsesPath": "responses", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) हा OmniRoute चा संस्थापक ओपन सोर्स मित्र आहे", "cheaperInferenceSupporterBadge": "ओपन सोर्स मित्र", "cheaperInferenceSupporterTooltip": "Cheaper Inference ओपन सोर्स मित्र म्हणून OmniRoute ला पाठिंबा देते", - "kimiPartnerLinkNote": "भागीदार लिंक — तुमच्यासाठी कोणत्याही अतिरिक्त खर्चाशिवाय OmniRoute ला सपोर्ट करते" + "kimiPartnerLinkNote": "भागीदार लिंक — तुमच्यासाठी कोणत्याही अतिरिक्त खर्चाशिवाय OmniRoute ला सपोर्ट करते", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Settings", @@ -7812,10 +7819,6 @@ "label": "कॉम्पॅक्ट करण्यासाठी किमान ओळी", "description": "टॅब्युलर कॉम्पॅक्शन ट्रिगर करण्यासाठी एकसमान JSON ॲरेमध्ये आवश्यक असलेल्या किमान ओळी. डीफॉल्ट: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "सिस्टम प्रॉम्प्ट जतन करा" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "किमान संदेश लांबी" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "कॉपी केले!", "run": "चालवा", "running": "चालवत आहे...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "प्रतिसाद", "tunnel": "टनेल", "send": "पाठवा", diff --git a/src/i18n/messages/ms.json b/src/i18n/messages/ms.json index bc2a159b25..899543d890 100644 --- a/src/i18n/messages/ms.json +++ b/src/i18n/messages/ms.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Tiada model baharu ditambahkan (semua sudah wujud).", "importDoneCount": "✓ Selesai! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Ralat yang tidak dijangka berlaku", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "mesej", "responsesPath": "maklum balas", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) ialah rakan sumber terbuka pengasas OmniRoute", "cheaperInferenceSupporterBadge": "Rakan Sumber Terbuka", "cheaperInferenceSupporterTooltip": "Cheaper Inference menyokong OmniRoute sebagai Rakan Sumber Terbuka", - "kimiPartnerLinkNote": "Pautan rakan kongsi — menyokong OmniRoute tanpa kos tambahan kepada anda" + "kimiPartnerLinkNote": "Pautan rakan kongsi — menyokong OmniRoute tanpa kos tambahan kepada anda", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "tetapan", @@ -7812,10 +7819,6 @@ "label": "Baris minimum untuk dipadatkan", "description": "Baris minimum dalam tatasusunan JSON homogen yang diperlukan untuk mencetuskan pemadatan jadual. Lalai: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Kekalkan gesaan sistem" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Panjang mesej minimum" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Disalin!", "run": "Jalankan", "running": "Menjalankan...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Respons", "tunnel": "Terowong", "send": "Hantar", diff --git a/src/i18n/messages/nl.json b/src/i18n/messages/nl.json index 8529dc71db..d4e934d2ed 100644 --- a/src/i18n/messages/nl.json +++ b/src/i18n/messages/nl.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Er zijn geen nieuwe modellen toegevoegd (ze bestaan allemaal al).", "importDoneCount": "✓ Klaar! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Er is een onverwachte fout opgetreden", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "berichten", "responsesPath": "reacties", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) is OmniRoute's oprichtende open source-vriend", "cheaperInferenceSupporterBadge": "Opensourcevriend", "cheaperInferenceSupporterTooltip": "Cheaper Inference steunt OmniRoute als opensourcevriend", - "kimiPartnerLinkNote": "Partnerlink — ondersteunt OmniRoute zonder extra kosten voor u" + "kimiPartnerLinkNote": "Partnerlink — ondersteunt OmniRoute zonder extra kosten voor u", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Instellingen", @@ -7812,10 +7819,6 @@ "label": "Minimum aantal rijen om te compacteren", "description": "Minimum aantal rijen in een homogene JSON-array dat vereist is om tabulaire compactie te activeren. Standaard: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Systeemprompt behouden" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Minimale berichtlengte" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Gekopieerd!", "run": "Uitvoeren", "running": "Bezig met uitvoeren...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Respons", "tunnel": "Tunnel", "send": "Verzenden", diff --git a/src/i18n/messages/no.json b/src/i18n/messages/no.json index bd779d1fea..28d4fc13bd 100644 --- a/src/i18n/messages/no.json +++ b/src/i18n/messages/no.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Ingen nye modeller ble lagt til (alle finnes allerede).", "importDoneCount": "✓ Ferdig! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Det oppstod en uventet feil", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "meldinger", "responsesPath": "svar", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) er OmniRoutes grunnleggende åpen kildekode-venn", "cheaperInferenceSupporterBadge": "Åpen kildekode-venn", "cheaperInferenceSupporterTooltip": "Cheaper Inference støtter OmniRoute som åpen kildekode-venn", - "kimiPartnerLinkNote": "Partnerlenke — støtter OmniRoute uten ekstra kostnad for deg" + "kimiPartnerLinkNote": "Partnerlenke — støtter OmniRoute uten ekstra kostnad for deg", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Innstillinger", @@ -7812,10 +7819,6 @@ "label": "Minimum rader å komprimere", "description": "Minimum antall rader i et homogent JSON-array som kreves for å utløse tabulær komprimering. Standard: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Bevar system-prompt" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Minimum meldingslengde" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Kopiert!", "run": "Kjør", "running": "Kjører...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Respons", "tunnel": "Tunnel", "send": "Send", diff --git a/src/i18n/messages/phi.json b/src/i18n/messages/phi.json index 3a3098b0e6..16e739b25d 100644 --- a/src/i18n/messages/phi.json +++ b/src/i18n/messages/phi.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Walang mga bagong modelo ang naidagdag (lahat ay mayroon na).", "importDoneCount": "✓ Tapos na! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "May naganap na hindi inaasahang error", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "mga mensahe", "responsesPath": "mga tugon", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Ang Kimi (Moonshot AI) ang tagapagtatag na open source na kaibigan ng OmniRoute", "cheaperInferenceSupporterBadge": "Kaibigan ng Open Source", "cheaperInferenceSupporterTooltip": "Sinusuportahan ng Cheaper Inference ang OmniRoute bilang Kaibigan ng Open Source", - "kimiPartnerLinkNote": "Link ng kasosyo — sumusuporta sa OmniRoute nang walang karagdagang gastos sa iyo" + "kimiPartnerLinkNote": "Link ng kasosyo — sumusuporta sa OmniRoute nang walang karagdagang gastos sa iyo", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Mga setting", @@ -7812,10 +7819,6 @@ "label": "Minimum na row na iko-compact", "description": "Minimum na row sa isang homogeneous na JSON array na kinakailangan upang ma-trigger ang tabular compaction. Default: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Panatilihin ang system prompt" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Minimum na haba ng mensahe" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Nakopya na!", "run": "Patakbuhin", "running": "Tumatakbo...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Tugon", "tunnel": "Tunnel", "send": "Ipadala", diff --git a/src/i18n/messages/pl.json b/src/i18n/messages/pl.json index 7b3db8339e..3eae950621 100644 --- a/src/i18n/messages/pl.json +++ b/src/i18n/messages/pl.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Nie dodano nowych models (wszystkie już istnieją).", "importDoneCount": "✓ Gotowe! {count, plural, one {Zaimportowano # model.} other {Zaimportowano # modeli.}}", "unexpectedErrorOccurred": "Wystąpił nieoczekiwany błąd", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# połączenie} other {# połączeń}}", "messagesPath": "messages", "responsesPath": "responses", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) jest przyjacielem-założycielem open source OmniRoute", "cheaperInferenceSupporterBadge": "Przyjaciel open source", "cheaperInferenceSupporterTooltip": "Cheaper Inference wspiera OmniRoute jako przyjaciel open source", - "kimiPartnerLinkNote": "Link partnerski — wspiera OmniRoute bez żadnych dodatkowych kosztów dla Ciebie" + "kimiPartnerLinkNote": "Link partnerski — wspiera OmniRoute bez żadnych dodatkowych kosztów dla Ciebie", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Ustawienia", @@ -7812,10 +7819,6 @@ "label": "Minimalna liczba wierszy do kompaktowania", "description": "Minimalna liczba wierszy w jednorodnej tablicy JSON wymagana do uruchomienia kompaktowania tabelarycznego. Domyślnie: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Zachowaj prompt systemowy" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Minimalna długość wiadomości" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Skopiowano!", "run": "Uruchom", "running": "Uruchamianie...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Odpowiedź", "tunnel": "Tunel", "send": "Wyślij", diff --git a/src/i18n/messages/pt-BR.json b/src/i18n/messages/pt-BR.json index 1b2dbe9ea2..7ba3d31af2 100644 --- a/src/i18n/messages/pt-BR.json +++ b/src/i18n/messages/pt-BR.json @@ -1094,6 +1094,8 @@ "costsFreeTiersSubtitle": "Cotas mensais de tokens gratuitos", "freeProviderRankings": "Rankings de provedores gratuitos", "freeProviderRankingsSubtitle": "Melhores provedores gratuitos classificados por pontuações ELO do modelo", + "radar": "Catálogo Radar", + "radarSubtitle": "Catálogo de modelos gratuitos enriquecido pela comunidade", "costsQuotaShare": "Compartilhamento de Cota", "costsPricing": "Pricing", "logsProxy": "Proxy Logs", @@ -5071,6 +5073,8 @@ "noNewModelsAddedExisting": "Nenhum novo modelo foi adicionado (todos já existem).", "importDoneCount": "✓ Concluído! {count, plural, one {# modelo importado.} other {# modelos importados.}}", "unexpectedErrorOccurred": "Ocorreu um erro inesperado", + "getApiKey": "Obter chave de API", + "getApiKeyDescription": "Registre-se ou inscreva-se para obter uma chave de API", "connectionCountLabel": "{count, plural, one {# conexão} other {# conexões}}", "messagesPath": "messages", "responsesPath": "responses", @@ -5487,6 +5491,13 @@ "newApiUserIdLabel": "ID de Usuário New-API", "newApiUserIdPlaceholder": "ex.: 12345", "newApiUserIdHint": "Valor do cabeçalho New-Api-User do AgentRouter, usado junto com a chave de API do console para consultar o saldo de cota.", + "newApiAggregatorToggleLabel": "Gateway agregador", + "newApiAggregatorToggleHint": "Ativa a detecção de saldo para nós agregadores New-API / One-API / Sub2API. O painel passa a mostrar o selo de saldo e o roteamento com quota-preflight pula contas esgotadas.", + "newApiAggregatorConsoleApiKeyHint": "System Access Token para o endpoint /api/user/self do agregador. Não é a chave de API de roteamento.", + "newApiAggregatorUserIdHint": "Valor do cabeçalho New-Api-User usado para buscar o saldo de quota do usuário do agregador.", + "newApiAggregatorQuotaPerUnitLabel": "Quota por unidade", + "newApiAggregatorQuotaPerUnitHint": "Unidades de crédito New-API por US$ 1 (padrão: 500000). Substitua se o seu agregador usar outra taxa.", + "featureFlagNewApiAggregatorBalanceDescription": "Ativa a detecção de saldo para nós compatíveis New-API / One-API / Sub2API", "cpaModeDisabledTitle": "Habilitar backend CLIProxyAPI para emulação OAuth mais profunda do Claude Code", "cpaModeEnabledTitle": "Usando CLIProxyAPI para uma emulação mais profunda do Claude Code (uTLS, multi-conta, perfis de dispositivo)", "customUserAgentHint": "Override opcional enviado upstream como cabeçalho User-Agent desta conexão.", @@ -5602,6 +5613,7 @@ "tagGroupPlaceholder": "ex.: personal, work, team-a", "testModel": "Test Model", "testingModel": "Testing Model", + "modelTestQuotaTooltip": "Quota esgotada — reseta amanhã ou precisa de recarga", "toggleOffShort": "OFF", "toggleOnShort": "ON", "tokenExpiredBadge": "Expirado", @@ -6020,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "A Kimi (Moonshot AI) é a amiga fundadora de código aberto do OmniRoute", "cheaperInferenceSupporterBadge": "Amigo do Código Aberto", "cheaperInferenceSupporterTooltip": "A Cheaper Inference apoia o OmniRoute como amiga do código aberto", - "kimiPartnerLinkNote": "Link de parceiro — apoia o OmniRoute sem custo extra para você" + "kimiPartnerLinkNote": "Link de parceiro — apoia o OmniRoute sem custo extra para você", + "anonymousFallbackTitle": "Fallback anônimo", + "anonymousFallbackDesc": "Quando todas as conexões configuradas estiverem esgotadas (cota, créditos ou expiração), use temporariamente a camada sem chave deste provedor. Desative para ignorar este provedor em vez de enviar solicitações anônimas — recomendado quando a camada sem chave as rejeita (401).", + "anonymousFallbackEnabled": "Fallback anônimo ativado para {provider}", + "anonymousFallbackDisabled": "Fallback anônimo desativado para {provider} — conexões esgotadas ignorarão este provedor", + "anonymousFallbackUpdateFailed": "Falha ao atualizar a configuração de fallback anônimo" }, "settings": { "title": "Configurações", @@ -7802,10 +7819,6 @@ "label": "Mínimo de linhas para compactar", "description": "Mínimo de linhas em um array JSON homogêneo necessárias para acionar a compactação tabular. Padrão: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Preservar prompt do sistema" }, @@ -7829,6 +7842,10 @@ }, "minMessageLength": { "label": "Comprimento mínimo da mensagem" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10185,6 +10202,8 @@ "copied": "Copiado!", "run": "Executar", "running": "Executando...", + "loading": "Carregando...", + "retry": "Tentar novamente", "response": "Resposta", "tunnel": "Tunnel", "send": "Enviar", @@ -11533,7 +11552,10 @@ "noSavedProxiesError": "Nenhum proxy salvo encontrado. Adicione proxies em Configurações → Proxy primeiro.", "updateProviderFailed": "Falha ao atualizar provedor", "providerEnabled": "{provider} ativado", - "providerDisabled": "{provider} desativado" + "providerDisabled": "{provider} desativado", + "providerAdded": "{provider} adicionado", + "add": "Adicionar", + "manualApiKey": "Usar uma chave de API manual" }, "gamification": { "leaderboardScopes": { @@ -12230,6 +12252,87 @@ "dismissAriaLabel": "Descartar" }, "featureFlagExposeFunctionalGatewayMirrorsDescription": "__MISSING__:Advertise / 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.", + "radarPage": { + "title": "Catálogo Radar", + "subtitle": "Catálogo de modelos gratuitos enriquecido com inteligência comunitária", + "loading": "Carregando catálogo...", + "errorLoading": "Falha ao carregar catálogo Radar", + "emptyState": "Sem dados no catálogo ainda. Sincronize para baixar o feed mais recente.", + "syncNow": "Sincronizar agora", + "syncing": "Sincronizando...", + "syncCta": "Sincronizar agora", + "syncFailed": "Falha na sincronização", + "flagDisabled": "Radar está desativado", + "activationFailed": "Falha na ativação", + "feedVersion": "Versão do feed", + "feedTier": "Nível", + "feedFetched": "Última busca", + "tierLive": "Ao vivo (tempo real)", + "tierCommunity": "Comunidade (atraso de 30 dias)", + "activateTitle": "Ativar Radar", + "activateDescription": "O Radar enriquece o catálogo de modelos gratuitos com inteligência de fontes comunitárias — disponibilidade de modelos atualizada, cotas e guias de configuração.", + "privacyNoUpload": "Nada é enviado — seus dados ficam locais", + "privacyOnlySigned": "Apenas metadados criptograficamente assinados são baixados", + "privacyLocalOnly": "Todo processamento acontece na sua instância OmniRoute", + "activateButton": "Ativar", + "activating": "Ativando...", + "keySectionTitle": "Already have a supporter key?", + "keyInvalidFormatError": "Invalid key format. It must start with \"omr_\" followed by 40 hex characters.", + "activateWithKeyButton": "Activate supporter", + "changeKeyButton": "Change key", + "claimSectionTitle": "Don't have a supporter key yet?", + "contributorButton": "I'm a contributor", + "contributorHint": "Verify your GitHub account — 5+ merged pull requests or a top-100 contributor spot unlocks a free supporter key.", + "supporterButton": "Support the project", + "supporterHint": "Support OmniRoute to get a supporter key with the live catalog and extra perks.", + "colProvider": "Provedor", + "colModel": "Modelo", + "colQuota": "Cota", + "colContext": "Contexto", + "colCapabilities": "Capacidades", + "colTos": "Risco ToS", + "newBadge": "novo", + "setupGuide": "Guia de configuração", + "disabledByFeed": "Desativado pelo feed Radar", + "capTools": "Ferramentas", + "capVision": "Visão", + "capThinking": "Raciocínio", + "catalogTab": "Catalog", + "freeCreditsTab": "Free credits", + "freeCreditsSubtitle": "Referral links from Radar-tracked providers — using them costs you nothing extra and helps support OmniRoute.", + "fixedLinksEmpty": "No referral links available yet. Sync Radar to check for updates.", + "requiredActionLabel": "What to do:", + "claimButton": "Claim credits", + "campaignsTitle": "Limited-time campaigns", + "campaignsEmpty": "No active campaigns right now — check back later.", + "campaignsUpsellCommunity": "Limited-time campaigns are a supporter extra. Everything on this page's fixed links stays free for everyone.", + "campaignsValidUntil": "Valid until {date}" + }, + "radarSetupPage": { + "title": "Configuração do Provedor", + "setupTitle": "Configuração: {provider}", + "setupSubtitle": "Siga os passos abaixo para configurar este provedor", + "loading": "Carregando...", + "loadFailed": "Falha ao carregar dados de configuração", + "flagDisabled": "Radar está desativado", + "providerNotFound": "Provedor \"{provider}\" não encontrado no catálogo", + "noProvider": "Nenhum provedor especificado. Volte ao catálogo e selecione um provedor.", + "backToCatalog": "Voltar ao catálogo", + "providerConfigured": "Provedor configurado e pronto", + "getApiKey": "Obtenha sua chave de API", + "setupSteps": "Passos de configuração", + "noGuide": "Nenhum guia de configuração disponível para este provedor.", + "visitDocs": "Visitar documentação do provedor", + "testConnection": "Testar conexão", + "testDescription": "Verifique se sua conexão está funcionando corretamente.", + "testButton": "Testar conexão", + "testing": "Testando...", + "testSuccess": "Conexão bem-sucedida!", + "testFailed": "Falha no teste de conexão", + "addConnection": "Adicionar conexão", + "addConnectionDescription": "Ainda não tem uma conexão? Adicione uma no painel de provedores.", + "addConnectionLink": "Ir para provedores →" + }, "resilienceConnections": { "title": "Resiliência de Conexão", "table": { diff --git a/src/i18n/messages/pt.json b/src/i18n/messages/pt.json index b5fb8a7380..a8564f9435 100644 --- a/src/i18n/messages/pt.json +++ b/src/i18n/messages/pt.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Nenhum novo modelo foi adicionado (todos já existem).", "importDoneCount": "✓ Pronto! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Ocorreu um erro inesperado", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "mensagens", "responsesPath": "respostas", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "A Kimi (Moonshot AI) é a amiga fundadora de código aberto do OmniRoute", "cheaperInferenceSupporterBadge": "Amigo do Código Aberto", "cheaperInferenceSupporterTooltip": "A Cheaper Inference apoia o OmniRoute como amiga do código aberto", - "kimiPartnerLinkNote": "Link de parceiro — apoia o OmniRoute sem custos adicionais para si" + "kimiPartnerLinkNote": "Link de parceiro — apoia o OmniRoute sem custos adicionais para si", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Configurações", @@ -7812,10 +7819,6 @@ "label": "Mínimo de linhas a compactar", "description": "Número mínimo de linhas num array JSON homogéneo necessário para acionar a compactação tabular. Predefinição: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Preservar prompt do sistema" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Comprimento mínimo da mensagem" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Copiado!", "run": "Executar", "running": "A executar...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Resposta", "tunnel": "Túnel", "send": "Enviar", diff --git a/src/i18n/messages/ro.json b/src/i18n/messages/ro.json index 843c7ef3fa..f443d1ea20 100644 --- a/src/i18n/messages/ro.json +++ b/src/i18n/messages/ro.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Nu au fost adăugate modele noi (toate există deja).", "importDoneCount": "✓ Gata! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "A apărut o eroare neașteptată", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "mesaje", "responsesPath": "răspunsuri", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) este prietenul fondator open source al OmniRoute", "cheaperInferenceSupporterBadge": "Prieten open source", "cheaperInferenceSupporterTooltip": "Cheaper Inference susține OmniRoute ca prieten open source", - "kimiPartnerLinkNote": "Link de partener — susține OmniRoute fără costuri suplimentare pentru dvs." + "kimiPartnerLinkNote": "Link de partener — susține OmniRoute fără costuri suplimentare pentru dvs.", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Setări", @@ -7812,10 +7819,6 @@ "label": "Număr minim de rânduri de compactat", "description": "Numărul minim de rânduri dintr-un tablou JSON omogen necesar pentru a declanșa compactarea tabulară. Implicit: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Păstrează promptul de sistem" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Lungime minimă a mesajului" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Copiat!", "run": "Rulează", "running": "Se rulează...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Răspuns", "tunnel": "Tunel", "send": "Trimite", diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json index 55292cd9d3..2f68901c5a 100644 --- a/src/i18n/messages/ru.json +++ b/src/i18n/messages/ru.json @@ -937,7 +937,7 @@ "disabled": "Отключено", "featureFlagOmnirouteEmergencyFallbackDescription": "Перенаправлять запросы при исчерпании бюджета на резервный бесплатный провайдер/модель.", "featureFlagArenaEloSyncEnabledDescription": "Включить периодическую синхронизацию ELO из таблицы лидеров Arena AI для рейтинга интеллектуальности моделей.", - "featureFlagExposeCcDiscoveryAliasesDescription": "__MISSING__: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.", + "featureFlagExposeCcDiscoveryAliasesDescription": "Публиковать claude/<провайдер>/<модель> зеркальные ID на /v1/models, чтобы Claude Code мог видеть не-Claude модели. Внимание: удваивает записи каталога для всех клиентов при глобальном включении.", "sidebar": { "home": "Главная", "dashboard": "Панель управления", @@ -1055,7 +1055,7 @@ "combosLive": "Combo Studio", "combosLiveSubtitle": "Каскад маршрутизации в реальном времени", "compressionStudio": "Compression Studio", - "compressionExclusions": "__MISSING__:Exclusions", + "compressionExclusions": "Исключения", "contextSettingsSubtitle": "Глобальные настройки по умолчанию", "contextHeadroomSubtitle": "Табличное уплотнение", "contextSessionDedupSubtitle": "Межходовая дедупликация", @@ -1066,7 +1066,7 @@ "contextUltraSubtitle": "Эвристическая обрезка", "contextOmniglyphSubtitle": "Контекст как изображения", "compressionStudioSubtitle": "Каскад движков в реальном времени", - "compressionExclusionsSubtitle": "__MISSING__:Per-model/endpoint bypass", + "compressionExclusionsSubtitle": "Обход для отдельных моделей/endpoint'ов", "chaosConfigSubtitle": "Мультимодельное параллельное выполнение", "routingSection": "Routing", "protocolsSection": "Protocols", @@ -1109,7 +1109,7 @@ "settingsSecurity": "Security", "settingsAccessTokens": "Токены доступа", "settingsFeatureFlags": "Флаги функций", - "settingsCache": "__MISSING__:Cache", + "settingsCache": "Кэш", "settingsAuthz": "Authz", "settingsRouting": "Routing", "settingsResilience": "Resilience", @@ -1121,7 +1121,7 @@ "runtime": "Runtime", "consoleLogs": "Console Logs", "logsTimeline": "Timeline", - "logsTimelineSubtitle": "__MISSING__:Visual request timeline", + "logsTimelineSubtitle": "Визуальная временная шкала запросов", "globalRouting": "Global Routing", "mitmProxy": "MITM Proxy", "oneProxy": "1Proxy", @@ -1196,7 +1196,7 @@ "settingsSecuritySubtitle": "Auth and encryption", "settingsAccessTokensSubtitle": "Токены CLI с ограниченной областью видимости для удаленного режима", "settingsFeatureFlagsSubtitle": "Переключить возможности системы", - "settingsCacheSubtitle": "__MISSING__:Model catalog and response caching", + "settingsCacheSubtitle": "Кэш каталога моделей и ответов", "settingsSidebar": "Sidebar", "settingsSidebarSubtitle": "Customize sidebar layout", "settingsAuthzSubtitle": "Политика маршрутизации инвентаря и обхода", @@ -1561,7 +1561,7 @@ "settingsGeneralDescription": "Storage, database, and general instance configuration", "settingsAppearanceDescription": "Theme, branding, and visual customization", "settingsAiDescription": "AI behaviors, thinking budgets, vision, and memory settings", - "settingsCacheDescription": "__MISSING__:TTL for model catalog cache entries", + "settingsCacheDescription": "TTL для записей кэша каталога моделей", "settingsSecurityDescription": "Authentication, authorization, and access control settings", "featureFlags": "Флаги функций", "featureFlagsDescription": "Возможности системы управления и экспериментальные возможности", @@ -2515,14 +2515,14 @@ "auto": "Авто", "always": "Всегда" }, - "ccDiscoveryInfoButton": "__MISSING__:How to enable discovery in Claude Code", - "ccDiscoveryInfoTooltip": "__MISSING__:Advertise non-Claude models under claude/<provider>/<model> mirror ids so Claude Code's gateway model discovery can list them. Doubles catalog entries for all clients when enabled globally.", - "ccDiscoveryInfoLink": "__MISSING__:Open Feature Flags", - "ccOnboardingTitle": "__MISSING__:settings.json for gateway model discovery", - "ccOnboardingCopy": "__MISSING__:Copy", - "ccOnboardingCopied": "__MISSING__:Copied", - "ccOnboardingKeyPlaceholder": "__MISSING__:", - "ccOnboardingWindowNote": "__MISSING__:Claude Code assumes a 200K context window for any model id it does not recognize. For a model with a different real window, add CLAUDE_CODE_AUTO_COMPACT_WINDOW just under it so auto-compaction does not fire too early.", + "ccDiscoveryInfoButton": "Как включить обнаружение в Claude Code", + "ccDiscoveryInfoTooltip": "Публиковать не-Claude модели под зеркальными ID claude/<провайдер>/<модель>, чтобы Claude Code мог их обнаруживать. Удваивает записи каталога для всех клиентов при глобальном включении.", + "ccDiscoveryInfoLink": "Открыть Feature Flags", + "ccOnboardingTitle": "settings.json для обнаружения gateway моделей", + "ccOnboardingCopy": "Копировать", + "ccOnboardingCopied": "Скопировано", + "ccOnboardingKeyPlaceholder": "<ваш API ключ OmniRoute>", + "ccOnboardingWindowNote": "Claude Code предполагает окно контекста в 200K для любой незнакомой модели. Если у модели другой реальный размер окна, добавьте CLAUDE_CODE_AUTO_COMPACT_WINDOW прямо под ней, чтобы авто-компактизация не срабатывала слишком рано.", "failedSave": "Не удалось сохранить", "profileSyncTitle": "Автосинхронизация профилей CLI", "profileSyncDescription": "После синхронизации моделей провайдеров автоматически перезаписывать профили инструментов CLI из актуального каталога. Отключено по умолчанию — записываются только файлы профилей; активная конфигурация или конфигурация по умолчанию никогда не изменяется.", @@ -3730,7 +3730,7 @@ "modelsCount": "{count, plural, one {# модель} few {# модели} many {# моделей} other {# модели}}", "sectionTitle": "Интерфейс интеграции", "sectionDescription": "API, совместимые с OpenAI, и конечные точки операционных протоколов", - "tabApis": "__MISSING__:APIs", + "tabApis": "API", "tabProtocols": "Протоколы", "tabsAria": "Разделы конечной точки", "protocolsTitle": "Протоколы", @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Новых моделей не добавлялось (все уже есть).", "importDoneCount": "✓ Готово! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Произошла непредвиденная ошибка", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# соединение} few {# соединения} many {# соединений} other {# соединения}}", "messagesPath": "сообщения", "responsesPath": "ответы", @@ -5203,18 +5205,18 @@ "interceptFetchHint": "Перенаправлять нативные вызовы инструмента web_fetch на /v1/web/fetch в OmniRoute.", "interceptionLoadError": "Не удалось загрузить настройки перехвата: {error}", "interceptionSaveError": "Не удалось сохранить настройки перехвата: {error}", - "ccAliasSectionTitle": "__MISSING__:Expose in Claude Code (claude/…)", - "ccAliasSectionHint": "__MISSING__:Advertise this provider's models under claude/<provider>/<model> mirror ids so Claude Code's gateway model discovery can list them. Off by default — enabling this doubles catalog entries for all clients.", - "ccAliasProviderLevelLabel": "__MISSING__:Provider default", - "ccAliasModelOverridesLabel": "__MISSING__:Per-model overrides", - "ccAliasModelOverrideAriaLabel": "__MISSING__:Override for {modelId}", - "ccAliasStateInherit": "__MISSING__:Inherit", - "ccAliasStateOn": "__MISSING__:On", - "ccAliasStateOff": "__MISSING__:Off", - "ccAliasAddModelPlaceholder": "__MISSING__:Model id (e.g. gpt-4o)", - "ccAliasAddModelButton": "__MISSING__:Add override", - "ccAliasLoadError": "__MISSING__:Failed to load discovery-alias settings: {error}", - "ccAliasSaveError": "__MISSING__:Failed to save discovery-alias setting: {error}", + "ccAliasSectionTitle": "Зеркальные ID Claude Code", + "ccAliasSectionHint": "Эти зеркала публикуют не-Claude модели под ID claude/<провайдер>/<модель>, чтобы Claude Code gateway model discovery мог их перечислить.", + "ccAliasProviderLevelLabel": "Провайдер включён", + "ccAliasModelOverridesLabel": "Переопределения моделей", + "ccAliasModelOverrideAriaLabel": "Переопределение модели", + "ccAliasStateInherit": "Наследовать", + "ccAliasStateOn": "Вкл", + "ccAliasStateOff": "Выкл", + "ccAliasAddModelPlaceholder": "Добавить модель…", + "ccAliasAddModelButton": "Добавить", + "ccAliasLoadError": "Не удалось загрузить зеркальные ID Claude Code", + "ccAliasSaveError": "Не удалось сохранить зеркальные ID Claude Code", "compatUpstreamHeadersLabel": "Дополнительные заголовки upstream", "compatUpstreamHeadersHint": "Настройка с высоким уровнем доверия - тот же уровень, что и редактирование API-учётных данных провайдера; использовать только доверенным администраторам. Применяется после того, как OmniRoute добавит авторизацию из API-ключа провайдера. Если пользовательский заголовок совпадает по имени с уже существующим (например, Authorization), ваше значение полностью заменяет автоматически созданный заголовок (включая Bearer token) - upstream увидит только введённое вами значение, а не ключ из настроек. Ошибка настройки может привести к 401 или поломке upstream-аутентификации. По одной строке на заголовок (например, дополнительный Authentication для некоторых шлюзов). Наведите курсор или сфокусируйте поле, чтобы увидеть предпросмотр. Сохраняется при потере фокуса, клике вне поля или закрытии панели.", "compatUpstreamHeaderName": "Имя заголовка", @@ -5449,8 +5451,8 @@ "t3ChatWebCookieHint": "Откройте t3.chat → DevTools → Приложение → Локальное хранилище → https://t3.chat, скопируйте «convex-session-id». Затем откройте DevTools → Network и скопируйте полный заголовок Cookie из любого запроса в чате. Вставьте оба значения в поля ниже.", "t3ChatWebCookiePlaceholder": "выпуклый-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", - "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", + "blockClaudeExtraUsageDescription": "При включении OmniRoute помечает это подключение Claude как недоступное, как только API использования сообщает о наличии платного доп. трафика, так что fallback переключается на другое подключение вместо продолжения работы с оплатой по факту.", + "blockClaudeExtraUsageLabel": "Блокировать доп. использование Claude", "disableCoolingDescription": "Пропускать временный кулдаун, чтобы это подключение оставалось доступным даже после устранимых ошибок (терминальные состояния, такие как banned/expired, по-прежнему применяются).", "disableCoolingLabel": "Отключить кулдаун для этого подключения", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5637,13 +5639,13 @@ "importGrokAuth": "Импортировать авторизацию Grok Build", "zedImportTitle": "Импортировать из связки ключей Zed", "zedImportDescription": "Найти учетные данные провайдеров ИИ (OpenAI, Anthropic, Google, Mistral, xAI), сохраненные Zed IDE в связке ключей ОС, и импортировать их как подключения. На этом компьютере должна быть установлена Zed IDE.", - "zedImportButton": "__MISSING__:Import from Zed", - "zedImportFailed": "__MISSING__:Zed import failed", + "zedImportButton": "Импортировать из Zed", + "zedImportFailed": "Импорт из Zed не удался", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", - "zedImporting": "__MISSING__:Importing…", + "zedImportSuccess": "Импортировано {credentials} учетная(ых) запись(ей) из Zed для {providers} провайдера(ов)", + "zedImporting": "Импортируется…", "zedNoCredentials": "В связке ключей не найдено учетных данных Zed", "zedUnsupportedCredentials": "Найдено {count} учетных записей в связке ключей, но ни одна не соответствует поддерживаемым провайдерам", "zedManualTitle": "Ручной импорт токена", @@ -5790,7 +5792,7 @@ "bailian-coding-plan": "Подключите Alibaba Coding Plan с помощью API-ключа.", "bedrock": "Нативная интеграция с Bedrock: для обнаружения моделей используются базовые модели Bedrock и профили вывода (inference profiles), а для чата — региональные API Bedrock Runtime Converse/ConverseStream.", "anthropic": "Подключите Anthropic с помощью API-ключа.", - "ant-ling": "__MISSING__:Register and create an API key at the Ant Ling API console (https://chat.ant-ling.com/open), then paste it here. OmniRoute routes chat traffic to https://api.ant-ling.com/v1/chat/completions; the provider is OpenAI-compatible and also exposes an Anthropic-compatible surface.", + "ant-ling": "Ant Ling — (ant-ling) — ML/AI платформа с фокусом на NLP", "api-airforce": "Получите API-ключ на https://panel.api.airforce — OpenAI-совместимая конечная точка по адресу https://api.airforce/v1", "arcee-ai": "Получите API-ключ на arcee.ai", "azure-ai": "Foundry использует интерфейс OpenAI v1 с именами развертываний в качестве моделей. OmniRoute нормализует корневые URL-адреса ресурсов до конечных точек v1 chat и /models.", @@ -5811,7 +5813,7 @@ "chutes": "Bearer API-ключ для совместимого с OpenAI шлюза Chutes.", "clarifai": "Clarifai предоставляет совместимый с OpenAI чат, ответы и /models по адресу /v2/ext/openai/v1. Для публичных моделей и моделей сообщества обычно требуется PAT; ключи с областью действия приложения работают только для ресурсов внутри этого приложения.", "cloudflare-ai": "Требуется API-токен И Account ID (можно найти на dash.cloudflare.com)", - "clova-studio": "__MISSING__:CLOVA Studio (HyperCLOVA X) is OpenAI-compatible on /v1/openai. OmniRoute probes /v1/openai/models and routes chat traffic to /v1/openai/chat/completions. Uses the current clovastudio.stream.ntruss.com host — the legacy clovastudio.apigw.ntruss.com endpoint is being deprecated.", + "clova-studio": "Clova Studio — (clova-studio) — Платформа AI от NAVER Cloud", "codestral": "Подключите Codestral с помощью API-ключа.", "cohere": "Пробный период: 1 000 API-запросов в месяц для тестирования, кредитная карта не требуется", "command-code": "Создайте или скопируйте API-ключ из Command Code, затем вставьте его сюда как Bearer-токен.", @@ -5856,9 +5858,9 @@ "watsonx": "Шлюз моделей watsonx предоставляет OpenAI-совместимые эндпоинты /chat/completions и /models по пути /ml/gateway/v1.", "ideogram": "Получите API-ключ на ideogram.ai/docs/api", "iflytek": "Получите API-ключ на console.xfyun.cn", - "inception": "__MISSING__:Inception Labs is OpenAI-compatible at https://api.inceptionlabs.ai/v1. mercury-2 is the first diffusion LLM (dLLM) in the catalog — 5-10x faster generation than comparable autoregressive models, with tool calling, json_mode, and structured outputs.", + "inception": "Inception — (inception) — Платформа AI с флагманскими моделями", "inference-net": "Бесплатный баланс $25 при регистрации, а также возможность получения исследовательских грантов", - "internlm": "__MISSING__:Free monthly quota ~1M input / 3M output tokens (~10 RPM)", + "internlm": "InternLM — (internlm) — Открытые языковые модели от Shanghai AI Lab", "jina-ai": "API-ключ Bearer для Jina AI rerank API.", "jina-reader": "Подключите Jina Reader с помощью API-ключа.", "kenari": "Kenari предоставляет OpenAI-совместимый эндпоинт генерации чата по адресу https://kenari.id/v1/chat/completions, а также актуальный каталог /v1/models, включающий Claude, GPT, DeepSeek, GLM, Kimi и другие модели. OmniRoute использует протокол OpenAI и выводит список моделей через сквозную передачу.", @@ -5905,7 +5907,7 @@ "perplexity": "Подключить Perplexity с помощью API-ключа.", "piapi": "Подключить PiAPI с помощью API-ключа.", "pioneer": "$75 бесплатных кредитов на использование — кредитная карта не требуется", - "plamo": "__MISSING__:PLaMo is OpenAI-compatible at https://api.platform.preferredai.jp/v1. Built by Preferred Networks and optimized for Japanese. Docs are primarily in Japanese.", + "plamo": "Plamo — (plamo) — Языковые модели для корейского языка", "poe": "Poe предоставляет совместимые с OpenAI чат и ответы на https://api.poe.com/v1, с аутентифицированной проверкой баланса на /usage/current_balance.", "pollinations": "Бесплатный уровень без ключа: openai, openai-fast, openai-large, qwen-coder, mistral, deepseek, grok, gemini-flash-lite-3.1, perplexity-fast, perplexity-reasoning. Для премиум-моделей (claude, gemini, midijourney) требуется API-ключ Pollinations с enter.pollinations.ai.", "publicai": "Требуется API-ключ — разовый кредит при регистрации, далее платно", @@ -5917,7 +5919,7 @@ "runwayml": "Генерация видео в Runway основана на задачах. OmniRoute отправляет задания text-to-video или image-to-video, опрашивает /v1/tasks/[id] и нормализует готовые видеовыходы обратно в ответ /v1/videos/generations, аналогичный OpenAI.", "sambanova": "$5 бесплатных кредитов при регистрации (срок действия 30 дней), кредитная карта не требуется", "sap": "Обнаружение моделей использует /v2/lm/scenarios/foundation-models/models на AI_API_URL. Запросы чата используют deploymentUrl/chat/completions и требуют AI-Resource-Group.", - "sarvam": "__MISSING__:Sarvam AI is OpenAI-compatible on /v1. OmniRoute probes /v1/models and routes chat traffic to /v1/chat/completions. Models are tuned for Indic languages.", + "sarvam": "Sarvam AI — (sarvam) — Индийские языковые AI модели", "scaleway": "1 млн бесплатных токенов для новых аккаунтов — соответствие EU/GDPR (Париж), Qwen3 235B и Llama 70B", "sensenova": "Получить API-ключ на platform.sensenova.cn", "siliconflow": "$1 бесплатных кредитов плюс постоянно бесплатные модели после подтверждения личности", @@ -5934,7 +5936,7 @@ "together": "Подключите Together AI с помощью API-ключа.", "tokenrouter": "TokenRouter предоставляет совместимую с OpenAI конечную точку генерации ответов чата по адресу https://api.tokenrouter.com/v1/chat/completions, а также рабочий каталог /v1/models. OmniRoute использует протокол OpenAI.", "topaz": "Подключите Topaz с помощью API-ключа.", - "typhoon": "__MISSING__:Typhoon is OpenAI-compatible on /v1. Built by SCB 10X (Thailand); typhoon-v2.5-30b-a3b-instruct is a thai-first, multilingual model.", + "typhoon": "Typhoon — (typhoon) — Тайские языковые модели", "udio": "Вставьте сессионный cookie из udio.com (авторизация Supabase)", "uncloseai": "Авторизация не требуется. API принимает любую непустую строку в качестве ключа для идентификации.", "upstage": "Подключите Upstage с помощью API-ключа.", @@ -5947,7 +5949,7 @@ "voyage-ai": "API-ключ Bearer для API эмбеддингов и ранжирования (rerank) Voyage AI.", "wafer": "API-ключ с https://wafer.ai", "wandb": "Подключите Weights & Biases Inference с помощью API-ключа.", - "writer": "__MISSING__:Writer Palmyra is OpenAI-compatible at https://api.writer.com/v1. palmyra-x5 offers a 1M-token context window.", + "writer": "Writer — (writer) — Полный стек AI для предприятий", "x5lab": "X5Lab предоставляет совместимую с OpenAI конечную точку генерации ответов чата по адресу https://api.x5lab.dev/v1/chat/completions, а также актуальный каталог /v1/models. OmniRoute использует протокол OpenAI и выводит список моделей через passthrough.", "xai": "Подключите xAI (Grok) с помощью API-ключа.", "xiaomi-mimo": "Подключите Xiaomi MiMo с помощью API-ключа.", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) — друг-основатель открытого кода OmniRoute", "cheaperInferenceSupporterBadge": "Друг открытого кода", "cheaperInferenceSupporterTooltip": "Cheaper Inference поддерживает OmniRoute как друг открытого кода", - "kimiPartnerLinkNote": "Партнерская ссылка — поддерживает OmniRoute без дополнительных затрат с вашей стороны" + "kimiPartnerLinkNote": "Партнерская ссылка — поддерживает OmniRoute без дополнительных затрат с вашей стороны", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Настройки", @@ -6125,18 +6132,18 @@ "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", "requestBodyLimitCurrent": "Current: {value}", - "cacheConfigLoadFailed": "__MISSING__:Failed to load cache settings", - "cacheConfigSaveSuccess": "__MISSING__:Cache settings saved", - "cacheConfigSaveFailed": "__MISSING__:Failed to save cache settings", - "modelCatalogTtlWholeNumberError": "__MISSING__:Use a whole number", - "modelCatalogTtlMinimumError": "__MISSING__:Minimum is {min} ms", - "modelCatalogTtlMaximumError": "__MISSING__:Maximum is {max} ms", - "modelCatalogCacheTtl": "__MISSING__:Model Catalog Cache TTL", - "modelCatalogCacheTtlDescription": "__MISSING__:How long model catalog responses are cached before refreshing", - "modelCatalogCacheTtlLabel": "__MISSING__:Model catalog cache TTL in milliseconds", - "modelCatalogCacheTtlSaving": "__MISSING__:Saving...", - "modelCatalogCacheTtlSave": "__MISSING__:Save", - "modelCatalogCacheTtlCurrent": "__MISSING__:Current: {value} ms", + "cacheConfigLoadFailed": "Не удалось загрузить конфигурацию кэша", + "cacheConfigSaveSuccess": "Конфигурация кэша сохранена", + "cacheConfigSaveFailed": "Не удалось сохранить конфигурацию кэша", + "modelCatalogTtlWholeNumberError": "TTL должен быть целым числом", + "modelCatalogTtlMinimumError": "TTL должен быть больше 0", + "modelCatalogTtlMaximumError": "TTL не может быть больше 7 дней", + "modelCatalogCacheTtl": "TTL кэша каталога моделей", + "modelCatalogCacheTtlDescription": "Как долго кэшировать каталог моделей (в секундах)", + "modelCatalogCacheTtlLabel": "TTL кэша", + "modelCatalogCacheTtlSaving": "Сохранение…", + "modelCatalogCacheTtlSave": "Сохранить", + "modelCatalogCacheTtlCurrent": "Текущий TTL: {ttl} сек", "mitmProxy": "МИТМ-прокси", "pricing": "Цены", "storage": "Хранение", @@ -6790,7 +6797,7 @@ "howPricingWorks": "Как работает ценообразование", "cacheWrite": "Запись в кэш", "unsaved": "несохраненный", - "resetDefaults": "__MISSING__:Reset defaults", + "resetDefaults": "Сбросить настройки по умолчанию", "saveProvider": "Сохранить поставщика", "model": "Модель", "models": "модели", @@ -6970,13 +6977,13 @@ "compressionPreserveSystemNever": "Никогда", "compressionLiveZoneTitle": "Live Zone с выравниванием по кэшу", "compressionLiveZoneDesc": "Сохранять сжатый префикс диалога неизменным и обрабатывать только вновь добавленные элементы.", - "compressionExclusionsTitle": "__MISSING__:Compression Exclusions", - "compressionExclusionsDesc": "__MISSING__:Model ids or provider/model patterns that must never be compressed. `*` is the only wildcard (e.g. `openai/*`, `*embedding*`). A matching request passes through byte-identical — no compression engine runs.", - "compressionExclusionsPlaceholder": "__MISSING__:One pattern per line, e.g.\nopenai/text-embedding-3-large\nanthropic/*", - "compressionExclusionsSave": "__MISSING__:Save", - "compressionExclusionsSaved": "__MISSING__:Saved", - "compressionExclusionsCount": "__MISSING__:{count, plural, one {# exclusion} other {# exclusions}} configured", - "compressionExclusionsEmpty": "__MISSING__:No exclusions configured — every model/endpoint is eligible for compression (default behavior).", + "compressionExclusionsTitle": "Исключения сжатия", + "compressionExclusionsDesc": "Список endpoint'ов, для которых сжатие пропускается", + "compressionExclusionsPlaceholder": "напр. groq/*, claude-*", + "compressionExclusionsSave": "Save", + "compressionExclusionsSaved": "Saved", + "compressionExclusionsCount": "{count, plural, one {# exclusion} other {# exclusions}} configured", + "compressionExclusionsEmpty": "No exclusions configured — every model/endpoint is eligible for compression (default behavior).", "compressionCavemanConfig": "Caveman Engine Configuration", "compressionCavemanConfigDesc": "Fine-tune the rule-based compression engine", "compressionCavemanPanelHint": "Включение/выключение и уровень настраиваются на панели:", @@ -7812,10 +7819,6 @@ "label": "Минимальное число строк для компактизации", "description": "Минимальное количество строк в однородном массиве JSON, необходимое для запуска табличной компактизации. По умолчанию: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Сохранять системный промпт" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Минимальная длина сообщения" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -9775,23 +9782,23 @@ "deviceCodeVerificationUrl": "URL-адрес подтверждения", "deviceCodeYourCode": "Ваш код", "deviceCodeWaiting": "Ожидание авторизации...", - "googleLoopbackTitle": "__MISSING__:Google sign-in can't complete from this address", - "googleLoopbackWhatHappens": "__MISSING__:Google only releases the authorization code once {redirectUri} is reachable from the browser that approves the sign-in. Here that address points at this computer, not at the OmniRoute server — so the consent screen hangs instead of redirecting, and there is no callback URL to copy.", - "googleLoopbackRecommended": "__MISSING__:Recommended — run this on your own computer, then paste the result below:", - "googleLoopbackHelperNote": "__MISSING__:It opens the Google consent locally (where 127.0.0.1 works) and prints a one-line omniroute-cred-v1.… blob. Paste that blob into the Step 2 field below — it accepts a credential blob as well as a callback URL.", - "googleLoopbackTunnelLabel": "__MISSING__:Or forward the dashboard port over SSH and reload OmniRoute through the tunnel:", - "googleLoopbackTunnelNote": "__MISSING__:Replace {userPlaceholder} with your SSH username, keep the terminal open, then open {localUrl} and connect again from there.", - "googleLoopbackHeadlessAlt": "__MISSING__:For fully headless use with no local callback at all, configure your own Google OAuth credentials plus a public base URL.", + "googleLoopbackTitle": "Google sign-in can't complete from this address", + "googleLoopbackWhatHappens": "Google only releases the authorization code once {redirectUri} is reachable from the browser that approves the sign-in. Here that address points at this computer, not at the OmniRoute server — so the consent screen hangs instead of redirecting, and there is no callback URL to copy.", + "googleLoopbackRecommended": "Recommended — run this on your own computer, then paste the result below:", + "googleLoopbackHelperNote": "It opens the Google consent locally (where 127.0.0.1 works) and prints a one-line omniroute-cred-v1.… blob. Paste that blob into the Step 2 field below — it accepts a credential blob as well as a callback URL.", + "googleLoopbackTunnelLabel": "Or forward the dashboard port over SSH and reload OmniRoute through the tunnel:", + "googleLoopbackTunnelNote": "Replace {userPlaceholder} with your SSH username, keep the terminal open, then open {localUrl} and connect again from there.", + "googleLoopbackHeadlessAlt": "For fully headless use with no local callback at all, configure your own Google OAuth credentials plus a public base URL.", "remoteAccessInfo": "Удаленный доступ. Поскольку вы получаете доступ к OmniRoute удаленно, после авторизации вы увидите страницу с ошибкой (localhost не найден). Это нормально — просто скопируйте полный URL-адрес из адресной строки браузера и вставьте его ниже.", - "loopbackMismatchTitle": "__MISSING__:Sign-in can't complete from this address", - "loopbackMismatchWhatHappened": "__MISSING__:What's happening", - "loopbackMismatchExplanation": "__MISSING__:After you approve the login, {providerName} always sends the browser back to {redirectUri}. That address points at the computer running this browser, not at the OmniRoute server — so the authorization code never reaches OmniRoute and the provider fails the sign-in without showing an error.", - "loopbackMismatchHowToFix": "__MISSING__:How to fix it", - "loopbackMismatchStep1": "__MISSING__:On this computer, open a terminal and start an SSH tunnel to the OmniRoute server:", - "loopbackMismatchStep1Note": "__MISSING__:Replace {userPlaceholder} with your SSH username. Keep this terminal open until the connection shows as active — both ports are needed: one serves the dashboard, the other receives the callback.", - "loopbackMismatchStep2": "__MISSING__:In this browser, reopen OmniRoute through the tunnel:", - "loopbackMismatchStep3": "__MISSING__:Then connect {providerName} again from the new tab. The callback now reaches the server and the login completes normally.", - "loopbackMismatchAlternative": "__MISSING__:No SSH access? If this provider offers a token import tab, connect with a token instead — that path doesn't use a loopback callback.", + "loopbackMismatchTitle": "Sign-in can't complete from this address", + "loopbackMismatchWhatHappened": "What's happening", + "loopbackMismatchExplanation": "After you approve the login, {providerName} always sends the browser back to {redirectUri}. That address points at the computer running this browser, not at the OmniRoute server — so the authorization code never reaches OmniRoute and the provider fails the sign-in without showing an error.", + "loopbackMismatchHowToFix": "How to fix it", + "loopbackMismatchStep1": "On this computer, open a terminal and start an SSH tunnel to the OmniRoute server:", + "loopbackMismatchStep1Note": "Replace {userPlaceholder} with your SSH username. Keep this terminal open until the connection shows as active — both ports are needed: one serves the dashboard, the other receives the callback.", + "loopbackMismatchStep2": "In this browser, reopen OmniRoute through the tunnel:", + "loopbackMismatchStep3": "Then connect {providerName} again from the new tab. The callback now reaches the server and the login completes normally.", + "loopbackMismatchAlternative": "No SSH access? If this provider offers a token import tab, connect with a token instead — that path doesn't use a loopback callback.", "step1OpenUrl": "Шаг 1. Откройте этот URL-адрес в своем браузере.", "copy": "Копировать", "step2PasteCallback": "Шаг 2. Вставьте сюда URL обратного вызова или код авторизации.", @@ -10195,6 +10202,8 @@ "copied": "Скопировано!", "run": "Запустить", "running": "Запуск...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Ответ", "tunnel": "Туннель", "send": "Отправить", @@ -11380,7 +11389,7 @@ } }, "pageTitle": "Навыки агента", - "pageSubtitle": "__MISSING__:Teach your agent to operate OmniRoute — 23 API areas + 21 CLI families", + "pageSubtitle": "Teach your agent to operate OmniRoute — 23 API areas + 21 CLI families", "conceptCard": { "agent": { "title": "Навыки агента — Исходящие", @@ -11737,7 +11746,7 @@ "danger": "Опасность", "requiresRestart": "Требуется перезапуск", "source": "Источник", - "ccDiscoveryAliasesEnvWarning": "__MISSING__:Active via environment variable (EXPOSE_CC_DISCOVERY_ALIASES) — this overrides any dashboard toggle below.", + "ccDiscoveryAliasesEnvWarning": "Active via environment variable (EXPOSE_CC_DISCOVERY_ALIASES) — this overrides any dashboard toggle below.", "resetFlag": "Сбросить {label} до значения по умолчанию", "reset": "Сбросить", "loadFailed": "Не удалось загрузить флаги функций", diff --git a/src/i18n/messages/sk.json b/src/i18n/messages/sk.json index ee9c62f677..78d068873f 100644 --- a/src/i18n/messages/sk.json +++ b/src/i18n/messages/sk.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Neboli pridané žiadne nové modely (všetky už existujú).", "importDoneCount": "✓ Hotovo! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Vyskytla sa neočakávaná chyba", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "správy", "responsesPath": "odozvy", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) je zakladajúci open source priateľ OmniRoute", "cheaperInferenceSupporterBadge": "Priateľ open source", "cheaperInferenceSupporterTooltip": "Cheaper Inference podporuje OmniRoute ako priateľ open source", - "kimiPartnerLinkNote": "Partnerský odkaz — podporuje OmniRoute bez akýchkoľvek dodatočných nákladov pre vás" + "kimiPartnerLinkNote": "Partnerský odkaz — podporuje OmniRoute bez akýchkoľvek dodatočných nákladov pre vás", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Nastavenia", @@ -7812,10 +7819,6 @@ "label": "Minimálny počet riadkov na zhustenie", "description": "Minimálny počet riadkov v homogénnom JSON poli potrebný na spustenie tabuľkového zhustenia. Predvolené: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Zachovať systémový prompt" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Minimálna dĺžka správy" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Skopírované!", "run": "Spustiť", "running": "Spúšťa sa...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Odpoveď", "tunnel": "Tunel", "send": "Odoslať", diff --git a/src/i18n/messages/sv.json b/src/i18n/messages/sv.json index ba6bbbe891..69aad2ad43 100644 --- a/src/i18n/messages/sv.json +++ b/src/i18n/messages/sv.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Inga nya modeller har lagts till (alla finns redan).", "importDoneCount": "✓ Klart! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Ett oväntat fel inträffade", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "meddelanden", "responsesPath": "svar", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) är OmniRoutes grundande öppen källkod-vän", "cheaperInferenceSupporterBadge": "Öppen källkod-vän", "cheaperInferenceSupporterTooltip": "Cheaper Inference stödjer OmniRoute som öppen källkod-vän", - "kimiPartnerLinkNote": "Partnerlänk — stöder OmniRoute utan extra kostnad för dig" + "kimiPartnerLinkNote": "Partnerlänk — stöder OmniRoute utan extra kostnad för dig", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Inställningar", @@ -7812,10 +7819,6 @@ "label": "Minsta antal rader att komprimera", "description": "Minsta antal rader i en homogen JSON-array som krävs för att utlösa tabellkomprimering. Standard: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Bevara systemprompt" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Minsta meddelandelängd" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Kopierat!", "run": "Kör", "running": "Körs...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Svar", "tunnel": "Tunnel", "send": "Skicka", diff --git a/src/i18n/messages/sw.json b/src/i18n/messages/sw.json index a3165d7dd8..3f4d69b9b5 100644 --- a/src/i18n/messages/sw.json +++ b/src/i18n/messages/sw.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "No new models were added (all already exist).", "importDoneCount": "✓ Done! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "An unexpected error occurred", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "messages", "responsesPath": "responses", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) ni rafiki mwanzilishi wa chanzo huria wa OmniRoute", "cheaperInferenceSupporterBadge": "Rafiki wa Chanzo Huria", "cheaperInferenceSupporterTooltip": "Cheaper Inference inaunga mkono OmniRoute kama Rafiki wa Chanzo Huria", - "kimiPartnerLinkNote": "Kiungo cha mshirika — kinaunga mkono OmniRoute bila gharama ya ziada kwako" + "kimiPartnerLinkNote": "Kiungo cha mshirika — kinaunga mkono OmniRoute bila gharama ya ziada kwako", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Settings", @@ -7812,10 +7819,6 @@ "label": "Kiwango cha chini cha safu mlalo za kubana", "description": "Kiwango cha chini cha safu mlalo katika safu ya JSON inayofanana inayohitajika ili kuanzisha ubana wa jedwali. Chaguo-msingi: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Hifadhi kidokezo cha mfumo" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Urefu wa chini wa ujumbe" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Imenakiliwa!", "run": "Endesha", "running": "Inaendesha...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Jibu", "tunnel": "Tunnel", "send": "Tuma", diff --git a/src/i18n/messages/ta.json b/src/i18n/messages/ta.json index 5187bea668..3d305c9bce 100644 --- a/src/i18n/messages/ta.json +++ b/src/i18n/messages/ta.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "No new models were added (all already exist).", "importDoneCount": "✓ Done! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "An unexpected error occurred", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "messages", "responsesPath": "responses", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) என்பது OmniRoute இன் நிறுவன திறந்த மூல நண்பர் ஆகும்", "cheaperInferenceSupporterBadge": "திறந்த மூல நண்பர்", "cheaperInferenceSupporterTooltip": "Cheaper Inference ஒரு திறந்த மூல நண்பராக OmniRoute-ஐ ஆதரிக்கிறது", - "kimiPartnerLinkNote": "பங்குதாரர் இணைப்பு — உங்களுக்கு எந்த கூடுதல் கட்டணமும் இன்றி OmniRoute-ஐ ஆதரிக்கிறது" + "kimiPartnerLinkNote": "பங்குதாரர் இணைப்பு — உங்களுக்கு எந்த கூடுதல் கட்டணமும் இன்றி OmniRoute-ஐ ஆதரிக்கிறது", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Settings", @@ -7812,10 +7819,6 @@ "label": "சுருக்குவதற்கான குறைந்தபட்ச வரிசைகள்", "description": "அட்டவணை சுருக்கத்தைத் தூண்டுவதற்கு ஒரே மாதிரியான JSON வரிசையில் தேவைப்படும் குறைந்தபட்ச வரிசைகள். இயல்புநிலை: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "சிஸ்டம் பிராம்ப்ட்டைப் பாதுகாக்கவும்" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "குறைந்தபட்ச செய்தி நீளம்" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "நகலெடுக்கப்பட்டது!", "run": "இயக்கு", "running": "இயங்குகிறது...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "பதில்", "tunnel": "டன்னல்", "send": "அனுப்பு", diff --git a/src/i18n/messages/te.json b/src/i18n/messages/te.json index a4de572e49..7b86bc2b28 100644 --- a/src/i18n/messages/te.json +++ b/src/i18n/messages/te.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "No new models were added (all already exist).", "importDoneCount": "✓ Done! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "An unexpected error occurred", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "messages", "responsesPath": "responses", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) అనేది OmniRoute యొక్క వ్యవస్థాపక ఓపెన్ సోర్స్ మిత్రుడు", "cheaperInferenceSupporterBadge": "ఓపెన్ సోర్స్ స్నేహితుడు", "cheaperInferenceSupporterTooltip": "Cheaper Inference ఓపెన్ సోర్స్ స్నేహితురాలిగా OmniRoute కు మద్దతు ఇస్తోంది", - "kimiPartnerLinkNote": "భాగస్వామి లింక్ — మీకు ఎటువంటి అదనపు ఖర్చు లేకుండా OmniRouteకు మద్దతు ఇస్తుంది" + "kimiPartnerLinkNote": "భాగస్వామి లింక్ — మీకు ఎటువంటి అదనపు ఖర్చు లేకుండా OmniRouteకు మద్దతు ఇస్తుంది", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Settings", @@ -7812,10 +7819,6 @@ "label": "కంపాక్ట్ చేయడానికి కనీస అడ్డు వరుసలు", "description": "టేబులర్ కంపాక్షన్‌ను ట్రిగ్గర్ చేయడానికి సజాతీయ JSON అరేలో అవసరమైన కనీస అడ్డు వరుసలు. డిఫాల్ట్: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "సిస్టమ్ ప్రాంప్ట్‌ను భద్రపరచండి" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "కనీస సందేశ నిడివి" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "కాపీ చేయబడింది!", "run": "రన్ చేయండి", "running": "రన్ అవుతోంది...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "ప్రతిస్పందన", "tunnel": "టన్నెల్", "send": "పంపండి", diff --git a/src/i18n/messages/th.json b/src/i18n/messages/th.json index 81f03e11c3..5681eed0e9 100644 --- a/src/i18n/messages/th.json +++ b/src/i18n/messages/th.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "ไม่มีการเพิ่มโมเดลใหม่ (มีอยู่แล้วทั้งหมด)", "importDoneCount": "✓ เสร็จแล้ว! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "เกิดข้อผิดพลาดที่ไม่คาดคิด", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "ข้อความ", "responsesPath": "การตอบสนอง", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) คือเพื่อนโอเพนซอร์สผู้ก่อตั้งของ OmniRoute", "cheaperInferenceSupporterBadge": "เพื่อนโอเพนซอร์ส", "cheaperInferenceSupporterTooltip": "Cheaper Inference สนับสนุน OmniRoute ในฐานะเพื่อนโอเพนซอร์ส", - "kimiPartnerLinkNote": "ลิงก์พันธมิตร — สนับสนุน OmniRoute โดยไม่มีค่าใช้จ่ายเพิ่มเติมสำหรับคุณ" + "kimiPartnerLinkNote": "ลิงก์พันธมิตร — สนับสนุน OmniRoute โดยไม่มีค่าใช้จ่ายเพิ่มเติมสำหรับคุณ", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "การตั้งค่า", @@ -7812,10 +7819,6 @@ "label": "จำนวนแถวขั้นต่ำที่จะกระชับข้อมูล", "description": "จำนวนแถวขั้นต่ำในอาร์เรย์ JSON ที่เป็นเนื้อเดียวกันซึ่งจำเป็นต่อการทริกเกอร์การกระชับข้อมูลแบบตาราง ค่าเริ่มต้น: 8" }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "คงพรอมต์ระบบไว้" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "ความยาวข้อความขั้นต่ำ" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "คัดลอกแล้ว!", "run": "รัน", "running": "กำลังรัน...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "การตอบกลับ", "tunnel": "ทันเนล", "send": "ส่ง", diff --git a/src/i18n/messages/tr.json b/src/i18n/messages/tr.json index 00cd54af41..81aaa03a1b 100644 --- a/src/i18n/messages/tr.json +++ b/src/i18n/messages/tr.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Yeni model eklenmedi (tümü zaten var).", "importDoneCount": "✓ Bitti! {count, plural, one {# model içe aktarıldı.} other {# model içe aktarıldı.}}", "unexpectedErrorOccurred": "Beklenmeyen bir hata oluştu", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# bağlantı} other {# bağlantı}}", "messagesPath": "messages", "responsesPath": "responses", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI), OmniRoute'un kurucu açık kaynak dostu", "cheaperInferenceSupporterBadge": "Açık Kaynak Dostu", "cheaperInferenceSupporterTooltip": "Cheaper Inference, OmniRoute'u Açık Kaynak Dostu olarak destekliyor", - "kimiPartnerLinkNote": "Ortaklık bağlantısı — size hiçbir ek ücret ödetmeden OmniRoute'u destekler" + "kimiPartnerLinkNote": "Ortaklık bağlantısı — size hiçbir ek ücret ödetmeden OmniRoute'u destekler", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Ayarlar", @@ -7812,10 +7819,6 @@ "label": "Sıkıştırılacak minimum satır sayısı", "description": "Tablosal sıkıştırmayı tetiklemek için homojen bir JSON dizisinde gereken minimum satır sayısı. Varsayılan: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Sistem istemini koru" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Minimum mesaj uzunluğu" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Kopyalandı!", "run": "Çalıştır", "running": "Çalıştırılıyor...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Yanıt", "tunnel": "Tünel", "send": "Gönder", diff --git a/src/i18n/messages/uk-UA.json b/src/i18n/messages/uk-UA.json index bc5082da8c..a1231b6840 100644 --- a/src/i18n/messages/uk-UA.json +++ b/src/i18n/messages/uk-UA.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "Нові моделі не додано (усі вже є).", "importDoneCount": "✓ Готово! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "Сталася неочікувана помилка", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "повідомлення", "responsesPath": "відповіді", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) — друг-засновник відкритого коду OmniRoute", "cheaperInferenceSupporterBadge": "Друг відкритого коду", "cheaperInferenceSupporterTooltip": "Cheaper Inference підтримує OmniRoute як друг відкритого коду", - "kimiPartnerLinkNote": "Партнерське посилання — підтримує OmniRoute без додаткових витрат для вас" + "kimiPartnerLinkNote": "Партнерське посилання — підтримує OmniRoute без додаткових витрат для вас", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Налаштування", @@ -7812,10 +7819,6 @@ "label": "Мінімальна кількість рядків для компактності", "description": "Мінімальна кількість рядків в однорідному масиві JSON, необхідна для запуску табличного ущільнення. За замовчуванням: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Зберігати системний промпт" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "Мінімальна довжина повідомлення" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "Скопійовано!", "run": "Запустити", "running": "Виконання...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "Відповідь", "tunnel": "Тунель", "send": "Надіслати", diff --git a/src/i18n/messages/ur.json b/src/i18n/messages/ur.json index 755d3929d0..d4be641d7b 100644 --- a/src/i18n/messages/ur.json +++ b/src/i18n/messages/ur.json @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "No new models were added (all already exist).", "importDoneCount": "✓ Done! {count, plural, one {# model imported.} other {# models imported.}}", "unexpectedErrorOccurred": "An unexpected error occurred", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# connection} other {# connections}}", "messagesPath": "messages", "responsesPath": "responses", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) OmniRoute کا بانی اوپن سورس دوست ہے", "cheaperInferenceSupporterBadge": "اوپن سورس دوست", "cheaperInferenceSupporterTooltip": "‏Cheaper Inference اوپن سورس دوست کے طور پر OmniRoute کی حمایت کرتی ہے", - "kimiPartnerLinkNote": "پارٹنر لنک — آپ کے لیے بغیر کسی اضافی قیمت کے OmniRoute کو سپورٹ کرتا ہے" + "kimiPartnerLinkNote": "پارٹنر لنک — آپ کے لیے بغیر کسی اضافی قیمت کے OmniRoute کو سپورٹ کرتا ہے", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "Settings", @@ -7812,10 +7819,6 @@ "label": "کمپیکٹ کرنے کے لیے کم از کم قطاریں", "description": "ٹیبلر کمپیکشن کو متحرک کرنے کے لیے ایک یکساں JSON اری میں مطلوبہ کم از کم قطاریں۔ ڈیفالٹ: 8۔" }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "سسٹم پرامپٹ کو محفوظ رکھیں" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "پیغام کی کم از کم لمبائی" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "کاپی ہو گیا!", "run": "چلائیں", "running": "چل رہا ہے...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "جواب", "tunnel": "ٹنل", "send": "بھیجیں", diff --git a/src/i18n/messages/vi.json b/src/i18n/messages/vi.json index d4b3f16030..0a37b8613a 100644 --- a/src/i18n/messages/vi.json +++ b/src/i18n/messages/vi.json @@ -937,7 +937,7 @@ "disabled": "Đã tắt", "featureFlagOmnirouteEmergencyFallbackDescription": "Định tuyến các yêu cầu đã hết ngân sách đến nhà cung cấp/mô hình dự phòng khẩn cấp miễn phí.", "featureFlagArenaEloSyncEnabledDescription": "Bật đồng bộ ELO định kỳ từ bảng xếp hạng Arena AI để xếp hạng năng lực của mô hình.", - "featureFlagExposeCcDiscoveryAliasesDescription": "Công bố các id phản chiếu claude/<provider>/<model> trên /v1/models để tính năng khám phá mô hình qua gateway của Claude Code liệt kê được các mô hình không phải Claude. Cảnh báo: khi bật ở phạm vi toàn cục, số mục trong danh mục tăng gấp đôi với mọi client.", + "featureFlagExposeCcDiscoveryAliasesDescription": "Quảng bá các id phản chiếu claude// trên /v1/models để tính năng khám phá mô hình qua gateway của Claude Code liệt kê được các mô hình không phải Claude. Cảnh báo: khi bật ở phạm vi toàn cục, số mục trong danh mục tăng gấp đôi với mọi client.", "sidebar": { "home": "Trang chủ", "dashboard": "Trang tổng quan", @@ -2516,7 +2516,7 @@ "always": "Luôn bật" }, "ccDiscoveryInfoButton": "Cách bật khám phá mô hình trong Claude Code", - "ccDiscoveryInfoTooltip": "Công bố các mô hình không phải Claude dưới dạng id phản chiếu claude/<provider>/<model> để tính năng khám phá mô hình qua gateway của Claude Code có thể liệt kê chúng. Khi bật ở phạm vi toàn cục, số mục trong danh mục tăng gấp đôi với mọi client.", + "ccDiscoveryInfoTooltip": "Quảng bá các mô hình không phải Claude dưới dạng id phản chiếu claude// để tính năng khám phá mô hình qua gateway của Claude Code có thể liệt kê chúng. Khi bật ở phạm vi toàn cục, số mục trong danh mục tăng gấp đôi với mọi client.", "ccDiscoveryInfoLink": "Mở Feature Flags", "ccOnboardingTitle": "settings.json cho việc khám phá mô hình qua gateway", "ccOnboardingCopy": "Sao chép", @@ -5206,7 +5206,7 @@ "interceptionLoadError": "Không thể tải cài đặt chặn: {error}", "interceptionSaveError": "Không thể lưu cài đặt chặn: {error}", "ccAliasSectionTitle": "Hiển thị trong Claude Code (claude/…)", - "ccAliasSectionHint": "Công bố các mô hình của nhà cung cấp này dưới dạng id phản chiếu claude/<provider>/<model> để tính năng khám phá mô hình qua gateway của Claude Code có thể liệt kê chúng. Mặc định tắt — bật lên sẽ nhân đôi số mục trong danh mục với mọi client.", + "ccAliasSectionHint": "Quảng bá các mô hình của nhà cung cấp này dưới dạng id phản chiếu claude// để tính năng khám phá mô hình qua gateway của Claude Code có thể liệt kê chúng. Mặc định tắt — bật lên sẽ nhân đôi số mục trong danh mục với mọi client.", "ccAliasProviderLevelLabel": "Mặc định của nhà cung cấp", "ccAliasModelOverridesLabel": "Ghi đè theo từng mô hình", "ccAliasModelOverrideAriaLabel": "Ghi đè cho {modelId}", @@ -6032,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) là người bạn mã nguồn mở sáng lập của OmniRoute", "cheaperInferenceSupporterBadge": "Người bạn mã nguồn mở", "cheaperInferenceSupporterTooltip": "Cheaper Inference hỗ trợ OmniRoute với tư cách là người bạn mã nguồn mở", - "kimiPartnerLinkNote": "Partner link — supports OmniRoute at no extra cost to you" + "kimiPartnerLinkNote": "Partner link — supports OmniRoute at no extra cost to you", + "anonymousFallbackTitle": "Dự phòng ẩn danh", + "anonymousFallbackDesc": "Khi tất cả kết nối đã cấu hình đều cạn kiệt (hạn ngạch, tín dụng hoặc hết hạn), hãy tạm thời sử dụng tầng không cần khóa của nhà cung cấp này. Tắt tùy chọn này để bỏ qua nhà cung cấp thay vì gửi yêu cầu ẩn danh — khuyến nghị khi tầng không cần khóa từ chối các yêu cầu đó (401).", + "anonymousFallbackEnabled": "Đã bật dự phòng ẩn danh cho {provider}", + "anonymousFallbackDisabled": "Đã tắt dự phòng ẩn danh cho {provider} — các kết nối đã cạn kiệt sẽ bỏ qua nhà cung cấp này", + "anonymousFallbackUpdateFailed": "Không thể cập nhật cài đặt dự phòng ẩn danh" }, "settings": { "title": "Cài đặt", @@ -7814,10 +7819,6 @@ "label": "Số hàng tối thiểu để nén", "description": "Số hàng tối thiểu trong một mảng JSON đồng nhất để kích hoạt nén dạng bảng. Mặc định: 8." }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "Giữ nguyên prompt hệ thống" }, @@ -7841,6 +7842,10 @@ }, "minMessageLength": { "label": "Độ dài tin nhắn tối thiểu" + }, + "compressToolResults": { + "label": "Chủ động rút gọn kết quả công cụ dài", + "description": "Rút gọn các kết quả công cụ dài hơn 2.000 ký tự trong quá trình nén Lite. Cơ chế bảo vệ tràn khẩn cấp vẫn có thể cắt bớt nội dung khi ngữ cảnh vượt quá ngân sách của mô hình." } }, "engineFields": { diff --git a/src/i18n/messages/zh-CN.json b/src/i18n/messages/zh-CN.json index 7e0fbfa1c6..d6b6f54191 100644 --- a/src/i18n/messages/zh-CN.json +++ b/src/i18n/messages/zh-CN.json @@ -1055,7 +1055,7 @@ "combosLive": "Combo Studio", "combosLiveSubtitle": "实时路由级联", "compressionStudio": "Compression Studio", - "compressionExclusions": "__MISSING__:Exclusions", + "compressionExclusions": "排除规则", "contextSettingsSubtitle": "全局默认值", "contextHeadroomSubtitle": "表格压缩", "contextSessionDedupSubtitle": "跨轮次去重", @@ -1066,7 +1066,7 @@ "contextUltraSubtitle": "启发式剪枝", "contextOmniglyphSubtitle": "上下文作为图像", "compressionStudioSubtitle": "实时引擎级联", - "compressionExclusionsSubtitle": "__MISSING__:Per-model/endpoint bypass", + "compressionExclusionsSubtitle": "按模型/端点绕过", "chaosConfigSubtitle": "多模型并行执行", "routingSection": "路由", "protocolsSection": "协议", @@ -3730,7 +3730,7 @@ "modelsCount": "{count, plural, one {# 个模型} other {# 个模型}}", "sectionTitle": "集成入口", "sectionDescription": "OpenAI 兼容 API 与操作协议端点", - "tabApis": "__MISSING__:APIs", + "tabApis": "OpenAI兼容API", "tabProtocols": "协议", "tabsAria": "端点分区", "protocolsTitle": "协议", @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "没有添加新模型(全部已存在)。", "importDoneCount": "✓ 完成!{count, plural, one {已导入 # 个模型。} other {已导入 # 个模型。}}", "unexpectedErrorOccurred": "发生意外错误", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# 个连接} other {# 个连接}}", "messagesPath": "messages", "responsesPath": "responses", @@ -5449,8 +5451,8 @@ "t3ChatWebCookieHint": "打开 t3.chat → 开发工具 → 应用程序 → 本地存储 → https://t3.chat,复制“凸会话 ID”。然后打开 DevTools → Network,从任何聊天请求中复制完整的 Cookie 标头。将这两个值粘贴到下面的字段中。", "t3ChatWebCookiePlaceholder": "凸会话 ID=abc123...", "grokWebCookieHint": "从 Grok Web 会话复制 Cookie。", - "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", - "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", + "blockClaudeExtraUsageDescription": "隐藏部分供应商返回的重复Claude额外用量记录,避免和主token统计重复。", + "blockClaudeExtraUsageLabel": "屏蔽重复Claude用量", "disableCoolingDescription": "跳过瞬态冷却,以便此连接在发生可恢复错误后仍符合条件(被禁/过期等终态仍适用)。", "disableCoolingLabel": "禁用此连接的冷却", "bulkPasteAdded": "{count, plural, one {已添加 1 个 key} other {已添加 # 个 key}}", @@ -5637,13 +5639,13 @@ "importGrokAuth": "导入 Grok Build 身份验证", "zedImportTitle": "从 Zed 钥匙串导入", "zedImportDescription": "发现 Zed IDE 存储在操作系统钥匙串中的 AI 提供者凭据(OpenAI、Anthropic、Google、Mistral、xAI)并将其导入为连接。此机器上必须安装 Zed IDE。", - "zedImportButton": "__MISSING__:Import from Zed", - "zedImportFailed": "__MISSING__:Zed import failed", + "zedImportButton": "从Zed导入", + "zedImportFailed": "Zed导入失败", "zedImportHint": "从 Zed 配置中导入 Provider。", "zedImportNetworkError": "Zed 导入网络错误", "zedImportNone": "没有可从 Zed 导入的内容", - "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", - "zedImporting": "__MISSING__:Importing…", + "zedImportSuccess": "Zed导入成功", + "zedImporting": "正在从Zed导入", "zedNoCredentials": "在钥匙串中未找到 Zed 凭据", "zedUnsupportedCredentials": "找到 {count} 个钥匙串凭据,但没有与支持的提供者匹配的凭据", "zedManualTitle": "手动导入令牌", @@ -5790,7 +5792,7 @@ "bailian-coding-plan": "使用 API 密钥连接阿里巴巴编码计划。", "bedrock": "原生 Bedrock 集成:模型发现使用 Bedrock 基础模型和推理配置文件,而聊天使用区域 Bedrock Runtime Converse/ConverseStream API。", "anthropic": "使用 API 密钥连接 Anthropic。", - "ant-ling": "__MISSING__:Register and create an API key at the Ant Ling API console (https://chat.ant-ling.com/open), then paste it here. OmniRoute routes chat traffic to https://api.ant-ling.com/v1/chat/completions; the provider is OpenAI-compatible and also exposes an Anthropic-compatible surface.", + "ant-ling": "使用API Key连接Ant-Ling。", "api-airforce": "从 https://panel.api.airforce 获取您的 API 密钥 — 兼容 OpenAI 的端点位于 https://api.airforce/v1", "arcee-ai": "在 arcee.ai 获取 API 密钥", "azure-ai": "Foundry 使用 OpenAI v1 接口,并将部署名称作为模型。OmniRoute 会将根资源 URL 规范化为 v1 chat 和 /models 端点。", @@ -5811,7 +5813,7 @@ "chutes": "Chutes 兼容 OpenAI 的网关的 Bearer API 密钥。", "clarifai": "Clarifai 在 /v2/ext/openai/v1 上公开了兼容 OpenAI 的 chat、responses 和 /models。公共/社区模型通常需要 PAT;应用范围的密钥仅适用于该应用内部的资源。", "cloudflare-ai": "需要 API Token 和 Account ID(可在 dash.cloudflare.com 找到)", - "clova-studio": "__MISSING__:CLOVA Studio (HyperCLOVA X) is OpenAI-compatible on /v1/openai. OmniRoute probes /v1/openai/models and routes chat traffic to /v1/openai/chat/completions. Uses the current clovastudio.stream.ntruss.com host — the legacy clovastudio.apigw.ntruss.com endpoint is being deprecated.", + "clova-studio": "使用API Key连接Clova Studio。", "codestral": "使用 API 密钥连接 Codestral。", "cohere": "免费试用:每月 1,000 次 API 调用用于测试,无需信用卡", "command-code": "从 Command Code 创建或复制 API 密钥,然后将其作为 Bearer 令牌粘贴在此处。", @@ -5856,9 +5858,9 @@ "watsonx": "watsonx 模型网关在 /ml/gateway/v1 下公开了兼容 OpenAI 的 /chat/completions 和 /models。", "ideogram": "在 ideogram.ai/docs/api 获取 API 密钥", "iflytek": "在 console.xfyun.cn 获取 API 密钥", - "inception": "__MISSING__:Inception Labs is OpenAI-compatible at https://api.inceptionlabs.ai/v1. mercury-2 is the first diffusion LLM (dLLM) in the catalog — 5-10x faster generation than comparable autoregressive models, with tool calling, json_mode, and structured outputs.", + "inception": "使用API Key连接Inception AI。", "inference-net": "注册即送 $25 免费额度,并提供研究资助", - "internlm": "__MISSING__:Free monthly quota ~1M input / 3M output tokens (~10 RPM)", + "internlm": "使用API Key连接InternLM。", "jina-ai": "用于 Jina AI rerank API 的 Bearer API 密钥。", "jina-reader": "使用 API 密钥连接 Jina Reader。", "kenari": "Kenari 在 https://kenari.id/v1/chat/completions 提供了兼容 OpenAI 的聊天补全端点,以及涵盖 Claude、GPT、DeepSeek、GLM、Kimi 等的实时 /v1/models 目录。OmniRoute 使用 OpenAI 协议并通过直通方式列出模型。", @@ -5905,7 +5907,7 @@ "perplexity": "使用 API 密钥连接 Perplexity。", "piapi": "使用 API 密钥连接 PiAPI。", "pioneer": "$75 免费使用额度 — 无需信用卡", - "plamo": "__MISSING__:PLaMo is OpenAI-compatible at https://api.platform.preferredai.jp/v1. Built by Preferred Networks and optimized for Japanese. Docs are primarily in Japanese.", + "plamo": "使用API Key连接Plamo。", "poe": "Poe 在 https://api.poe.com/v1 上公开了兼容 OpenAI 的 chat 和 responses,并在 /usage/current_balance 上提供经过身份验证的余额查询。", "pollinations": "免密钥免费层级:openai、openai-fast、openai-large、qwen-coder、mistral、deepseek、grok、gemini-flash-lite-3.1、perplexity-fast、perplexity-reasoning。高级模型(claude、gemini、midijourney)需要来自 enter.pollinations.ai 的 Pollinations API 密钥。", "publicai": "需要 API 密钥 — 一次性注册额度,之后付费", @@ -5917,7 +5919,7 @@ "runwayml": "Runway 视频生成基于任务。OmniRoute 提交文生视频或图生视频作业,轮询 /v1/tasks/[id],并将完成的视频输出规范化为类似 OpenAI 的 /v1/videos/generations 响应。", "sambanova": "注册即送 $5 免费额度(30 天有效期),无需信用卡", "sap": "模型发现使用 AI_API_URL 上的 /v2/lm/scenarios/foundation-models/models。Chat 请求使用 deploymentUrl/chat/completions 并需要 AI-Resource-Group。", - "sarvam": "__MISSING__:Sarvam AI is OpenAI-compatible on /v1. OmniRoute probes /v1/models and routes chat traffic to /v1/chat/completions. Models are tuned for Indic languages.", + "sarvam": "使用API Key连接Sarvam AI。", "scaleway": "新账户可获 1M 免费 Token — 符合 EU/GDPR 规范(巴黎),Qwen3 235B & Llama 70B", "sensenova": "在 platform.sensenova.cn 获取 API 密钥", "siliconflow": "身份验证后可获 $1 免费额度以及永久免费模型", @@ -5934,7 +5936,7 @@ "together": "使用 API 密钥连接 Together AI。", "tokenrouter": "TokenRouter 在 https://api.tokenrouter.com/v1/chat/completions 提供了兼容 OpenAI 的 chat completions 端点,以及可用的 /v1/models 目录。OmniRoute 使用 OpenAI 协议。", "topaz": "使用 API 密钥连接 Topaz。", - "typhoon": "__MISSING__:Typhoon is OpenAI-compatible on /v1. Built by SCB 10X (Thailand); typhoon-v2.5-30b-a3b-instruct is a thai-first, multilingual model.", + "typhoon": "使用API Key连接Typhoon AI。", "udio": "粘贴来自 udio.com 的 session cookie(Supabase 认证)", "uncloseai": "无需身份验证。API 接受任何非空字符串作为标识密钥。", "upstage": "使用 API 密钥连接 Upstage。", @@ -5947,7 +5949,7 @@ "voyage-ai": "用于 Voyage AI embeddings 和 rerank API 的 Bearer API 密钥。", "wafer": "来自 https://wafer.ai 的 API 密钥", "wandb": "使用 API 密钥连接 Weights & Biases Inference。", - "writer": "__MISSING__:Writer Palmyra is OpenAI-compatible at https://api.writer.com/v1. palmyra-x5 offers a 1M-token context window.", + "writer": "使用API Key连接Writer。", "x5lab": "X5Lab 在 https://api.x5lab.dev/v1/chat/completions 提供了兼容 OpenAI 的 chat completions 端点,以及实时的 /v1/models 目录。OmniRoute 使用 OpenAI 协议并通过直通方式列出模型。", "xai": "使用 API 密钥连接 xAI (Grok)。", "xiaomi-mimo": "使用 API 密钥连接 Xiaomi MiMo。", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi(Moonshot AI)是 OmniRoute 的创始开源好友", "cheaperInferenceSupporterBadge": "开源好友", "cheaperInferenceSupporterTooltip": "Cheaper Inference 作为开源好友支持 OmniRoute", - "kimiPartnerLinkNote": "合作伙伴链接 — 支持 OmniRoute,您无需承担额外费用" + "kimiPartnerLinkNote": "合作伙伴链接 — 支持 OmniRoute,您无需承担额外费用", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "设置", @@ -6790,7 +6797,7 @@ "howPricingWorks": "定价如何运作", "cacheWrite": "缓存写入", "unsaved": "未保存", - "resetDefaults": "__MISSING__:Reset defaults", + "resetDefaults": "重置默认值", "saveProvider": "保存提供者", "model": "模型", "models": "模型", @@ -6970,13 +6977,13 @@ "compressionPreserveSystemNever": "从不", "compressionLiveZoneTitle": "缓存对齐的活动区域", "compressionLiveZoneDesc": "保持压缩后的对话前缀稳定,仅处理新追加的项。", - "compressionExclusionsTitle": "__MISSING__:Compression Exclusions", - "compressionExclusionsDesc": "__MISSING__:Model ids or provider/model patterns that must never be compressed. `*` is the only wildcard (e.g. `openai/*`, `*embedding*`). A matching request passes through byte-identical — no compression engine runs.", - "compressionExclusionsPlaceholder": "__MISSING__:One pattern per line, e.g.\nopenai/text-embedding-3-large\nanthropic/*", - "compressionExclusionsSave": "__MISSING__:Save", - "compressionExclusionsSaved": "__MISSING__:Saved", - "compressionExclusionsCount": "__MISSING__:{count, plural, one {# exclusion} other {# exclusions}} configured", - "compressionExclusionsEmpty": "__MISSING__:No exclusions configured — every model/endpoint is eligible for compression (default behavior).", + "compressionExclusionsTitle": "压缩排除规则", + "compressionExclusionsDesc": "配置哪些模型或端点应跳过压缩。使用 * 作为通配符。", + "compressionExclusionsPlaceholder": "例如claude-opus*", + "compressionExclusionsSave": "保存排除规则", + "compressionExclusionsSaved": "排除规则已保存。", + "compressionExclusionsCount": "{count} 条规则", + "compressionExclusionsEmpty": "尚未配置排除规则—所有模型和端点均可压缩。", "compressionCavemanConfig": "Caveman 引擎配置", "compressionCavemanConfigDesc": "微调基于规则的压缩引擎", "compressionCavemanPanelHint": "其开关和级别在面板中设置:", @@ -7812,10 +7819,6 @@ "label": "压缩所需的最小行数", "description": "触发表格压缩所需的同构 JSON 数组的最小行数。默认值: 8。" }, - "compressToolResults": { - "label": "主动截断过长的工具结果", - "description": "在 Lite 压缩期间截断超过 2,000 个字符的工具结果。当上下文超出模型预算时,紧急溢出保护仍可能裁剪内容。" - }, "preserveSystemPrompt": { "label": "保留系统提示词" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "最小消息长度" + }, + "compressToolResults": { + "label": "主动截断过长的工具结果", + "description": "在 Lite 压缩期间截断超过 2,000 个字符的工具结果。当上下文超出模型预算时,紧急溢出保护仍可能裁剪内容。" } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "已复制!", "run": "运行", "running": "运行中...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "响应", "tunnel": "隧道", "send": "发送", @@ -11380,7 +11389,7 @@ } }, "pageTitle": "特工技能", - "pageSubtitle": "__MISSING__:Teach your agent to operate OmniRoute — 23 API areas + 21 CLI families", + "pageSubtitle": "教你的智能体操作OmniRoute— 22 个API区域 + 20 个CLI家族", "conceptCard": { "agent": { "title": "代理技能 — 外呼", @@ -12328,7 +12337,7 @@ "title": "连接韧性", "table": { "status": "状态", - "provider": "提供商", + "provider": "提供者", "connectionId": "连接", "authType": "认证", "backoffLevel": "退避", @@ -12378,7 +12387,7 @@ "backoffLevel": "退避级别", "remaining": "剩余", "noLockouts": "无活动锁定", - "provider": "提供商", + "provider": "提供者", "id": "ID", "authType": "认证类型", "priority": "优先级", @@ -12395,7 +12404,7 @@ }, "empty": { "title": "无连接", - "description": "提供商连接将显示在此处。" + "description": "提供者连接将显示在此处。" }, "loading": { "title": "加载中", diff --git a/src/i18n/messages/zh-TW.json b/src/i18n/messages/zh-TW.json index f8a5261460..335ba8a9c0 100644 --- a/src/i18n/messages/zh-TW.json +++ b/src/i18n/messages/zh-TW.json @@ -1055,7 +1055,7 @@ "combosLive": "Combo Studio", "combosLiveSubtitle": "即時路由串聯", "compressionStudio": "Compression Studio", - "compressionExclusions": "__MISSING__:Exclusions", + "compressionExclusions": "排除規則", "contextSettingsSubtitle": "全域預設值", "contextHeadroomSubtitle": "表格壓縮", "contextSessionDedupSubtitle": "跨輪次去重", @@ -1066,7 +1066,7 @@ "contextUltraSubtitle": "啟發式修剪", "contextOmniglyphSubtitle": "以圖像呈現上下文", "compressionStudioSubtitle": "即時引擎串聯", - "compressionExclusionsSubtitle": "__MISSING__:Per-model/endpoint bypass", + "compressionExclusionsSubtitle": "按模型/端點繞過", "chaosConfigSubtitle": "多模型並行執行", "routingSection": "路由", "protocolsSection": "協議", @@ -3730,7 +3730,7 @@ "modelsCount": "{count, plural, one {# 個模型} other {# 個模型}}", "sectionTitle": "整合入口", "sectionDescription": "OpenAI 相容 API 與操作協議端點", - "tabApis": "__MISSING__:APIs", + "tabApis": "OpenAI相容API", "tabProtocols": "協議", "tabsAria": "端點分割槽", "protocolsTitle": "協議", @@ -5073,6 +5073,8 @@ "noNewModelsAddedExisting": "沒有新增新模型(全部已存在)。", "importDoneCount": "✓ 完成!{count, plural, one {已匯入 # 個模型。} other {已匯入 # 個模型。}}", "unexpectedErrorOccurred": "發生意外錯誤", + "getApiKey": "__MISSING__:Get API key", + "getApiKeyDescription": "__MISSING__:Register or sign up for an API key", "connectionCountLabel": "{count, plural, one {# 個連線} other {# 個連線}}", "messagesPath": "messages", "responsesPath": "responses", @@ -5637,13 +5639,13 @@ "importGrokAuth": "匯入 Grok Build 驗證", "zedImportTitle": "從 Zed 鑰匙圈匯入", "zedImportDescription": "探索 Zed IDE 存放在 OS 鑰匙圈中的 AI 提供者憑證(OpenAI、Anthropic、Google、Mistral、xAI),並將其匯入為連線。此機器上必須已安裝 Zed IDE。", - "zedImportButton": "__MISSING__:Import from Zed", - "zedImportFailed": "__MISSING__:Zed import failed", + "zedImportButton": "從Zed導入", + "zedImportFailed": "Zed導入失敗", "zedImportHint": "從 Zed 設定中匯入 Provider。", "zedImportNetworkError": "Zed 匯入網路錯誤", "zedImportNone": "沒有可從 Zed 匯入的內容", - "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", - "zedImporting": "__MISSING__:Importing…", + "zedImportSuccess": "Zed導入成功", + "zedImporting": "正在從Zed導入", "zedNoCredentials": "在鑰匙圈中找不到 Zed 憑證", "zedUnsupportedCredentials": "找到 {count} 個鑰匙圈憑證,但均未匹配支援的提供者", "zedManualTitle": "手動 Token 匯入", @@ -5790,7 +5792,7 @@ "bailian-coding-plan": "使用 API 金鑰連線阿里雲通義靈碼。", "bedrock": "原生 Bedrock 整合:模型探索使用 Bedrock 基礎模型和推論設定檔,聊天則使用區域性 Bedrock Runtime Converse/ConverseStream API。", "anthropic": "使用 API 金鑰連線 Anthropic。", - "ant-ling": "__MISSING__:Register and create an API key at the Ant Ling API console (https://chat.ant-ling.com/open), then paste it here. OmniRoute routes chat traffic to https://api.ant-ling.com/v1/chat/completions; the provider is OpenAI-compatible and also exposes an Anthropic-compatible surface.", + "ant-ling": "使用API Key連接Ant-Ling。", "api-airforce": "從 https://panel.api.airforce 取得 API 金鑰 — OpenAI 相容端點為 https://api.airforce/v1", "arcee-ai": "在 arcee.ai 取得 API 金鑰", "azure-ai": "Foundry 使用 OpenAI v1 介面,以部署名稱作為模型。OmniRoute 將根資源 URL 正規化為 v1 chat 和 /models 端點。", @@ -5811,7 +5813,7 @@ "chutes": "Chutes OpenAI 相容閘道的 Bearer API 金鑰。", "clarifai": "Clarifai 在 /v2/ext/openai/v1 提供 OpenAI 相容的聊天、回應和 /models 端點。公開/社群模型通常需要 PAT;應用程式範圍的金鑰僅適用於該應用程式內的資源。", "cloudflare-ai": "需要 API Token 和 Account ID(可在 dash.cloudflare.com 找到)", - "clova-studio": "__MISSING__:CLOVA Studio (HyperCLOVA X) is OpenAI-compatible on /v1/openai. OmniRoute probes /v1/openai/models and routes chat traffic to /v1/openai/chat/completions. Uses the current clovastudio.stream.ntruss.com host — the legacy clovastudio.apigw.ntruss.com endpoint is being deprecated.", + "clova-studio": "使用API Key連接Clova Studio。", "codestral": "使用 API 金鑰連線 Codestral。", "cohere": "免費試用:每月 1,000 次 API 呼叫供測試使用,無需信用卡", "command-code": "從 Command Code 建立或複製 API 金鑰,然後在此貼上作為 Bearer token。", @@ -5856,9 +5858,9 @@ "watsonx": "watsonx 模型閘道在 /ml/gateway/v1 下提供 OpenAI 相容的 /chat/completions 和 /models 端點。", "ideogram": "在 ideogram.ai/docs/api 取得 API 金鑰", "iflytek": "在 console.xfyun.cn 取得 API 金鑰", - "inception": "__MISSING__:Inception Labs is OpenAI-compatible at https://api.inceptionlabs.ai/v1. mercury-2 is the first diffusion LLM (dLLM) in the catalog — 5-10x faster generation than comparable autoregressive models, with tool calling, json_mode, and structured outputs.", + "inception": "使用API Key連接Inception AI。", "inference-net": "註冊即贈 $25 美元免費額度,另提供研究補助金", - "internlm": "__MISSING__:Free monthly quota ~1M input / 3M output tokens (~10 RPM)", + "internlm": "使用API Key連接InternLM。", "jina-ai": "Jina AI 重新排序 API 的 Bearer API 金鑰。", "jina-reader": "使用 API 金鑰連線 Jina Reader。", "kenari": "Kenari 在 https://kenari.id/v1/chat/completions 提供 OpenAI 相容的聊天完成端點,以及涵蓋 Claude、GPT、DeepSeek、GLM、Kimi 等模型的即時 /v1/models 目錄。OmniRoute 使用 OpenAI 協定並透過透傳方式列出模型。", @@ -5905,7 +5907,7 @@ "perplexity": "使用 API 金鑰連線 Perplexity。", "piapi": "使用 API 金鑰連線 PiAPI。", "pioneer": "$75 美元免費使用額度 — 無需信用卡", - "plamo": "__MISSING__:PLaMo is OpenAI-compatible at https://api.platform.preferredai.jp/v1. Built by Preferred Networks and optimized for Japanese. Docs are primarily in Japanese.", + "plamo": "使用API Key連接Plamo。", "poe": "Poe 在 https://api.poe.com/v1 提供 OpenAI 相容的聊天和回應功能,並在 /usage/current_balance 進行認證餘額檢查。", "pollinations": "免費無需金鑰方案:openai、openai-fast、openai-large、qwen-coder、mistral、deepseek、grok、gemini-flash-lite-3.1、perplexity-fast、perplexity-reasoning。進階模型(claude、gemini、midijourney)需要從 enter.pollinations.ai 取得 Pollinations API 金鑰。", "publicai": "需要 API 金鑰 — 一次性註冊額度,之後付費", @@ -5917,7 +5919,7 @@ "runwayml": "Runway 影片生成為任務導向。OmniRoute 提交文字轉影片或圖片轉影片作業,輪詢 /v1/tasks/[id],並將完成的影片輸出正規化為類似 OpenAI 的 /v1/videos/generations 回應。", "sambanova": "註冊即贈 $5 美元免費額度(30 天有效期),無需信用卡", "sap": "模型探索使用 AI_API_URL 上的 /v2/lm/scenarios/foundation-models/models。聊天請求使用 deploymentUrl/chat/completions,並需要 AI-Resource-Group。", - "sarvam": "__MISSING__:Sarvam AI is OpenAI-compatible on /v1. OmniRoute probes /v1/models and routes chat traffic to /v1/chat/completions. Models are tuned for Indic languages.", + "sarvam": "使用API Key連接Sarvam AI。", "scaleway": "新帳戶贈送 100 萬免費 tokens — 符合歐盟/GDPR 規範(巴黎),Qwen3 235B 和 Llama 70B", "sensenova": "在 platform.sensenova.cn 取得 API 金鑰", "siliconflow": "$1 美元免費額度,身分驗證後另有永久免費模型", @@ -5934,7 +5936,7 @@ "together": "使用 API 金鑰連線 Together AI。", "tokenrouter": "TokenRouter 在 https://api.tokenrouter.com/v1/chat/completions 提供 OpenAI 相容的聊天完成端點,以及可用的 /v1/models 目錄。OmniRoute 使用 OpenAI 協定。", "topaz": "使用 API 金鑰連線 Topaz。", - "typhoon": "__MISSING__:Typhoon is OpenAI-compatible on /v1. Built by SCB 10X (Thailand); typhoon-v2.5-30b-a3b-instruct is a thai-first, multilingual model.", + "typhoon": "使用API Key連接Typhoon AI。", "udio": "貼上來自 udio.com 的 session cookie(Supabase 驗證)", "uncloseai": "無需驗證。API 接受任何非空字串作為識別金鑰。", "upstage": "使用 API 金鑰連線 Upstage。", @@ -5947,7 +5949,7 @@ "voyage-ai": "Voyage AI 嵌入向量和重新排序 API 的 Bearer API 金鑰。", "wafer": "來自 https://wafer.ai 的 API 金鑰", "wandb": "使用 API 金鑰連線 Weights & Biases Inference。", - "writer": "__MISSING__:Writer Palmyra is OpenAI-compatible at https://api.writer.com/v1. palmyra-x5 offers a 1M-token context window.", + "writer": "使用API Key連接Writer。", "x5lab": "X5Lab 在 https://api.x5lab.dev/v1/chat/completions 提供 OpenAI 相容的聊天完成端點,以及即時 /v1/models 目錄。OmniRoute 使用 OpenAI 協定並透過透傳方式列出模型。", "xai": "使用 API 金鑰連線 xAI(Grok)。", "xiaomi-mimo": "使用 API 金鑰連線 Xiaomi MiMo。", @@ -6030,7 +6032,12 @@ "kimiOfficialSupporterTooltip": "Kimi(Moonshot AI)是 OmniRoute 的創始開源好友", "cheaperInferenceSupporterBadge": "開源好友", "cheaperInferenceSupporterTooltip": "Cheaper Inference 作為開源好友支持 OmniRoute", - "kimiPartnerLinkNote": "合作夥伴連結 — 支援 OmniRoute,您無需額外付費" + "kimiPartnerLinkNote": "合作夥伴連結 — 支援 OmniRoute,您無需額外付費", + "anonymousFallbackTitle": "__MISSING__:Anonymous fallback", + "anonymousFallbackDesc": "__MISSING__:When all configured connections are exhausted (quota, credits, or expiry), temporarily use this provider's keyless tier. Turn off to skip this provider instead of sending anonymous requests — recommended when the keyless tier rejects them (401).", + "anonymousFallbackEnabled": "__MISSING__:Anonymous fallback enabled for {provider}", + "anonymousFallbackDisabled": "__MISSING__:Anonymous fallback disabled for {provider} — exhausted connections will skip this provider", + "anonymousFallbackUpdateFailed": "__MISSING__:Failed to update anonymous fallback setting" }, "settings": { "title": "設定", @@ -6790,7 +6797,7 @@ "howPricingWorks": "定價如何運作", "cacheWrite": "快取寫入", "unsaved": "未儲存", - "resetDefaults": "__MISSING__:Reset defaults", + "resetDefaults": "重置預設值", "saveProvider": "儲存提供者", "model": "模型", "models": "模型", @@ -6970,13 +6977,13 @@ "compressionPreserveSystemNever": "永不", "compressionLiveZoneTitle": "快取對齊即時區域", "compressionLiveZoneDesc": "保持壓縮對話前綴穩定,僅處理新附加的項目。", - "compressionExclusionsTitle": "__MISSING__:Compression Exclusions", - "compressionExclusionsDesc": "__MISSING__:Model ids or provider/model patterns that must never be compressed. `*` is the only wildcard (e.g. `openai/*`, `*embedding*`). A matching request passes through byte-identical — no compression engine runs.", - "compressionExclusionsPlaceholder": "__MISSING__:One pattern per line, e.g.\nopenai/text-embedding-3-large\nanthropic/*", - "compressionExclusionsSave": "__MISSING__:Save", - "compressionExclusionsSaved": "__MISSING__:Saved", - "compressionExclusionsCount": "__MISSING__:{count, plural, one {# exclusion} other {# exclusions}} configured", - "compressionExclusionsEmpty": "__MISSING__:No exclusions configured — every model/endpoint is eligible for compression (default behavior).", + "compressionExclusionsTitle": "壓縮排除規則", + "compressionExclusionsDesc": "設定哪些模型或端點應跳過壓縮。使用 * 作為通配符。", + "compressionExclusionsPlaceholder": "例如claude-opus*", + "compressionExclusionsSave": "保存排除規則", + "compressionExclusionsSaved": "排除規則已保存。", + "compressionExclusionsCount": "{count} 條規則", + "compressionExclusionsEmpty": "尚未設定排除規則—所有模型和端點均可壓縮。", "compressionCavemanConfig": "Caveman 引擎設定", "compressionCavemanConfigDesc": "微調基於規則的壓縮引擎", "compressionCavemanPanelHint": "其開關與等級在面板中設定:", @@ -7812,10 +7819,6 @@ "label": "最小壓縮行數", "description": "觸發表格壓縮所需的同質 JSON 陣列最小行數。預設值:8。" }, - "compressToolResults": { - "label": "__MISSING__:Proactively truncate long tool results", - "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." - }, "preserveSystemPrompt": { "label": "保留系統提示詞" }, @@ -7839,6 +7842,10 @@ }, "minMessageLength": { "label": "最小訊息長度" + }, + "compressToolResults": { + "label": "__MISSING__:Proactively truncate long tool results", + "description": "__MISSING__:Truncates tool results over 2,000 characters during Lite compression. Emergency overflow protection may still trim content when the context exceeds the model budget." } }, "engineFields": { @@ -10195,6 +10202,8 @@ "copied": "已複製!", "run": "執行", "running": "執行中...", + "loading": "__MISSING__:Loading...", + "retry": "__MISSING__:Retry", "response": "回應", "tunnel": "隧道", "send": "傳送", @@ -11380,7 +11389,7 @@ } }, "pageTitle": "特工技能", - "pageSubtitle": "__MISSING__:Teach your agent to operate OmniRoute — 23 API areas + 21 CLI families", + "pageSubtitle": "教你的智能體操作OmniRoute— 22 個API區域 + 20 個CLI家族", "conceptCard": { "agent": { "title": "代理技能 — 外呼", diff --git a/src/lib/db/migrationRunner.ts b/src/lib/db/migrationRunner.ts index fabcd06e6d..e7a2d06b3b 100644 --- a/src/lib/db/migrationRunner.ts +++ b/src/lib/db/migrationRunner.ts @@ -487,6 +487,8 @@ function isSchemaAlreadyApplied( // but still burn a version-tracking slot mismatch — guard it the same // way as the other renumbers for consistency. return hasTable(db, "connection_runtime_state"); + case "146": + return hasTable(db, "jobs") && hasTable(db, "job_runs"); default: return false; } diff --git a/src/lib/db/migrationRunner/constants.ts b/src/lib/db/migrationRunner/constants.ts index 697fe3b31d..13da58e4bc 100644 --- a/src/lib/db/migrationRunner/constants.ts +++ b/src/lib/db/migrationRunner/constants.ts @@ -75,6 +75,12 @@ export const RENAMED_MIGRATION_COMPATIBILITY = [ toVersion: "139", toName: "ccr_blocks", }, + { + fromVersion: "139", + fromName: "job_registry", + toVersion: "146", + toName: "job_registry", + }, ] as const; export const LEGACY_VERSION_SLOT_MIGRATIONS = [ diff --git a/src/lib/db/migrations/139_job_registry.sql b/src/lib/db/migrations/146_job_registry.sql similarity index 97% rename from src/lib/db/migrations/139_job_registry.sql rename to src/lib/db/migrations/146_job_registry.sql index 3bf29ac3d2..e948d2ee9e 100644 --- a/src/lib/db/migrations/139_job_registry.sql +++ b/src/lib/db/migrations/146_job_registry.sql @@ -1,4 +1,4 @@ --- Migration 139: generic job registry (jobs + job_runs tables) +-- Migration 146: generic job registry (jobs + job_runs tables) -- Job registry (#8848): centralized periodic-job scheduling + run history. -- -- jobs: one row per registered job (interval or cron), with env-flag gating diff --git a/src/lib/oauth/constants/oauth.ts b/src/lib/oauth/constants/oauth.ts index c89f5fa63e..d75deffcad 100644 --- a/src/lib/oauth/constants/oauth.ts +++ b/src/lib/oauth/constants/oauth.ts @@ -154,7 +154,7 @@ export const XAI_OAUTH_CONFIG = { // Openference OAuth Configuration (Authorization Code Flow with PKCE) export const OPENFERENCE_CONFIG = { - clientId: "omniroute", + clientId: resolvePublicCred("openference_id"), authorizeUrl: "https://openference.com/app/oauth/authorize", tokenUrl: "https://openference.com/oauth/token", userinfoUrl: "https://openference.com/oauth/userinfo", diff --git a/src/lib/telegram/errorMessage.ts b/src/lib/telegram/errorMessage.ts new file mode 100644 index 0000000000..6ce8c5ce17 --- /dev/null +++ b/src/lib/telegram/errorMessage.ts @@ -0,0 +1,5 @@ +import { sanitizeErrorMessage } from "@omniroute/open-sse/utils/error.ts"; + +export function formatTelegramGatewayError(error: unknown): string { + return `⚠️ Gateway error: ${sanitizeErrorMessage(error)}`; +} diff --git a/tests/unit/check-db-rules-classification.test.ts b/tests/unit/check-db-rules-classification.test.ts index 7ccee8987e..91b46bdceb 100644 --- a/tests/unit/check-db-rules-classification.test.ts +++ b/tests/unit/check-db-rules-classification.test.ts @@ -121,7 +121,7 @@ test("INTENTIONALLY_INTERNAL is exported from check-db-rules.mjs", () => { assert.ok(INTENTIONALLY_INTERNAL.size > 0, "INTENTIONALLY_INTERNAL must not be empty"); }); -test("INTENTIONALLY_INTERNAL contains the expected 38 audited modules", () => { +test("INTENTIONALLY_INTERNAL contains the expected 39 audited modules", () => { const expected = [ "_rowTypes", "accessTokens", @@ -134,6 +134,7 @@ test("INTENTIONALLY_INTERNAL contains the expected 38 audited modules", () => { "commandCodeAuth", "compression", "compressionDetailNormalizers", + "connectionRuntimeState", "detailedLogs", "discovery", "domainState", diff --git a/tests/unit/check-migration-numbering.test.ts b/tests/unit/check-migration-numbering.test.ts index 12cc3ba67e..f90734f270 100644 --- a/tests/unit/check-migration-numbering.test.ts +++ b/tests/unit/check-migration-numbering.test.ts @@ -99,9 +99,13 @@ test("the real migrations dir produces ZERO anomalies under the frozen allowlist assert.deepEqual(r.gaps, [], `unexpected sequence gaps: ${r.gaps.join(", ")}`); }); -test("frozen allowlists match the documented audit (026 & 055 gaps)", () => { +test("frozen allowlists match the documented legacy and stacked-series gaps", () => { assert.ok((KNOWN_GAPS as Set).has("026")); assert.ok((KNOWN_GAPS as Set).has("055")); + assert.ok((KNOWN_GAPS as Set).has("121")); + assert.ok((KNOWN_GAPS as Set).has("143")); + assert.ok((KNOWN_GAPS as Set).has("144")); + assert.ok((KNOWN_GAPS as Set).has("145")); // "041" was removed from KNOWN_DUPLICATE_VERSIONS in 6A.3 (stale: no physical // duplicate for that prefix on disk anymore — only 041_compression_receipts.sql exists). assert.equal((KNOWN_DUPLICATE_VERSIONS as Set).has("041"), false); diff --git a/tests/unit/codebuddy-cn-provider.test.ts b/tests/unit/codebuddy-cn-provider.test.ts index 931c2e7552..c87db2afdb 100644 --- a/tests/unit/codebuddy-cn-provider.test.ts +++ b/tests/unit/codebuddy-cn-provider.test.ts @@ -4,7 +4,7 @@ import assert from "node:assert/strict"; import { AI_PROVIDERS, USAGE_SUPPORTED_PROVIDERS, - FREE_APIKEY_PROVIDER_IDS, + supportsDualAuthProvider, } from "../../src/shared/constants/providers.ts"; import { REGISTRY } from "../../open-sse/config/providerRegistry.ts"; import { getExecutor } from "../../open-sse/executors/index.ts"; @@ -25,6 +25,20 @@ type CapturedRequest = { body: Record; }; +type ToolDefinition = { + type: string; + function: { + name: string; + description?: string; + parameters: unknown; + }; +}; + +type UsageResult = { + plan: string; + quotas: Record; +}; + async function executeWithMockedUpstream( body: Record, responses: Response[] @@ -251,7 +265,7 @@ test("CodeBuddyCnExecutor retries a sensitive-content rejection with compact too assert.equal(calls.length, 2, "known rejection should dispatch exactly one compact retry"); assert.deepEqual(calls[0].body.tools, input.tools, "the first request must remain unchanged"); - const retryTools = calls[1].body.tools as Array>; + const retryTools = calls[1].body.tools as ToolDefinition[]; assert.deepEqual( retryTools.map((tool) => tool.function.name), ["read_file", "run_workflow"], @@ -261,7 +275,7 @@ test("CodeBuddyCnExecutor retries a sensitive-content rejection with compact too assert.equal("description" in retryTools[1].function, false); assert.deepEqual( retryTools.map((tool) => tool.function.parameters), - (input.tools as Array>).map((tool) => tool.function.parameters), + (input.tools as ToolDefinition[]).map((tool) => tool.function.parameters), "parameter schemas, including nested descriptions, must remain unchanged" ); assert.deepEqual(calls[1].body.tool_choice, input.tool_choice); @@ -304,7 +318,7 @@ test("CodeBuddyCnExecutor does not retry unrelated 400 responses with tools", as test("CodeBuddyCnExecutor does not retry sensitive rejection for normal-sized tools", async () => { const input = toolRequestBody(); - for (const tool of input.tools as Array>) { + for (const tool of input.tools as ToolDefinition[]) { tool.function.description = "A normal-sized tool description"; } const { calls, status } = await executeWithMockedUpstream(input, [rejectionResponse()]); @@ -315,7 +329,7 @@ test("CodeBuddyCnExecutor does not retry sensitive rejection for normal-sized to test("CodeBuddyCnExecutor does not retry an already-compacted tool request", async () => { const input = toolRequestBody(); - for (const tool of input.tools as Array>) { + for (const tool of input.tools as ToolDefinition[]) { delete tool.function.description; } const { calls, status } = await executeWithMockedUpstream(input, [rejectionResponse()]); @@ -411,8 +425,7 @@ test("CodeBuddyCnExecutor preserves reasoning transformations on compact retries test("codebuddy-cn OAuth provider is wired with device_code flow and GET-poll on state", async () => { assert.equal(OAUTH_PROVIDER_IDS.CODEBUDDY_CN, "codebuddy-cn"); - const map = PROVIDERS_MAP as Record; - const cb = map["codebuddy-cn"]; + const cb = PROVIDERS_MAP["codebuddy-cn"]; assert.ok(cb, "PROVIDERS map must include 'codebuddy-cn'"); assert.equal(cb.flowType, "device_code"); assert.equal(typeof cb.requestDeviceCode, "function"); @@ -422,7 +435,7 @@ test("codebuddy-cn OAuth provider is wired with device_code flow and GET-poll on // with the state as a query param (upstream's distinguishing detail). const origFetch = globalThis.fetch; const calls: { url: string; init?: RequestInit }[] = []; - globalThis.fetch = async (url: any, init?: RequestInit) => { + globalThis.fetch = async (url: string | URL | Request, init?: RequestInit) => { calls.push({ url: String(url), init }); return new Response( JSON.stringify({ @@ -509,7 +522,7 @@ test("codebuddy-cn is in USAGE_SUPPORTED_PROVIDERS and quota handler parses Tenc try { const result = await getCodeBuddyCnUsage("ACCESS_TOKEN", undefined, undefined); assert.ok(result && typeof result === "object"); - const r = result as Record; + const r = result as UsageResult; assert.equal(r.plan, "Refill Pack"); assert.ok(r.quotas); // Refill (Monthly) uses CycleCapacity*; Bonus packs use plain Capacity*; soonest-expiring first. @@ -527,10 +540,10 @@ test("codebuddy-cn is in USAGE_SUPPORTED_PROVIDERS and quota handler parses Tenc }); test("codebuddy-cn is treated as a managed dual-auth provider (oauth + apikey accepted by POST /api/providers)", async () => { - // The provider creation gate trusts FREE_APIKEY_PROVIDER_IDS to admit - // OAuth-category providers that also accept a direct API key (like qoder). + // OAuth-category providers that also accept a direct API key use the + // dedicated dual-auth gate so their primary dashboard action remains OAuth. assert.ok( - FREE_APIKEY_PROVIDER_IDS.has("codebuddy-cn"), + supportsDualAuthProvider("codebuddy-cn"), "codebuddy-cn must be admitted by the dual-auth gate" ); }); diff --git a/tests/unit/db-job-registry-migration-renumber-139.test.ts b/tests/unit/db-job-registry-migration-renumber-139.test.ts new file mode 100644 index 0000000000..b2dfff0d3e --- /dev/null +++ b/tests/unit/db-job-registry-migration-renumber-139.test.ts @@ -0,0 +1,59 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import Database from "better-sqlite3"; + +const migrationsDir = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-job-migration-")); +const originalMigrationsDir = process.env.OMNIROUTE_MIGRATIONS_DIR; +process.env.OMNIROUTE_MIGRATIONS_DIR = migrationsDir; + +fs.writeFileSync( + path.join(migrationsDir, "139_ccr_blocks.sql"), + "CREATE TABLE ccr_blocks (principal_id TEXT PRIMARY KEY);" +); +fs.writeFileSync( + path.join(migrationsDir, "146_job_registry.sql"), + "CREATE TABLE jobs (id TEXT PRIMARY KEY); CREATE TABLE job_runs (id INTEGER PRIMARY KEY);" +); + +const { runMigrations } = await import("../../src/lib/db/migrationRunner.ts"); + +test.after(() => { + fs.rmSync(migrationsDir, { recursive: true, force: true }); + if (originalMigrationsDir === undefined) delete process.env.OMNIROUTE_MIGRATIONS_DIR; + else process.env.OMNIROUTE_MIGRATIONS_DIR = originalMigrationsDir; +}); + +test("job registry previously applied on 139 is rehomed so CCR can claim that slot", () => { + const db = new Database(":memory:"); + try { + db.exec(` + CREATE TABLE jobs (id TEXT PRIMARY KEY); + CREATE TABLE job_runs (id INTEGER PRIMARY KEY); + CREATE TABLE _omniroute_migrations ( + version TEXT PRIMARY KEY, + name TEXT NOT NULL, + applied_at TEXT NOT NULL DEFAULT (datetime('now')) + ); + INSERT INTO _omniroute_migrations (version, name) VALUES ('139', 'job_registry'); + `); + + assert.equal(runMigrations(db), 1); + assert.deepEqual( + db.prepare("SELECT version, name FROM _omniroute_migrations ORDER BY version").all(), + [ + { version: "139", name: "ccr_blocks" }, + { version: "146", name: "job_registry" }, + ] + ); + assert.ok( + db + .prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'ccr_blocks'") + .get() + ); + } finally { + db.close(); + } +}); diff --git a/tests/unit/db-migrationrunner-constants-split.test.ts b/tests/unit/db-migrationrunner-constants-split.test.ts index 7da7d426ad..40c27a91bc 100644 --- a/tests/unit/db-migrationrunner-constants-split.test.ts +++ b/tests/unit/db-migrationrunner-constants-split.test.ts @@ -70,8 +70,8 @@ describe("migrationRunner/constants — exact small-table snapshots", () => { // ── large tables — count + shape + spot-checks (corruption guard) ───────────── describe("migrationRunner/constants — large-table integrity", () => { - it("RENAMED_MIGRATION_COMPATIBILITY has 11 well-formed entries", () => { - assert.equal(RENAMED_MIGRATION_COMPATIBILITY.length, 11); + it("RENAMED_MIGRATION_COMPATIBILITY has 12 well-formed entries", () => { + assert.equal(RENAMED_MIGRATION_COMPATIBILITY.length, 12); for (const e of RENAMED_MIGRATION_COMPATIBILITY) { assert.equal(typeof e.fromVersion, "string"); assert.equal(typeof e.fromName, "string"); @@ -91,12 +91,18 @@ describe("migrationRunner/constants — large-table integrity", () => { // both manifest_routing collisions (052→059 and 056→059) must survive const manifest = RENAMED_MIGRATION_COMPATIBILITY.filter((e) => e.toName === "manifest_routing"); assert.deepEqual(manifest.map((e) => e.fromVersion).sort(), ["052", "056"]); - assert.deepEqual(RENAMED_MIGRATION_COMPATIBILITY.at(-1), { + assert.deepEqual(RENAMED_MIGRATION_COMPATIBILITY.at(-2), { fromVersion: "134", fromName: "ccr_blocks", toVersion: "139", toName: "ccr_blocks", }); + assert.deepEqual(RENAMED_MIGRATION_COMPATIBILITY.at(-1), { + fromVersion: "139", + fromName: "job_registry", + toVersion: "146", + toName: "job_registry", + }); }); it("PHYSICAL_SCHEMA_SENTINELS has 15 well-formed entries incl. the newest 064", () => { diff --git a/tests/unit/openference-oauth-provider.test.ts b/tests/unit/openference-oauth-provider.test.ts index 707a3f83a8..0e7add513b 100644 --- a/tests/unit/openference-oauth-provider.test.ts +++ b/tests/unit/openference-oauth-provider.test.ts @@ -8,6 +8,7 @@ import { } from "../../src/lib/oauth/providers/openference.ts"; import { OPENFERENCE_CONFIG } from "../../src/lib/oauth/constants/oauth.ts"; import { getExecutor, hasSpecializedExecutor } from "../../open-sse/executors/index.ts"; +import { OAUTH_ENDPOINTS } from "../../open-sse/config/constants.ts"; import { openferenceProvider } from "../../open-sse/config/providers/registry/openference/index.ts"; import { refreshOpenferenceToken } from "../../open-sse/services/tokenRefresh/providers/openference.ts"; import { OAUTH_TEST_CONFIG } from "../../src/app/api/providers/[id]/test/oauthTestConfig.ts"; @@ -117,6 +118,10 @@ test("Openference is registered as an OAuth gateway with default executor", () = assert.equal(openferenceProvider.authType, "oauth"); assert.equal(openferenceProvider.executor, "default"); + assert.equal(openferenceProvider.oauth?.clientIdDefault, OPENFERENCE_CONFIG.clientId); + assert.equal(OAUTH_ENDPOINTS.openference.clientId, OPENFERENCE_CONFIG.clientId); + assert.match(OPENFERENCE_CONFIG.clientId, /^[a-z]+$/); + assert.equal(OPENFERENCE_CONFIG.clientId.length, 9); assert.equal(openferenceProvider.baseUrl, "https://api.openference.com/v1/chat/completions"); assert.deepEqual( openferenceProvider.models?.map((model) => model.id), diff --git a/tests/unit/publicCreds.test.ts b/tests/unit/publicCreds.test.ts index 6690069cf0..422e285eeb 100644 --- a/tests/unit/publicCreds.test.ts +++ b/tests/unit/publicCreds.test.ts @@ -59,6 +59,12 @@ test("resolvePublicCred('grok_id') returns a UUID-shaped xAI OAuth client id", ( assert.equal(v.length, 36); }); +test("resolvePublicCred('openference_id') returns the public PKCE client id shape", () => { + const v = resolvePublicCred("openference_id"); + assert.match(v, /^[a-z]+$/); + assert.equal(v.length, 9); +}); + test("encode/decode roundtrip is stable across arbitrary plaintexts", () => { for (const sample of [ "hello world", diff --git a/tests/unit/telegram-route-error-sanitization.test.ts b/tests/unit/telegram-route-error-sanitization.test.ts new file mode 100644 index 0000000000..951faa9597 --- /dev/null +++ b/tests/unit/telegram-route-error-sanitization.test.ts @@ -0,0 +1,18 @@ +import assert from "node:assert/strict"; +import { test } from "node:test"; + +import { formatTelegramGatewayError } from "../../src/lib/telegram/errorMessage"; + +test("Telegram gateway failures do not expose paths, secrets, or stack traces", () => { + const error = new Error( + "provider failed at /home/operator/omniroute/provider.ts access_token=super-secret\n" + + " at dispatch (/home/operator/omniroute/route.ts:42:1)" + ); + + const message = formatTelegramGatewayError(error); + + assert.match(message, /^⚠️ Gateway error: /); + assert.doesNotMatch(message, /\/home\/operator/); + assert.doesNotMatch(message, /super-secret/); + assert.doesNotMatch(message, /at dispatch/); +}); diff --git a/tests/unit/ui/resilience-connections.test.tsx b/tests/unit/ui/resilience-connections.test.tsx index 75329034ab..8cd728aeb3 100644 --- a/tests/unit/ui/resilience-connections.test.tsx +++ b/tests/unit/ui/resilience-connections.test.tsx @@ -348,6 +348,7 @@ describe("ConnectionsTable", () => { ) as HTMLDivElement; }); + const root = containers[containers.length - 1].root; const row = el!.querySelector("tbody tr") as HTMLTableRowElement; act(() => { row.click(); @@ -355,10 +356,10 @@ describe("ConnectionsTable", () => { await waitFor(() => el!.textContent?.includes("detail.title")); // Re-render with the connection removed. act(() => { - render(
) as HTMLDivElement; + root.render(
); }); - // No crash; the unmount of the old tree is handled by createRoot reuse here. - expect(true).toBe(true); + await waitFor(() => !el!.textContent?.includes("detail.title")); + expect(el!.textContent).not.toContain("detail.title"); }); });