{"repo": "bsangs/omniroute", "files": {"docs/i18n/it/CHANGELOG.md": {"63029ae7eb5118baa91257939233db8fb0aed60b": {"t": 1785746533.1683807, "n": 229533, "h": "5c23b70c4c95ab05", "c": "# Changelog (Italiano)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.6.8] — 2026-04-17\n\n### ✨ New Features\n\n- **feat(providers):** Support `xhigh` reasoning tier exclusively on Claude models that expose it (#1356)\n- **feat(providers):** Add CC Compatible connection-level 1M context toggle (#1357)\n- **feat(core):** Add full support for Node.js 24 LTS (Krypton) environments with continuous integration coverage (#1340)\n- **feat(dashboard):** Display Antigravity credit balance in dashboard Limits & Quotas (#1338)\n- **feat(i18n):** Add internationalization support for combo features and dashboard components; sync translations across 31 keys (#1318)\n- **feat(providers):** Add Claude Opus 4.7 to Claude Code OAuth models natively with extended context and caching (#1347)\n- **feat(core):** Add stopSequences support and expand tool definitions to include Google Search capabilities\n- **feat(auth):** Enforce dashboard session authentication on all management API routes, preventing unauthenticated access to configuration endpoints\n- **feat(runtime):** Add hot-reloadable guardrails and model diagnostics for real-time rule evaluation without restarts\n- **feat(core):** Add payload rules, tag-based routing, and scheduled budget systems for fine-grained request governance\n- **feat(providers):** Expose Antigravity preview model aliases and Gemini CLI onboarding flow for first-time setup\n- **feat(antigravity):** Add client model aliases and thoughtSignature bypass modes for Antigravity OAuth connections\n- **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations\n- **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages\n\n### Sicurezza\n\n- **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns\n- **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353)\n- **fix(providers):** Resolve Codex token refresh race condition via mutex `getAccessToken` preventing `refresh_token_reused` Auth0 revocations\n\n### 🔧 Maintenance & Architecture\n\n- **refactor(core):** Split CLI runner and decouple migration engine for extensibility (#1358)\n- **refactor(audit):** Rewire audit dashboard from dead in-memory `configAudit` store to live SQLite `audit_log` table — 331+ hidden compliance entries now visible in `/dashboard/audit`\n- **build(deps):** Bump `softprops/action-gh-release` from v2 to v3\n- **ci:** Bump GitHub Actions CI node-version to Node.js 24 natively\n- **fix(types):** Resolve TypeScript compilation errors in `claudeCodeCompatible.ts` (type predicates, `cache_control` index access) and `proxyFetch.ts` (`signal` nullability)\n\n### 🐛 Bug Fixes\n\n- **fix(context):** Scale reserved context tokens dynamically using a 15% sliding window for smaller models\n- **test(core):** Replace unit test with integration test for proactive context compression to align with isolated runner rules (#1378)\n- **fix(services):** Pass origin provider to refreshWithRetry to avoid tripping the generic \"unknown\" circuit breaker (fixes Codex accounts erroneously disabling)\n- **fix(db):** Prevent native module ABI load crashes from assuming database corruption and skipping databases\n- **fix(db):** Increase mass-migration threshold from 5 to 50 pending migrations to protect legacy users upgrading node\n- **fix(db):** Prevent migration runner safety aborts from triggering on fresh `DATA_DIR` installations by detecting new databases (#1328)\n- **fix(mcp):** Checkpoint and close MCP audit SQLite database safely on process signals and shutdown (#1348)\n- **fix(mcp):** Fully decouple MCP audit SQLite connection caching via globalThis to fix unhandled teardown in standalone Next.js chunks (#1349)\n- **fix(cli):** Avoid creating app router directory during postinstall initialization on non-built source trees (#1351)\n- **fix(codex):** Correctly translate `system` role to `developer` in input array to unlock GPT-5 automatic prompt caching (#1346)\n- **fix(core):** Pass client headers to executor in chatCore (#1335)\n- **fix(providers):** Separate test batch calls and ignore unknown connections\n- **fix(providers):** Add grok-web SSO cookie validation handler (#1334)\n- **fix(db):** Preserve key_value settings (dashboard passwords, saved aliases) across DB heuristic recreation cycles (#1333)\n- **fix(routing):** Allow combo fallback to cascade context overflow 400 errors instead of immediate aborts (#1331)\n- **fix(core):** Resolve thinking leaks, consecutive roles, and missing thoughtSignatures for Antigravity translator (#1316)\n- **fix(translator):** Only apply thoughtSignature to the first `functionCall` part in Gemini parallel tool calls, preventing duplicate signatures\n- **fix(providers):** Default to batch testing execution blocks for web, search, and audio modalities to prevent connection timeouts\n- **fix(cli):** Resolve Node 22 TS entrypoint incompatibility by using esbuild compilation (#1315)\n- **fix(chat):** Preserve max_output_tokens for Responses API targets in chatCore sanitization (#1313)\n- **fix(api):** API Manager usage stats showing 0 for all registered keys (#1310)\n- **fix(api):** Support image-only models in catalog and allow authless search providers to bypass validation requirements\n- **fix(routes):** Require prompts for media generation requests (`/images`, `/videos`, `/music`), returning 400 on missing payloads\n- **fix(dashboard):** Auto-scroll ActivityHeatmap to show current date (#1309)\n- **fix(dashboard):** Restore horizontal layout with `w-max` wrapper in heatmap components\n- **fix(i18n):** Update `nodeIncompatibleHint` to recommend Node 24 LTS across all 31 languages\n- **fix(i18n):** Add Chinese i18n support to remaining dashboard components (`Loading.tsx`, `DataTable`, etc.)\n- **fix(requestLogger):** Add missing `cacheSource` and `tps` columns to i18n log detail views\n\n## [3.6.6] — 2026-04-15\n\n### ✨ New Features\n\n- **feat(storage):** Add database backup cleanup controls, UI management, and customizable retention period env vars (#1304)\n- **feat(providers):** Add Freepik Pikaso image generation provider with support for cookie/subscription-based auth modes (#1277)\n- **feat(providers): Add Perplexity Web (Session) Provider** — Routes through Perplexity's internal SSE API using a session cookie, giving native proxy access without separate API costs to GPT-5.4, Claude Opus, Gemini 3.1 Pro, and Nemotron via preferences mapping (#1289)\n- **feat(api): Sync Tokens & V1 WebSocket Bridge** — Dedicated sync token storage, issuance, revocation, and bundle download routes backed by stable config bundle versioning with ETag support. Exposes `/v1/ws` WebSocket upgrade route and a custom Next.js server bridge (`scripts/v1-ws-bridge.mjs`) so OpenAI-compatible WebSocket traffic can be proxied through the gateway. Compliance auditing expanded with structured metadata, pagination, request context, auth/provider credential events, and SSRF-blocked validation logging. New migrations: `024_create_sync_tokens.sql`. New modules: `syncTokens.ts`, `src/lib/sync/bundle.ts`, `src/lib/sync/tokens.ts`, `src/lib/ws/handshake.ts`, `src/lib/apiBridgeServer.ts`, `src/lib/compliance/providerAudit.ts`.\n- **feat(models): GLM Thinking Preset & Hybrid Token Counting** — GLM Thinking (`glmt`) registered as a first-class provider preset with shared GLM model metadata, pricing, per-connection usage sync, dashboard support, and `maxTokens: 65536 / thinkingBudgetTokens: 24576` request defaults with 900s extended timeout. Provider-side `/messages/count_tokens` endpoint used when a Claude-compatible upstream supports it; gracefully falls back to estimation on missing models, missing credentials, or upstream failures. Startup seeding of default model aliases (`src/lib/modelAliasSeed.ts`) normalizes common cross-proxy model dialects so canonical slash-based model IDs are not misrouted. New file `open-sse/config/glmProvider.ts`.\n- **feat(core): Hardened Outbound Provider Calls & Cooldown Retries** — Guarded outbound fetch helpers (`src/shared/network/safeOutboundFetch.ts`, `src/shared/network/outboundUrlGuard.ts`) blocking private/local URLs with configurable retry, timeout normalisation, and route-level status propagation for provider validation and model discovery. Cooldown-aware chat retries (`src/sse/services/cooldownAwareRetry.ts`) with configurable `requestRetry` and `maxRetryIntervalSec` settings and model-scoped cooldown responses. Improved rate-limit learning from headers and error bodies so short upstream lockouts can recover automatically. Runtime environment validation (`src/lib/env/runtimeEnv.ts`) checks env at startup. Pollinations now requires an API key. Antigravity and Codex header handling aligned via `open-sse/config/antigravityUpstream.ts` and `open-sse/config/codexClient.ts`. Gemini tool names restored in translated responses; synthetic Claude text block injected when upstream SSE completes empty.\n- **feat(logs):** Add TPS (Tokens Per Second) metric to log details modal metadata grid (#1182)\n- **feat(memory+skills):** Full-featured Memory & Skills systems with FTS5 SQLite search, dynamic UI pagination, backend observability, and extensive test coverage (#1228)\n- **feat(bailian-quota):** Add Alibaba Coding Plan quota monitoring, multi-window quota extraction, and UI credential validation (#1235)\n- **feat(storage): Call Log Storage Refactor** — Extracted heavy request/response JSON payloads from the core SQLite database (`storage.sqlite`) into filesystem artifacts stored within `DATA_DIR/call_logs`. This massively reduces WAL bloat and eliminates `SQLITE_FULL` crashes on high-traffic nodes (#1307).\n- **feat(providers): Add Grok Web (Subscription) Provider** — Routes through the xAI web interface for subscription users via cookie session mapping (#1295).\n- **feat(api): Advanced Media Support** — Extends OpenAI generic proxy layer to natively support `image`, `embeddings`, `audio-transcriptions`, and `audio-speech` workflows (#1297).\n- **feat(cli-tools): Qwen Code CLI Integration** — Full integration for Qwen Code local execution mapping, model resolution, and dynamic API key fetching (#1266, #1263).\n- **feat(oauth):** Supports `cursor-agent` CLI as a native Cursor credential source alongside the standard configuration (#1258).\n- **feat(models):** Custom and imported models now merge correctly into filter lists for all available global providers (#1191).\n\n### 🐛 Bug Fixes\n\n- **fix(providers):** match correct endpoint api.xiaomimimo.com for Xiaomi MiMo (#1303)\n- **fix(core):** strip provider alias routing prefix from payload for custom endpoints to fix Azure OpenAI 400 errors (#1261)\n- **fix(core):** ProxyFetch Undici dispatcher automatically bypasses LAN/local addresses, preventing fetch failures on internal OpenRouter requests (#1254)\n- **fix(core):** Gemini thought stream signature detection upgraded to use native part.thought boolean, preventing reasoning text leaks (#1298)\n- **deps:** bump hono from 4.12.12 to 4.12.14 to resolve CVE SSR HTML injection vulnerability (#1306, #59)\n- **deps:** update dompurify to 3.4.0 in frontend overrides mitigating XSS HTML Injection (CVE-XYZ / Dependabot #60)\n- **test:** Disable SQLite automatic backups during continuous integration (CI) tests to resolve E2E timeout issues limiting runner scaling (#24481475058)\n- **feat(core): Proactive Context Compression** — `chatCore` now proactively compresses oversized message contexts before hitting upstream providers to dramatically reduce `context_length_exceeded` errors. Employs binary-search message pruning with structural integrity guarantees tracking explicit `tool_use` boundaries ensuring truncated tool inputs drop paired outputs appropriately (#1292, #1293)\n\n- **fix(cli):** Resolve codex routing config parsing by strictly quoting section keys array, enforcing responses wire_api with fallback, and standardizing select-model button positioning mirroring Claude UI\n- **fix(providers):** Correct Lobehub provider icons rendering by removing unsupported local references ensuring local SVG/PNG fallback mechanism invokes natively\n- **fix(db):** Implement Database migration tracking safety abort safeguards (pre-migration backups via `VACUUM INTO` and mass renumbering warnings) to protect existing database structures on startup upgrades (#1281)\n- **fix(dashboard):** Cleaned up target codex `config.toml` structure preventing recursive section rendering by enforcing quotes on section dot paths and mapping correct UI `OMNIROUTE_API_KEY` names.\n- **fix(mcp):** Add dedicated explicit timeout constraint overrides for search handlers (#1280)\n- **fix(crypto):** Add validation guard to encryption layer to surface clear UI errors when cryptographic environment variables are missing, replacing raw Node.js TypeErrors. Legacy env vars `OMNIROUTE_CRYPT_KEY` and `OMNIROUTE_API_KEY_BASE64` now also accepted as fallbacks (#1165)\n- **fix(providers):** Update Pollinations provider definition to require API keys and specify their new limited pollen/hour free tier (#1177)\n- **Streaming `\\n\\n` Artifact Fix (#1211):** Changed `` tag-stripping regex from `?` to `*` quantifier across `combo.ts`, `comboAgentMiddleware.ts`, and `contextHandoff.ts` to greedily strip all accumulated JSON-escaped newline sequences surrounding the tag. This prevents literal `\\n\\n` prefix artifacts from appearing in consumer streaming responses\n- **E2E Combo Test Locator:** Fixed Playwright strict-mode violation in `combo-unification.spec.ts` by replacing ambiguous `getByRole` locator with a compound filter locator for the \"All\" strategy tab\n- **fix(cc-compatible):** Trim beta flags and preserve cache passthrough for third-party HTTP proxy compatibility (#1230)\n- **fix(providers):** Update Xiaomi MiMo endpoints to the live token-plan, migrating away from dead API URLs (#1238)\n- **fix:** Forward client `x-initiator` header to GitHub Copilot upstream to accurately distinguish agent vs user turns (#1227)\n- **fix:** Resolve backlog bugs including streaming edge cases, unhandled rejections, and quota parse failures (#1206, #1220, #1231, #1175, #1187, #1218, #1202)\n- **fix(tests):** Resolve memory migration and skills route pagination bugs arising from PR overlaps\n- **fix(i18n):** Add missing Chinese i18n support to dashboard components (`DataTable`, `EmptyState`, etc), update `en.json/zh-CN.json` routing keys, and natively resolve JSX defaults via `next-intl` (#1274)\n\n### 🔧 Internal Improvements\n\n- **Compliance Audit Expansion:** `src/lib/compliance/index.ts` expanded with structured metadata, pagination support, request context enrichment, and new `providerAudit.ts` module logging auth and provider credential events, SSRF-blocked validation attempts, and provider CRUD operations\n- **Config Sync Bundle:** `src/lib/sync/bundle.ts` exports `buildConfigBundle()` generating a versioned JSON snapshot of settings, provider connections, nodes, model aliases, combos, and API keys (passwords redacted) with ETag support for bandwidth-efficient polling\n- **Codex Client Constants:** Centralized `CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT_PLATFORM`, and pattern-validated env overrides (`CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT`) in `open-sse/config/codexClient.ts`\n- **Antigravity Upstream Constants:** `open-sse/config/antigravityUpstream.ts` consolidates all Antigravity base URLs and model/fetchAvailableModels discovery path builders\n- **Model Alias Seed:** `src/lib/modelAliasSeed.ts` seeds 30+ cross-proxy model dialect aliases (e.g. `openai/gpt-5` → `gpt-5`, `anthropic/claude-opus-4-6` → `cc/claude-opus-4-6`) at startup via idempotent `upsert`\n- **Test Coverage:** 15+ new unit test suites covering sync routes, WebSocket bridge, compliance index, GLM provider config, cooldown-aware retry, safe outbound fetch, stream utilities, Codex executor, provider validation branches, model cross-proxy compatibility, and model alias seeding\n- **TypeScript Migration:** Finalized migration of remaining JS tests (`proxy-load` and `testFromFile`) to TypeScript ES modules, ensuring a fully synchronized TS stack.\n- **Reliability & Resilience:** Added exponential backoff to `models.dev` auto-sync to combat transient network failures, raised interval floor to 1 hour, and added LKGP debug logging for enhanced observability during routing. (#1286)\n\n---\n\n## [3.6.5] — 2026-04-13\n\n### ✨ New Features\n\n- **Antigravity AI Credits Fallback:** Automatically retries with `GOOGLE_ONE_AI` credit injection when free-tier quota is exhausted. Per-account credit balance (5-hour TTL) is cached from SSE `remainingCredits` and exposed as a numeric badge in the Provider Usage dashboard (#1190 — thanks @sFaxsy)\n- **Claude Code Native Parity:** Full header/body signing parity with the Claude Code 2.1.87 OAuth client — CCH xxHash64 body signing with singleton WASM initialization promise (fixing race conditions), dynamic per-request fingerprint, bidirectional TitleCase ↔ lowercase tool name remapping (14 tools), API constraint enforcement (`temperature=1` for thinking, max 4 `cache_control` blocks, auto-inject ephemeral on last user message), and optional ZWJ obfuscation. Wired into `BaseExecutor` for automatic CCH signing on all `anthropic-compatible-cc-*` providers and into `chatCore` for synchronous parity pipeline steps (#1188 — thanks @RaviTharuma)\n- **Per-Connection Codex Defaults:** Codex Fast Service Tier and Reasoning Effort settings are now per-connection instead of a single global toggle. Existing connections are migrated automatically on startup via an idempotent backfill migration (#1176 — thanks @rdself)\n- **Cursor Usage Dashboard:** New `getCursorUsage()` fetches quotas from Cursor's `/api/usage`, `/api/auth/me`, and `/api/subscription` endpoints. Displays standard requests, on-demand usage, and per-plan limits (Free/Pro/Business/Team). Client version bumped to `3.1.0` and `x-cursor-user-agent` header added for parity\n- **Database Health Check System:** Automated periodic SQLite integrity monitoring via `runDbHealthCheck()` — detects orphan quota/domain rows, broken combo references, stale snapshots, and invalid JSON state. Runs every 6 hours (configurable via `OMNIROUTE_DB_HEALTHCHECK_INTERVAL_MS`), with auto-repair and pre-repair backup. Exposed as **MCP tool #18** (`omniroute_db_health_check`) with Zod schemas and `autoRepair` option. Dashboard panel in Health page with status card, issue count, repaired count, and one-click repair button\n- **OpenAI Responses API Store Opt-In:** Per-connection `openaiStoreEnabled` flag controls whether the `store` field is preserved or forced to `false` on Codex Responses API requests. When enabled, `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields are round-tripped through the Chat Completions → Responses translation, enabling multi-turn context caching on supported providers\n- **Email Privacy Toggle (Combos Page):** Global email visibility toggle (`EmailPrivacyToggle`) added to the Combos page header with responsive layout, tooltip guidance, and per-connection label masking via `pickDisplayValue()`. All combo builder options, provider connection lists, and quota screens now respect the global privacy state from `emailPrivacyStore`\n- **skills.sh Integration:** Added `skills.sh` as an external skill provider. Users can now search, browse, and install agent skills directly from a new \"skills.sh\" tab in the Skills dashboard. Includes backend API resolvers, frontend implementation with search/install states, and a dedicated unit test suite (#1223 — thanks @RaviTharuma)\n- **Stabilization Settings:** Added persistence support for `lkgpEnabled` and `backgroundDegradation` settings, integrated into `instrumentation-node.ts` for improved lifecycle awareness (#1212)\n- **xxhash-wasm dependency:** Added `xxhash-wasm@^1.1.0` for CCH signing (xxHash64 with seed `0x6E52736AC806831E`)\n\n### 🐛 Bug Fixes\n\n- **Codex `stream: false` via Combo (ALL_ACCOUNTS_INACTIVE):** Fixed a critical bug where Codex combos returned `ALL_ACCOUNTS_INACTIVE` or empty content when the client sent `stream: false`. Root cause was triple: (1) `CodexExecutor.transformRequest()` mutated `body.stream` in-place to `true`, contaminating the combo's quality check which skipped validation thinking it was streaming; (2) the non-stream SSE parser used the wrong format (Chat Completions instead of Responses API) for Codex SSE output; (3) combo quality validation read the mutated `body.stream` instead of the client's original intent. Fixed by: cloning the body via `structuredClone()` in CodexExecutor, detecting Codex/Responses SSE format in the non-stream fallback path (with auto-translation back to Chat Completions), and capturing `clientRequestedStream` before the combo loop\n- **Gemini CLI Tool Schema Rejection:** Fixed 400 Bad Request errors from the Google API by strictly filtering non-standard vendor extensions (starting with `x-`) and `deprecated` fields from tool parameter schemas (#1206)\n- **SOCKS5 Proxy Interop (Node.js 22):** Resolved `invalid onRequestStart method` crashes caused by `undici` version mismatches between dispatchers and the built-in fetch. Hardened `proxyFetch.ts` to strictly use the library's fetch implementation for custom dispatchers (#1219)\n- **Search Cache Coalescing with TTL=0:** Fixed a bug where providers configured with `cacheTTLMs: 0` (caching explicitly disabled) still had concurrent requests coalesced and returned `{ cached: true }`. Now each call gets its own independent upstream fetch (#1178 — thanks @sjhddh)\n- **Antigravity Credit Cache Alignment (PR #1190):** Reconciled `accountId` derivation between `AntigravityExecutor.collectStreamToResponse` and `getAntigravityUsage` to use consistent cache keys (`email || sub || \"unknown\"`). Previously, SSE-parsed credit balances could be written under a different key than the one read by the usage dashboard, causing stale/missing credit badges\n- **Non-streaming reasoning_content Duplication:** Fixed clients rendering duplicated reasoning panels when both `reasoning_content` and visible `content` were present in non-streaming responses. `responseSanitizer` now strips `reasoning_content` from messages that already have visible text content, preserving it only for reasoning-only messages\n- **Streaming Regression Fix:** Hardened the `sanitize` TransformStream in the combo engine to strip both literal and JSON-escaped newline sequences, eliminating leading `\\n\\n` prefixes in assistant responses (#1211)\n- **Gemini Empty Choice Fix:** Ensured initial assistant deltas always include an empty `content: \"\"` string to satisfy strict OpenAI client requirements and prevent empty choice responses in tools (#1209)\n- **Gemini Tools Sanitizer Deduplication:** Extracted shared tool conversion logic into `buildGeminiTools()` helper (`geminiToolsSanitizer.ts`), eliminating duplicate implementations between `openai-to-gemini.ts` and `claude-to-gemini.ts`. The new helper correctly handles `web_search` / `web_search_preview` tool types by emitting `googleSearch` tools with priority over function declarations\n- **Qwen/Qoder Thinking+Tool_Choice Conflict:** Added `sanitizeQwenThinkingToolChoice()` to both `DefaultExecutor` (for Qwen provider) and `QoderExecutor` to prevent provider-side 400 errors when clients send `tool_choice` alongside thinking/reasoning parameters that are mutually exclusive upstream\n- **API Key Deletion Orphan Cleanup:** Deleting an API key now also removes associated `domain_budgets` and `domain_cost_history` rows, preventing orphan data accumulation\n- **CC-compatible test assertion:** Fixed pre-existing test that expected no `cache_control` on system blocks — the billing header system block now carries `cache_control: { type: \"ephemeral\" }` per PR #1188 design\n- **Codex Combo Smoke Test False Positives:** Fixed combo tests incorrectly reporting `ERROR` for valid Codex streaming responses when `response.output` is empty but text deltas were emitted. The summary now falls back to accumulated delta text (#1176 — thanks @rdself)\n- **Electron Builder Version Mismatch:** Fixed Electron desktop startup failures on Windows packaged builds caused by native modules (`better-sqlite3`) being under `app.asar.unpacked` while helpers were in `app/node_modules`. `resolveServerNodePath()` now merges both locations with deduplication and existence checks (#1172 — thanks @backryun)\n\n### 🔧 Internal Improvements\n\n- **SSE Parser: Responses API Non-Stream Conversion:** Added full `parseSSEToResponsesOutput()` implementation in `sseParser.ts` (255+ lines) — reconstructs complete Responses API objects from SSE event streams, handling `response.output_text.delta/done`, `response.reasoning_summary_text.delta/done`, `response.function_call_arguments.delta/done`, and terminal events. Used by the new chatCore non-stream fallback path for Codex\n- **Cursor Executor Version Sync:** Updated Cursor client User-Agent to `3.1.0` and centralized version constants (`CURSOR_CLIENT_VERSION`, `CURSOR_USER_AGENT`) for consistent fingerprinting across executor, usage fetcher, and OAuth flows\n- **Responses API Translator Parity:** `convertResponsesApiFormat()` now accepts credentials and passes them through to the translator, enabling store-aware field propagation. Round-trip preservation of `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields\n- **Provider Schema Validation:** Added `openaiStoreEnabled` boolean validation to `providerSpecificData` Zod schema\n- **Combo Error Response Normalization:** Empty combo targets now return 404 (`comboModelNotFoundResponse`) instead of generic 503, improving client-side error differentiation\n- **Dependency Updates:** Bumps `typescript-eslint` to `8.58.2` (dev), `axios` to `1.15.0` (prod), and `next` to `16.2.2` (prod) (#1224, #1225)\n\n### ⚠️ Breaking Changes\n\n- **`DELETE /api/settings/codex-service-tier` removed:** This endpoint no longer exists. Codex Service Tier configuration has moved to per-connection `providerSpecificData.requestDefaults`. Existing connections are migrated automatically on first startup after upgrade. Any external scripts or integrations that call this endpoint should be updated — use `PUT /api/providers/:id` with `providerSpecificData.requestDefaults.serviceTier` instead (#1176).\n- **CCH signing on CC-compatible providers:** All requests to `anthropic-compatible-cc-*` providers now include an xxHash64 integrity token (`cch=...`) in the billing header. Providers that do not validate CCH will ignore it (no behavioral change), but any custom middleware inspecting the billing header should expect a 5-character hex token instead of the `00000` placeholder\n\n---\n\n## [3.6.4] — 2026-04-12\n\n### ✨ New Features\n\n- **Combo Builder v2 (Wizard UI):** Completely redesigned the combo creation/editing interface as a multi-stage wizard with stages: Basics → Steps → Strategy → Review. The builder fetches provider, model, and connection metadata via a new `GET /api/combos/builder/options` endpoint, enabling precise provider/model/account selection with duplicate detection and automatic next-connection suggestion. Heavy UI components (`ModelSelectModal`, `ProxyConfigModal`, `ModelRoutingSection`) are now lazily loaded via `next/dynamic` for faster initial page render\n- **Combo Step Architecture (Schema v2):** Introduced a structured step model (`ComboModelStep`, `ComboRefStep`) replacing the legacy flat string/object combo entries. Steps carry explicit `id`, `kind`, `providerId`, `connectionId`, `weight`, and `label` fields, enabling pinned-account routing, cross-combo references, and per-step metrics. All combo CRUD operations normalize entries through the new `src/lib/combos/steps.ts` module. Zod schemas updated with `comboModelStepInputSchema` and `comboRefStepInputSchema` unions\n- **Composite Tiers System:** Added tiered model routing via `config.compositeTiers` — each tier maps a named stage to a specific combo step with optional fallback chains. Includes comprehensive validation (`src/lib/combos/compositeTiers.ts`) ensuring step existence, preventing circular fallback, and validating default tier references. Zod schema enforcement blocks composite tiers on global defaults (concrete combos only)\n- **Model Capabilities Registry:** Created `src/lib/modelCapabilities.ts` providing `getResolvedModelCapabilities()` — a unified resolver that merges static specs, provider registry data, and live-synced capabilities into a single `ResolvedModelCapabilities` object covering tool calling, reasoning, vision, context window, thinking budget, modalities, and model lifecycle metadata\n- **Observability Module:** Extracted health and telemetry payload construction into `src/lib/monitoring/observability.ts` with `buildHealthPayload()`, `buildTelemetryPayload()`, and `buildSessionsSummary()` builders. The health endpoint now returns session activity, quota monitor status, and per-provider breakdowns alongside existing system metrics\n- **Session & Quota Monitor Dashboard:** Added live Session Activity and Quota Monitors panels to the Health dashboard, showing active session counts, sticky-bound sessions, per-API-key breakdowns, and top session details alongside quota monitor alerting/exhausted/error status with per-provider drill-down\n- **Combo Health Per-Target Analytics:** The combo-health API now resolves per-target metrics using the new `resolveNestedComboTargets()` function, providing step-level success rates, latency, and historical usage breakdowns per execution key — enabling per-account, per-connection health visibility\n- **Auto-Combo → Combos Unification:** Merged the separate `/dashboard/auto-combo` page into the main `/dashboard/combos` page. Auto/LKGP combos are now managed alongside all other combos with a new strategy filter tabs system (All / Intelligent / Deterministic). The old auto-combo route redirects to `/dashboard/combos?filter=intelligent`. Removed the `auto-combo` sidebar entry, consolidating navigation into the single `Combos` item\n- **Intelligent Routing Panel (`IntelligentComboPanel`):** New inline panel (371 lines) within the combos page that shows real-time provider scores, 6-factor scoring breakdown (quota, health, cost, latency, task fitness, stability), mode pack selector, incident mode status, and excluded providers for `auto`/`lkgp` combos — replacing the former standalone auto-combo dashboard\n- **Builder Intelligent Step (`BuilderIntelligentStep`):** New conditional wizard step (280 lines) that appears in the Builder v2 flow only when `strategy=auto` or `strategy=lkgp` is selected. Exposes candidate pool selection, mode pack presets, router sub-strategy selector, exploration rate slider, budget cap, and collapsible advanced scoring weights configuration\n- **Intelligent Routing Module (`intelligentRouting.ts`):** Extracted strategy categorization and filtering logic into a dedicated shared module (210 lines) with `getStrategyCategory()`, `isIntelligentStrategy()`, `filterCombosByStrategyCategory()`, `normalizeIntelligentRoutingFilter()`, and `normalizeIntelligentRoutingConfig()` utility functions\n- **LKGP Standalone Strategy:** Implemented `lkgp` (Last Known Good Provider) as a fully functional standalone combo strategy. Previously, `lkgp` as a combo strategy silently fell through to `priority` ordering — the LKGP lookup only ran inside the `auto` engine. Now `strategy: \"lkgp\"` correctly queries the LKGP state, moves the last successful provider to the top of the target list, and saves the LKGP state after each successful request. Falls back to priority ordering when no LKGP state exists\n- **Unified Routing Rules & Model Aliases:** Consolidated the routing rules and model alias management controls into the Settings page, reducing fragmentation across the dashboard\n\n### ⚡ Performance\n\n- **Middleware Lazy Loading:** Refactored `src/proxy.ts` to lazy-import `apiAuth`, `db/settings`, and `modelSyncScheduler` modules, reducing middleware cold-start overhead. Added inline `isPublicApiRoute()` to avoid loading the full auth module for public routes\n- **E2E Auth Bypass:** Added `NEXT_PUBLIC_OMNIROUTE_E2E_MODE` environment flag to bypass authentication gates for dashboard and management API routes during Playwright E2E test runs\n\n### 🐛 Bug Fixes\n\n- **P2C Credential Selection:** Implemented Power-of-Two-Choices (P2C) connection scoring in `src/sse/services/auth.ts` with quota headroom awareness, error/recency penalties, and forced/excluded connection support. The new `getProviderCredentialsWithQuotaPreflight()` function integrates quota preflight checks directly into credential selection, eliminating the separate Codex-only preflight path\n- **Fixed-Account Combo Steps:** Combo steps with explicit `connectionId` now correctly bypass provider-level model cooldowns and circuit breakers, preventing a single account failure from blocking pinned-connection routing for the same model\n- **Combo Metrics Per-Target Tracking:** Extended `comboMetrics.ts` to track `byTarget` metrics keyed by execution path, recording per-step `provider`, `providerId`, `connectionId`, and `label` alongside existing per-model aggregates\n- **Call Logs Schema Expansion:** Added `requested_model`, `request_type`, `tokens_cache_read`, `tokens_cache_creation`, `tokens_reasoning`, `combo_step_id`, and `combo_execution_key` columns to `call_logs` with auto-migration. Added composite index `idx_cl_combo_target` for efficient per-target historical queries\n- **Quota Monitor Enrichment:** Expanded `quotaMonitor.ts` with full lifecycle state tracking (`status`, `startedAt`, `lastPolledAt`, `consecutiveFailures`, `totalPolls`, `totalAlerts`), ISO-formatted snapshots via `getQuotaMonitorSnapshots()`, and sorted summary via `getQuotaMonitorSummary()`\n- **Codex Quota Fetcher Hardening:** Improved `codexQuotaFetcher.ts` with safer connection registration and quota fetch error handling\n- **LKGP Save Refactored to Async/Await:** Replaced fire-and-forget `.then()` chain for LKGP persistence after successful combo routing with proper `async/await` + `try/catch`, preventing unhandled promise rejections and ensuring LKGP state is reliably saved before the response is returned\n- **Duplicate `auto` in Combo Strategy Schema:** Removed duplicate `\"auto\"` entry from `comboStrategySchema` (was listed on both line 104 and 108). Harmless to Zod runtime but cleaned up to avoid confusion. Schema now has exactly 13 unique strategy values\n- **Legacy Combo Refs Normalization:** Fixed combo step normalization to preserve legacy string combo references during CRUD operations, preventing data loss when editing combos created before the v2 step architecture\n\n### Sicurezza\n\n- **Auth Bypass on Backup Routes (Critical):** Added `isAuthenticated` guards to `/api/db-backups/exportAll` (full database export) and `/api/db-backups` (list, create, and restore backups) — both were previously accessible without authentication\n- **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency\n- **API Key Secret Hardening:** Removed the hardcoded `\"omniroute-default-insecure-api-key-secret\"` fallback from `apiKey.ts` — the function now fails fast if `API_KEY_SECRET` is unset, relying on the startup validator to auto-generate it\n- **NPM Tarball Leak Fix:** Added `app/.env*` to `.npmignore` to prevent the working `.env` file from being shipped inside the npm tarball distribution\n- **Electron Builder CVE Fix:** Bumped `electron-builder` to 26.8.1 to resolve `tar` CVEs in the desktop build pipeline\n\n### 🔧 Maintenance & Infrastructure\n\n- **DB Migration 021:** Added `combo_call_log_targets` migration for `combo_step_id` and `combo_execution_key` columns in call_logs\n- **Combo CRUD Normalization:** `db/combos.ts` now normalizes all stored combo entries through the step normalization pipeline on read, ensuring consistent step IDs and kind annotations regardless of when the combo was created\n- **Playwright Config:** Updated Playwright configuration and `run-next-playwright.mjs` script for improved E2E test orchestration\n- **Build Script:** Updated `build-next-isolated.mjs` with additional reliability improvements\n- **Auto-Combo UI Cleanup:** Deleted `AutoComboModal.tsx` (161 lines), replaced `auto-combo/page.tsx` (478→5 lines) with a server-side redirect to `/dashboard/combos?filter=intelligent`\n- **Sidebar Consolidation:** Removed `\"auto-combo\"` from `HIDEABLE_SIDEBAR_ITEM_IDS` and `PRIMARY_SIDEBAR_ITEMS` — `normalizeHiddenSidebarItems()` silently discards any stale `\"auto-combo\"` entries in user settings\n- **Schema Cleanup:** Removed obsolete `createAutoComboSchema` from `schemas.ts`. Exported `comboStrategySchema` for direct use in test and filter modules\n- **A2A Agent Card Update:** Renamed skill ID from `auto-combo` to `intelligent-routing` with updated description referencing the unified combos dashboard\n- **Builder Draft Refactor:** Extended `builderDraft.ts` with dynamic stage list generation via `getComboBuilderStages()` and `isIntelligentBuilderStrategy()`. Stage navigation (`getNextComboBuilderStage`, `getPreviousComboBuilderStage`, `canAccessComboBuilderStage`) now accepts options to conditionally include/skip the `intelligent` wizard step\n- **i18n Consolidation:** Removed the standalone `\"autoCombo\"` i18n block (22 keys) from all 30 language files. Migrated keys into the `\"combos\"` block with new additions for filter tabs, intelligent panel, and builder step labels\n\n### 🧪 Tests\n\n- **16 New Test Suites:** Added comprehensive test coverage including:\n - `combo-builder-draft.test.mjs` (186 lines) — Builder draft step construction and validation\n - `combo-builder-options-route.test.mjs` (228 lines) — Builder options API endpoint\n - `combo-health-route.test.mjs` (266 lines) — Combo health analytics with per-target metrics\n - `combo-routes-composite-tiers.test.mjs` (157 lines) — Composite tiers API integration\n - `composite-tiers-validation.test.mjs` (131 lines) — Composite tier validation rules\n - `db-combos-crud.test.mjs` — Combo CRUD with step normalization\n - `db-core-init.test.mjs` (129 lines) — DB initialization and column migrations\n - `model-capabilities-registry.test.mjs` (105 lines) — Model capabilities resolution\n - `observability-payloads.test.mjs` (165 lines) — Health/telemetry payload construction\n - `openapi-spec-route.test.mjs` — OpenAPI spec generation\n - `proxy-e2e-mode.test.mjs` (74 lines) — E2E mode auth bypass\n - `quota-monitor.test.mjs` — Quota monitor lifecycle state\n - `run-next-playwright.test.mjs` (119 lines) — Playwright runner script\n - `sse-auth.test.mjs` (154 lines) — P2C credential selection and quota preflight\n - `telemetry-summary-route.test.mjs` (35 lines) — Telemetry summary endpoint\n - Plus updates to 12 existing test files for compatibility with new step architecture\n- **Auto-Combo Unification Tests:**\n - `autocombo-unification.test.mjs` (156 lines) — Strategy categorization, schema deduplication, sidebar cleanup, and routing strategies metadata validation\n - `combo-unification.spec.ts` (189 lines) — Playwright E2E tests for filter tabs, intelligent panel rendering, redirect from old route, sidebar entry removal, and Builder v2 intelligent step flow\n - 3 new LKGP standalone tests in `combo-routing-engine.test.mjs` — Validates LKGP provider prioritization, fallback to priority when no state exists, and LKGP state persistence after successful requests\n - Updated `combo-builder-draft.test.mjs` with intelligent stage navigation tests\n - Updated `sidebar-visibility.test.mjs` to reflect `auto-combo` removal\n\n---\n\n## [3.6.3] — 2026-04-11\n\n### ✨ New Features\n\n- **OpenAI-Compatible Loose Validation:** Empty API keys can now be naturally submitted and saved for any `openai-compatible-*` providers (e.g. Pollinations, localized routes) directly in the UI instead of blocking save actions (#1152)\n- **Cloudflare Configuration:** Updated the provider schema and UI integration for Cloudflare AI to officially expose and support the backend `accountId` field securely without overrides (#1150)\n\n### 🐛 Bug Fixes\n\n- **Vertex JSON Validation Crash:** Prevented `invalid character in header` crashes inside the `/validate` endpoint by creating a native authentication parser that correctly handles Google Identity Service Account JSON flows prior to pinging endpoints (#1153)\n- **Extraneous Payload Rejection:** Globally prevented upstream `400 Bad Request` execution crashes by stripping the non-standard `prompt_cache_retention` attribute forcibly attached by Cursor/Cline IDE engines when targeting strict OpenAI/Anthropic routes (#1154)\n- **Reasoning Content Drop:** Prevented pure reasoning packets, common in advanced fallback models like DeepSeek, from being aborted mid-stream by explicitly adjusting the `Empty Content (502)` circuit breakers to acknowledge `reasoning_content` states as valid (#1155)\n- **Desktop Windows Build Crash:** Fixed `better_sqlite3.node is not a valid Win32 application` preventing OmniRoute Desktop from launching on Windows by properly removing the ABI-mismatched sqlite cache from Next.js standalone and falling back to the cross-compiled Electron equivalent during packager build steps (#1163)\n- **Login Visual Security:** Removed the raw fallback hash dump that artificially rendered underneath the login modal in Docker instances missing `OMNIROUTE_API_KEY_BASE64` flags (#1148)\n\n### 🔧 Maintenance & Dependencies\n\n- **Dependabot Updates:** Safely bumped GitHub Actions `docker/build-push-action` to v7 and `actions/download-artifact` to v8\n- **Electron Updates:** Upgraded desktop wrapper core to Electron `41.2.0` and `electron-builder` to `26.8.1`, incorporating essential V8/Chromium security patches\n- **NPM Package Groups:** Updated `production` and `development` NPM groups to securely handle minor audit warnings and keep toolchains modern\n- **CI/CD Reliability:** Fixed persistent `Snyk` token-absence failures on automated pull requests by appropriately bypassing on dependabot actions\n\n## [3.6.2] — 2026-04-11\n\n### ✨ New Features\n\n- **33 New API Key Providers:** Massive provider expansion adding DeepInfra, Vercel AI Gateway, Lambda AI, SambaNova, nScale, OVHcloud AI, Baseten, PublicAI, Moonshot AI, Meta Llama API, v0 (Vercel), Morph, Featherless AI, FriendliAI, LlamaGate, Galadriel, Weights & Biases Inference, Volcengine, AI21 Labs, Venice.ai, Codestral, Upstage, Maritalk, Xiaomi MiMo, Inference.net, NanoGPT, Predibase, Bytez, Heroku AI, Databricks, Snowflake Cortex, and GigaChat (Sber). OmniRoute now supports **100+ providers** (4 Free + 8 OAuth + 91 API Key + Custom compatible)\n- **Global Email Privacy Toggle:** Added a persistent eye-icon toggle button across all dashboard pages (Providers, Usage Limits, Playground) that reveals or hides masked email addresses. Toggle state is stored in localStorage and synced globally via Zustand store\n- **Documentation Refresh:** Updated README, ARCHITECTURE, FEATURES, AGENTS.md, and API_REFERENCE for v3.6.2 with accurate provider counts (100+), new executor list, and system API documentation\n- **Uninstall Guide:** Created comprehensive `docs/UNINSTALL.md` covering clean uninstallation for all deployment methods (npm, Docker, Electron, source)\n\n### 🐛 Bug Fixes\n\n- **PDF Attachments:** Unlocked deep string object parsing (`geminiHelper`) ensuring Gemini translation successfully passes complex PDF payloads from OpenAI-compatible streams without dropping them silently (#993)\n- **SkillsMP Engine:** Corrected object extraction path mappings inside the API router to fix UI marketplace rendering under Docker/Standalone Node isolated deployments (#988)\n\n---\n\n## [3.6.1] — 2026-04-10\n\n### ✨ New Features\n\n- **OAuth Env Repair Action:** Added a \"Repair env\" button to the OAuth Providers dashboard that detects and restores missing OAuth client IDs from `.env.example` — with timestamped backup and append-only safety. Includes full 33-language i18n support and sanitized API responses (#1116, by @yart)\n\n### 🐛 Bug Fixes\n\n- **i18n: Missing Provider Keys:** Added missing `filterModels`, `modelsActive`, `showModel`, `hideModel` keys across all 32 locale files, fixing runtime `MISSING_MESSAGE` errors in the providers UI. Also cleaned up duplicate keys in `en.json` (#1111, by @rilham97)\n- **GPT-5.4 Routing:** Added missing `targetFormat: \"openai-responses\"` to `gpt-5.4` and `gpt-5.4-mini` models in both the Codex and GitHub Copilot providers, fixing `[400]: model not accessible via /chat/completions` errors (#1114, by @ask33r)\n\n---\n\n## [3.6.0] — 2026-04-10\n\n### ✨ New Features & Analytics\n\n- **Combo Smoke Test:** Raised the default token budget to 2048 to prevent truncation of thinking models during preflight checks, and fully randomized the arithmetic probe prompt to bypass deterministic caching from upstream relays (#1105)\n\n### 🐛 Bug Fixes & Compliance\n\n- **DB Bloat / Row Limits:** Added `CALL_LOGS_TABLE_MAX_ROWS` and `PROXY_LOGS_TABLE_MAX_ROWS` (default: 100,000) to the backend DB compliance cleaner to prevent runaway SQLite growth. Limits are enforced automatically on the TTL cycle (#1104, fixes #1101)\n- **HTML Error Handling:** The router now correctly identifies unexpected HTML responses (e.g. ``) sent by upstream providers (like Azure/Copilot) instead of throwing obscure `Unexpected token '<'` JSON parse errors, bubbling up a clean 502 Bad Gateway (#1104, fixes #1066)\n- **Android/Termux SQLite Native Support:** `better-sqlite3` is now correctly built from source with cross-compilation flags in ARM64 local Termux deployments without failing on missing prebuilt binaries (#1107)\n\n---\n\n## [3.5.9] — 2026-04-09\n\n### ✨ New Features\n\n- **Persistent Combo Ordering:** Drag combo cards by handle to reorder them in the dashboard; order is persisted to SQLite via a new `sort_order` column and `POST /api/combos/reorder` endpoint. Includes DB migration `020_combo_sort_order.sql` and JSON import preservation (#1095)\n- **Sidebar Group Reorder:** Moved \"Logs\" before \"Health\" in the System section and \"Limits & Quotas\" after \"Cache\" in the Primary section for a more logical navigation flow (#1095)\n\n### 🐛 Bug Fixes\n\n- **Stream Failure Surfacing:** Upstream `response.failed` events (e.g. Codex rate-limit errors) are now properly surfaced as non-200 errors instead of being silently swallowed as empty 200 OK streams. Rate-limit failures return HTTP 429 (#1098, closes #1093)\n- **Upstream Model Preservation:** The Responses-to-OpenAI stream translator now preserves the actual upstream model (e.g. `gpt-5.4`) instead of hardcoding a `gpt-4` fallback (#1098, closes #1094)\n- **Docker EXDEV Fix:** `build-next-isolated.mjs` now falls back from `fs.rename()` to `cp/rm` when Docker buildx raises `EXDEV` (cross-device link), unblocking the Docker image publish workflow (#1097)\n- **macOS CLI Path Resolution:** `cliRuntime.ts` resolves symlink parents with `fs.realpath()` to handle macOS `/var` → `/private/var` chains, preventing false `symlink_escape` rejections (#1097)\n- **Request Log Token Layout:** Split token badges into separate Input (Total In, Cache Read, Cache Write) and Output (Total Out, Reasoning) groups for clearer readability; renamed \"Time\" label to \"Completed Time\" (#1096)\n\n---\n\n## [3.5.8] — 2026-04-09\n\n### ✨ New Features & Analytics\n\n- **Analytics Layout Redesign:** Replaced flat metrics with a responsive `CompactStatGrid`, grouping data visually across sections (#1089)\n\n### 🐛 Bug Fixes\n\n- **Build Core:** Force Turbopack cleanup via Prepbulish script to prevent Next.js 16 app/ routing conflicts on runtime.\n- **Provider Quarantine:** Introduces model/provider circuit-breakers with adaptive TTL exponential backoff for recurring upstream errors (#1090)\n- **Oauth Keep-Alive:** Safely protects authenticated active accounts against spontaneous dropping from router due to transient token refresh failures (#1085)\n\n### 🔒 Security & Maintenance\n\n- **Dependabot:** bumped axios from 1.14.0 to 1.15.0 addressing SSRF flags (#1088)\n\n---\n\n## [3.5.7] — 2026-04-09\n\n### 🐛 Bug Fixes & Security\n\n- **Turbopack Standalone Chunks:** Fixed a critical bug in `scripts/prepublish.mjs` where Turbopack chunks missing from the `.next/standalone` trace resulted in a `500 ChunkLoadError` (e.g., `_not-found` page crash) during production deployments via NPM or Docker. Standalone chunks are now explicitly copied and correctly stripped of Turbopack hashes.\n\n---\n\n## [3.5.6] — 2026-04-09\n\n### ✨ New Features\n\n- **Email Privacy Masking:** OAuth account emails are now masked in the provider dashboard (e.g. `di*****@g****.com`) to prevent accidental exposure when sharing screenshots. Full address visible on hover via `title` attribute (#1025).\n- **OpenRouter & GitHub in Embedding/Image Registries:** OpenRouter (3 embedding models, 4 image models) and GitHub Models (2 embedding models via Azure inference) are now first-class entries in the provider registries, enabling their use for `/v1/embeddings` and `/v1/images/generations` (#960).\n- **Model Visibility Toggle & Search Filter:** The provider page model list now includes a real-time search/filter bar and a per-model visibility toggle (👁 icon). Hidden models are grayed out and excluded from the `/v1/models` catalog. An active-count badge (`N/M active`) shows at a glance how many models are enabled (#750).\n- **Chinese Localization (zh-CN):** Added missing translations for Context Relay, Memory, LKGP, and Models.dev sync features, while standardizing terminology across the application (#1079).\n- **Environment Auto-Sync:** Added `sync-env.mjs` to auto-generate and append `.env` from `.env.example` during installation, automatically generating cryptographic secrets on first run.\n- **Source Mode Dashboard Update:** Fixed real-time Source (git-checkout) updating in the dashboard, enabling secure, real-time update pipelines for non-NPM installations.\n\n### 🐛 Bug Fixes & Security\n\n- **Hardcoded Secret Cleanup:** Removed 12 hardcoded OAuth credential fallbacks from the source code, forcing secure reliance on environment variables and resolving static analysis security alerts.\n- **Next.js Security Patch:** Bumped `next` from 16.2.2 to 16.2.3 to resolve critical RSC deserialization RCE vulnerability (SNYK-JS-NEXT-15954202).\n- **Memory/Cache UI Crash:** Added null-safety guards (`?? 0`) to `.toLocaleString()` calls in Memory and Cache dashboard pages, preventing `TypeError` crashes when database tables are empty or contain null numeric values (#1083).\n- **WebSearch tool_choice Translation:** Fixed OpenAI-to-Claude translator dropping `tool_choice` objects with `type: \"function\"` as-is, which Claude rejects. Now properly maps all OpenAI `tool_choice` variants (`function`, `required`, `none`) to Claude-compatible format (`tool`, `any`, `auto`), fixing \"Did 0 searches\" in Claude Code WebSearch (#1072).\n- **Provider Validation baseUrl Override:** Added `baseUrl` passthrough from frontend validation requests to the backend validation endpoint. Chinese-site users of Alibaba Coding Plan (bailian-coding-plan) can now validate API keys against their custom Base URL instead of always hitting the international endpoint (#1078).\n- **Minimax Auth Header:** Switched Minimax provider from `x-api-key` to `Authorization: Bearer` header format, matching the current API spec (#1076).\n- **Native Fetch Fallback:** Added graceful fallback to native `fetch` when the `undici` dispatcher fails, improving resilience in environments where undici is unavailable (#1054).\n- **EPIPE Flood Fix:** Added circuit-breaker logic to prevent EPIPE errors from creating a feedback loop that fills logs at GB/s (#1006).\n- **Qoder PAT Validation:** Improved Qoder Personal Access Token validation with actionable error messages that guide users to the correct token format (#966).\n- **CI/CD Pipeline:** Fixed `check:docs-sync` failure by syncing OpenAPI version to 3.5.6 and finalizing CHANGELOG release heading. Commented out `DATA_DIR` in `.env.example` to prevent E2E test failures in CI runners lacking root permissions.\n\n### 🌍 i18n\n\n- **Auto Language Generation (CI):** Added CI pipeline to auto-generate missing language files and strings via `feat(CI,i18n)` workflow, covering 30+ locales (#1071).\n\n---\n\n## [3.5.5] — 2026-04-08\n\n### ✨ New Features\n\n- **Node.js 24 Compatibility Warning:** Added a proactive version incompatibility warning on the login page to guide users to the stable Node.js 22 LTS, preventing native sqlite binding crashes.\n- **Context Relay Combo Strategy:** Added the new `context-relay` combo strategy with priority-style routing, structured handoff summary generation once quota usage reaches the warning threshold, and handoff injection after the next real account switch.\n- **Global Context Relay Defaults:** Added global Settings defaults plus combo-level configuration for `handoffThreshold`, `handoffModel`, and `handoffProviders`, so new or unconfigured combos can inherit the feature consistently.\n\n### 🐛 Bug Fixes\n\n- **Proxy Connection Healthchecks:** Applied proxy resolution per connection in the sweeping loop (`tokenHealthCheck.ts`) and global provider validation sweeps, resolving Node 22 bypass and improving proxy stability (#1051, #1056, #1061).\n- **Security Vulnerability Remediation:** Resolved multiple CodeQL scanning alerts including SSRF in model sync, insecure randomness in web crypto (`generateSessionId`), and incomplete URL sanitization.\n- **Context Relay Typing & Synchronization:** Reverted out-of-scope test breakages and resolved `handoffProvider` and response `input` extraction payload typing.\n- **Legacy OpenAI-Compatible Responses Routing:** Fixed legacy/imported OpenAI-compatible providers (for example `openai-compatible-sp-openai`) incorrectly routing Chat Completions traffic to `/chat/completions` when the real provider node was configured as `apiType: \"responses\"`. OmniRoute now treats `providerSpecificData.apiType` as authoritative across routing, executors, and translator tools, avoiding false empty-content failures during combo/provider smoke tests (#1069).\n- **Gemini PDF Attachment Integration:** Fixed payload generation and format for parsing `inline_data` and generic base64 sources for deep Gemini PDF routing (#993, #1021).\n- **Vercel AI SDK Fallbacks:** Mapped `max_output_tokens` to `max_tokens` for strict OpenAI-compatible providers, resolving errors from standard AI agents and frameworks (#994).\n- **External Auth & UI Reliability:** Handled null `state` failures in Cline OAuth exchange (#1016), added 3rd-party 400 error patterns to combo fallback (#1024), and resolved desktop sidebar layout and popover overflows (#1039, #1001).\n- **Context Relay In-Flight Deduplication:** Prevented duplicate handoff generation for the same session/combo while an earlier summary request is still in flight.\n- **Context Relay Provider Gating:** Aligned runtime behavior with configuration so explicit `handoffProviders` exclusions, including an empty array, now disable handoff generation as expected.\n\n### 🛠️ Maintenance & Dependabot\n\n- **Updated Sub-dependencies:** Bumped `hono` to `4.12.12` and `@hono/node-server` to `1.19.13` to patch critical security gaps (#1063, #1064, #1067, #1068).\n\n### Documentazione\n\n- **Documentation Synchronization:** Updated system documentation (README, Architecture, Features, Tools, Troubleshooting) and synced `i18n` configurations to match the v3.5.5 context relay patterns and proxy troubleshooting steps.\n- **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance.\n\n---\n\n## [3.5.4] — 2026-04-07\n\n### ✨ New Features\n\n- **Detailed Token Tracking:** Added granular token breakdown columns (cache read, cache write, reasoning) to call logs with proper null vs zero distinction. Includes DB migration 018 and 5-label UI display per provider capability (#1017 — thanks @rdself).\n- **Legacy JSON Config Import/Export:** Restored JSON-based settings export and import for migration from legacy 9router configurations. Security-hardened with Zero-Trust redaction of passwords and `requireLogin` fields, and automatic pre-import database backups (#1012 — thanks @luandiasrj).\n- **Non-Stream Aliases:** Added API support for explicit non-streaming aliases (`non_stream`, `disable_stream`, `disable_streaming`, `streaming=false`), normalized at the boundary before provider translation (#1036 — thanks @wlfonseca).\n- **Russian Dashboard Localization:** Comprehensive Russian translation for the dashboard UI, including fixes for 2 Ukrainian locale keys (#1003 — thanks @mercs2910).\n\n### 🐛 Bug Fixes\n\n- **Anthropic Streaming Input Undercount:** Fixed a critical bug where Anthropic streaming `prompt_tokens` only reported non-cached tokens (e.g., `in=3` when actual total was 113,616). Cache tokens are now summed into prompt_tokens during streaming (#1017).\n- **Built-in Responses API Tool Types:** Preserved built-in Responses API tools (`web_search`, `file_search`, `computer`, `code_interpreter`, `image_generation`) from being silently stripped by the empty-name tool filter — these tools carry no `.name` field (#1014 — thanks @rdself).\n- **Cursor/Codex Responses Compatibility:** Fixed empty output in Cursor when using Codex models by hoisting system input items to `instructions`, sanitizing invalid tool names, and detecting Responses-format payloads on chat/completions endpoint (#1002 — thanks @mercs2910).\n- **OAuth Token Expiry Display:** Fixed OAuth connections showing \"expired\" badge even with valid tokens by reading `tokenExpiresAt` (updated on refresh) instead of `expiresAt` (original grant timestamp) (#1032 — thanks @tombii).\n- **Codex Fast-Tier Copy:** Corrected dashboard settings copy from `service_tier=fast` to `service_tier=priority`, matching the actual Codex wire format (#1045 — thanks @kfiramar).\n- **macOS Desktop App Startup:** Stabilized packaged macOS app launch by excluding desktop artifacts from the standalone bundle and improving launch path detection (#1004 — thanks @mercs2910).\n- **macOS Sidebar Layout:** Fixed macOS traffic light overlap, sidebar spacing, and button overflow in the Electron desktop app (#1001 — thanks @mercs2910).\n\n### ⚡ Performance\n\n- **Analytics Page Load:** Dramatically reduced analytics page load times (30s→1-2s for 50K entries) via date-filtered DB queries, parallel `Promise.all()` cost calculations, and merged 6 COUNT queries into a single CASE WHEN aggregate (#1038 — thanks @oyi77).\n\n### 🔒 Security & Dependencies\n\n- **Node Base Image:** Upgraded Docker base from `22-bookworm-slim` to `22.22.2-trixie-slim` (#1011 — Snyk).\n- **Production Dependencies:** Bumped 5 production dependencies (#1044 — Dependabot).\n- **Vite:** Bumped from 8.0.3 to 8.0.5 (#1031 — Dependabot).\n- **Development Dependencies:** Bumped 4 development dependencies (#1030 — Dependabot).\n\n### 🧪 Tests\n\n- **Token Accounting Tests:** Added 18 new unit tests covering detailed token breakdown, null vs zero semantics, per-provider token extraction, and Anthropic streaming input fix (#1017).\n- **Built-in Tool Tests:** Added 3 new test cases for built-in Responses API tool type preservation (#1014).\n- **ChatCore Sanitization:** Updated sanitization tests to accommodate Responses format detection (PR #1002) and built-in tool preservation (PR #1014).\n\n### 🛠️ Maintenance\n\n- **PR Workflow:** Updated `/review-prs` workflow to merge PRs into the release branch (`release/vX.Y.Z`) instead of directly into `main`, ensuring proper pre-release staging.\n\n### Coverage\n\n- **2537 tests, 2532 passing** — Statement coverage: 91.95%, Branch coverage: 78.79%, Function coverage: 93.19%\n\n## [3.5.3] - 2026-04-07\n\n### Sicurezza\n\n- **Vulnerabilities:** Fully remediated 12 High-Severity CodeQL vulnerabilities by migrating from Math.random to `crypto.randomUUID()`, wrapping SSE injection points with aggressive backslash escaping, sanitizing trailing HTTP fragments, and enforcing rigid SSRF HTTP verification schemes across internal routes.\n- **Dependencies:** Upgraded Next.js to `^16.2.2` and Vite to `>=8.0.5` resolving critical DoS, arbitrary file reads and CSRF vectors in the build/server environments.\n\n### Fixed\n\n- **E2E Stability:** Eliminated extreme CI unreliability and transient test timeouts (Playwright) by propagating internal standalone `_next/static` assets properly and refactoring deep UI interactions inside defensive `expect().toPass()` loops.\n- **Middleware:** Resolved infinite redirect loop on dashboard for fresh instances when requireLogin is disabled.\n- **Core Fallbacks:** Preserved primary failure contexts and enhanced Edge-case error handling pipelines across chat and fallback loops.\n- **Proxy/Hooks:** Optimized local git hooks, normalized token coverage endpoints into `/coverage`, and guarded GLM region lookups.\n\n### 🛠️ Maintenance\n\n- **CI/CD Stabilization:** Prevented random GitHub Runner freezes by decoupling sharded processes, adjusting test concurrencies, unref-ing active connections on server teardown, and strictly capping job timeout durations.\n\n### Documentazione\n\n- **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned).\n\n### Coverage\n\n- **Testing:** Consolidated the workspace test coverage framework hitting 92.1% statement line coverage, with new rigid unit-tests matching API key policies and tool scopes.\n\n---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n- **Qoder API Native Integration:** Completely refactored the Qoder Executor to bypass the legacy COSY AES/RSA encryption algorithm, routing directly into the native DashScope OpenAi-compatible URL. Eliminates complex dependencies on Node `crypto` modules while improving stream fidelity.\n- **Resilience Engine Overhaul:** Integrated context overflow graceful fallbacks, proactive OAuth token detection, and empty-content emission prevention (#990).\n- **Context-Optimized Routing Strategy:** Added new intelligent routing capability to natively maximize context windows in automated combo deployments (#990).\n\n### 🐛 Bug Fixes\n\n- **Responses API Stream Corruption:** Fixed deep-cloning corruption where Anthropic/OpenAI translation boundaries stripped `response.` specific SSE prefixes from streaming boundaries (#992).\n- **Claude Cache Passthrough Alignment:** Aligned CC-Compatible cache markers consistently with upstream Client Pass-Through mode preserving prompt caching.\n- **Turbopack Memory Leak:** Pinned Next.js to strict `16.0.10` preventing memory leaks and build staleness from recent upstream Turbopack hashed module regressions (#987).\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **Models.dev Integration:** Integrated models.dev as the authoritative runtime source for model pricing, capabilities, and specifications, overriding hardcoded prices. Includes a settings UI to manage sync intervals, translation strings for all 30 languages, and robust test coverage.\n- **Provider Native Capabilities:** Added support for declaring and checking native API features (e.g. `systemInstructions_supported`) preventing failures by sanitizing invalid roles. Currently configured for Gemini Base and Antigravity OAuth providers.\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Sicurezza\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Funzionalità\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Sicurezza\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicurezza\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicurezza\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Documentazione\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Documentazione\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funzionalità\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funzionalità\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funzionalità\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicurezza\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funzionalità\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funzionalità\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funzionalità\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funzionalità\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funzionalità\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funzionalità\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funzionalità\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funzionalità\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicurezza\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\bany\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funzionalità\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funzionalità\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funzionalità\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funzionalità\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funzionalità\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funzionalità\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Documentazione\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funzionalità\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "e5c4e450c0cd597c2de3d9dde1d74b572c0a6bb3": {"t": 1785765399.09176, "n": 229533, "h": "5c23b70c4c95ab05", "c": "# Changelog (Italiano)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.6.8] — 2026-04-17\n\n### ✨ New Features\n\n- **feat(providers):** Support `xhigh` reasoning tier exclusively on Claude models that expose it (#1356)\n- **feat(providers):** Add CC Compatible connection-level 1M context toggle (#1357)\n- **feat(core):** Add full support for Node.js 24 LTS (Krypton) environments with continuous integration coverage (#1340)\n- **feat(dashboard):** Display Antigravity credit balance in dashboard Limits & Quotas (#1338)\n- **feat(i18n):** Add internationalization support for combo features and dashboard components; sync translations across 31 keys (#1318)\n- **feat(providers):** Add Claude Opus 4.7 to Claude Code OAuth models natively with extended context and caching (#1347)\n- **feat(core):** Add stopSequences support and expand tool definitions to include Google Search capabilities\n- **feat(auth):** Enforce dashboard session authentication on all management API routes, preventing unauthenticated access to configuration endpoints\n- **feat(runtime):** Add hot-reloadable guardrails and model diagnostics for real-time rule evaluation without restarts\n- **feat(core):** Add payload rules, tag-based routing, and scheduled budget systems for fine-grained request governance\n- **feat(providers):** Expose Antigravity preview model aliases and Gemini CLI onboarding flow for first-time setup\n- **feat(antigravity):** Add client model aliases and thoughtSignature bypass modes for Antigravity OAuth connections\n- **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations\n- **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages\n\n### Sicurezza\n\n- **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns\n- **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353)\n- **fix(providers):** Resolve Codex token refresh race condition via mutex `getAccessToken` preventing `refresh_token_reused` Auth0 revocations\n\n### 🔧 Maintenance & Architecture\n\n- **refactor(core):** Split CLI runner and decouple migration engine for extensibility (#1358)\n- **refactor(audit):** Rewire audit dashboard from dead in-memory `configAudit` store to live SQLite `audit_log` table — 331+ hidden compliance entries now visible in `/dashboard/audit`\n- **build(deps):** Bump `softprops/action-gh-release` from v2 to v3\n- **ci:** Bump GitHub Actions CI node-version to Node.js 24 natively\n- **fix(types):** Resolve TypeScript compilation errors in `claudeCodeCompatible.ts` (type predicates, `cache_control` index access) and `proxyFetch.ts` (`signal` nullability)\n\n### 🐛 Bug Fixes\n\n- **fix(context):** Scale reserved context tokens dynamically using a 15% sliding window for smaller models\n- **test(core):** Replace unit test with integration test for proactive context compression to align with isolated runner rules (#1378)\n- **fix(services):** Pass origin provider to refreshWithRetry to avoid tripping the generic \"unknown\" circuit breaker (fixes Codex accounts erroneously disabling)\n- **fix(db):** Prevent native module ABI load crashes from assuming database corruption and skipping databases\n- **fix(db):** Increase mass-migration threshold from 5 to 50 pending migrations to protect legacy users upgrading node\n- **fix(db):** Prevent migration runner safety aborts from triggering on fresh `DATA_DIR` installations by detecting new databases (#1328)\n- **fix(mcp):** Checkpoint and close MCP audit SQLite database safely on process signals and shutdown (#1348)\n- **fix(mcp):** Fully decouple MCP audit SQLite connection caching via globalThis to fix unhandled teardown in standalone Next.js chunks (#1349)\n- **fix(cli):** Avoid creating app router directory during postinstall initialization on non-built source trees (#1351)\n- **fix(codex):** Correctly translate `system` role to `developer` in input array to unlock GPT-5 automatic prompt caching (#1346)\n- **fix(core):** Pass client headers to executor in chatCore (#1335)\n- **fix(providers):** Separate test batch calls and ignore unknown connections\n- **fix(providers):** Add grok-web SSO cookie validation handler (#1334)\n- **fix(db):** Preserve key_value settings (dashboard passwords, saved aliases) across DB heuristic recreation cycles (#1333)\n- **fix(routing):** Allow combo fallback to cascade context overflow 400 errors instead of immediate aborts (#1331)\n- **fix(core):** Resolve thinking leaks, consecutive roles, and missing thoughtSignatures for Antigravity translator (#1316)\n- **fix(translator):** Only apply thoughtSignature to the first `functionCall` part in Gemini parallel tool calls, preventing duplicate signatures\n- **fix(providers):** Default to batch testing execution blocks for web, search, and audio modalities to prevent connection timeouts\n- **fix(cli):** Resolve Node 22 TS entrypoint incompatibility by using esbuild compilation (#1315)\n- **fix(chat):** Preserve max_output_tokens for Responses API targets in chatCore sanitization (#1313)\n- **fix(api):** API Manager usage stats showing 0 for all registered keys (#1310)\n- **fix(api):** Support image-only models in catalog and allow authless search providers to bypass validation requirements\n- **fix(routes):** Require prompts for media generation requests (`/images`, `/videos`, `/music`), returning 400 on missing payloads\n- **fix(dashboard):** Auto-scroll ActivityHeatmap to show current date (#1309)\n- **fix(dashboard):** Restore horizontal layout with `w-max` wrapper in heatmap components\n- **fix(i18n):** Update `nodeIncompatibleHint` to recommend Node 24 LTS across all 31 languages\n- **fix(i18n):** Add Chinese i18n support to remaining dashboard components (`Loading.tsx`, `DataTable`, etc.)\n- **fix(requestLogger):** Add missing `cacheSource` and `tps` columns to i18n log detail views\n\n## [3.6.6] — 2026-04-15\n\n### ✨ New Features\n\n- **feat(storage):** Add database backup cleanup controls, UI management, and customizable retention period env vars (#1304)\n- **feat(providers):** Add Freepik Pikaso image generation provider with support for cookie/subscription-based auth modes (#1277)\n- **feat(providers): Add Perplexity Web (Session) Provider** — Routes through Perplexity's internal SSE API using a session cookie, giving native proxy access without separate API costs to GPT-5.4, Claude Opus, Gemini 3.1 Pro, and Nemotron via preferences mapping (#1289)\n- **feat(api): Sync Tokens & V1 WebSocket Bridge** — Dedicated sync token storage, issuance, revocation, and bundle download routes backed by stable config bundle versioning with ETag support. Exposes `/v1/ws` WebSocket upgrade route and a custom Next.js server bridge (`scripts/v1-ws-bridge.mjs`) so OpenAI-compatible WebSocket traffic can be proxied through the gateway. Compliance auditing expanded with structured metadata, pagination, request context, auth/provider credential events, and SSRF-blocked validation logging. New migrations: `024_create_sync_tokens.sql`. New modules: `syncTokens.ts`, `src/lib/sync/bundle.ts`, `src/lib/sync/tokens.ts`, `src/lib/ws/handshake.ts`, `src/lib/apiBridgeServer.ts`, `src/lib/compliance/providerAudit.ts`.\n- **feat(models): GLM Thinking Preset & Hybrid Token Counting** — GLM Thinking (`glmt`) registered as a first-class provider preset with shared GLM model metadata, pricing, per-connection usage sync, dashboard support, and `maxTokens: 65536 / thinkingBudgetTokens: 24576` request defaults with 900s extended timeout. Provider-side `/messages/count_tokens` endpoint used when a Claude-compatible upstream supports it; gracefully falls back to estimation on missing models, missing credentials, or upstream failures. Startup seeding of default model aliases (`src/lib/modelAliasSeed.ts`) normalizes common cross-proxy model dialects so canonical slash-based model IDs are not misrouted. New file `open-sse/config/glmProvider.ts`.\n- **feat(core): Hardened Outbound Provider Calls & Cooldown Retries** — Guarded outbound fetch helpers (`src/shared/network/safeOutboundFetch.ts`, `src/shared/network/outboundUrlGuard.ts`) blocking private/local URLs with configurable retry, timeout normalisation, and route-level status propagation for provider validation and model discovery. Cooldown-aware chat retries (`src/sse/services/cooldownAwareRetry.ts`) with configurable `requestRetry` and `maxRetryIntervalSec` settings and model-scoped cooldown responses. Improved rate-limit learning from headers and error bodies so short upstream lockouts can recover automatically. Runtime environment validation (`src/lib/env/runtimeEnv.ts`) checks env at startup. Pollinations now requires an API key. Antigravity and Codex header handling aligned via `open-sse/config/antigravityUpstream.ts` and `open-sse/config/codexClient.ts`. Gemini tool names restored in translated responses; synthetic Claude text block injected when upstream SSE completes empty.\n- **feat(logs):** Add TPS (Tokens Per Second) metric to log details modal metadata grid (#1182)\n- **feat(memory+skills):** Full-featured Memory & Skills systems with FTS5 SQLite search, dynamic UI pagination, backend observability, and extensive test coverage (#1228)\n- **feat(bailian-quota):** Add Alibaba Coding Plan quota monitoring, multi-window quota extraction, and UI credential validation (#1235)\n- **feat(storage): Call Log Storage Refactor** — Extracted heavy request/response JSON payloads from the core SQLite database (`storage.sqlite`) into filesystem artifacts stored within `DATA_DIR/call_logs`. This massively reduces WAL bloat and eliminates `SQLITE_FULL` crashes on high-traffic nodes (#1307).\n- **feat(providers): Add Grok Web (Subscription) Provider** — Routes through the xAI web interface for subscription users via cookie session mapping (#1295).\n- **feat(api): Advanced Media Support** — Extends OpenAI generic proxy layer to natively support `image`, `embeddings`, `audio-transcriptions`, and `audio-speech` workflows (#1297).\n- **feat(cli-tools): Qwen Code CLI Integration** — Full integration for Qwen Code local execution mapping, model resolution, and dynamic API key fetching (#1266, #1263).\n- **feat(oauth):** Supports `cursor-agent` CLI as a native Cursor credential source alongside the standard configuration (#1258).\n- **feat(models):** Custom and imported models now merge correctly into filter lists for all available global providers (#1191).\n\n### 🐛 Bug Fixes\n\n- **fix(providers):** match correct endpoint api.xiaomimimo.com for Xiaomi MiMo (#1303)\n- **fix(core):** strip provider alias routing prefix from payload for custom endpoints to fix Azure OpenAI 400 errors (#1261)\n- **fix(core):** ProxyFetch Undici dispatcher automatically bypasses LAN/local addresses, preventing fetch failures on internal OpenRouter requests (#1254)\n- **fix(core):** Gemini thought stream signature detection upgraded to use native part.thought boolean, preventing reasoning text leaks (#1298)\n- **deps:** bump hono from 4.12.12 to 4.12.14 to resolve CVE SSR HTML injection vulnerability (#1306, #59)\n- **deps:** update dompurify to 3.4.0 in frontend overrides mitigating XSS HTML Injection (CVE-XYZ / Dependabot #60)\n- **test:** Disable SQLite automatic backups during continuous integration (CI) tests to resolve E2E timeout issues limiting runner scaling (#24481475058)\n- **feat(core): Proactive Context Compression** — `chatCore` now proactively compresses oversized message contexts before hitting upstream providers to dramatically reduce `context_length_exceeded` errors. Employs binary-search message pruning with structural integrity guarantees tracking explicit `tool_use` boundaries ensuring truncated tool inputs drop paired outputs appropriately (#1292, #1293)\n\n- **fix(cli):** Resolve codex routing config parsing by strictly quoting section keys array, enforcing responses wire_api with fallback, and standardizing select-model button positioning mirroring Claude UI\n- **fix(providers):** Correct Lobehub provider icons rendering by removing unsupported local references ensuring local SVG/PNG fallback mechanism invokes natively\n- **fix(db):** Implement Database migration tracking safety abort safeguards (pre-migration backups via `VACUUM INTO` and mass renumbering warnings) to protect existing database structures on startup upgrades (#1281)\n- **fix(dashboard):** Cleaned up target codex `config.toml` structure preventing recursive section rendering by enforcing quotes on section dot paths and mapping correct UI `OMNIROUTE_API_KEY` names.\n- **fix(mcp):** Add dedicated explicit timeout constraint overrides for search handlers (#1280)\n- **fix(crypto):** Add validation guard to encryption layer to surface clear UI errors when cryptographic environment variables are missing, replacing raw Node.js TypeErrors. Legacy env vars `OMNIROUTE_CRYPT_KEY` and `OMNIROUTE_API_KEY_BASE64` now also accepted as fallbacks (#1165)\n- **fix(providers):** Update Pollinations provider definition to require API keys and specify their new limited pollen/hour free tier (#1177)\n- **Streaming `\\n\\n` Artifact Fix (#1211):** Changed `` tag-stripping regex from `?` to `*` quantifier across `combo.ts`, `comboAgentMiddleware.ts`, and `contextHandoff.ts` to greedily strip all accumulated JSON-escaped newline sequences surrounding the tag. This prevents literal `\\n\\n` prefix artifacts from appearing in consumer streaming responses\n- **E2E Combo Test Locator:** Fixed Playwright strict-mode violation in `combo-unification.spec.ts` by replacing ambiguous `getByRole` locator with a compound filter locator for the \"All\" strategy tab\n- **fix(cc-compatible):** Trim beta flags and preserve cache passthrough for third-party HTTP proxy compatibility (#1230)\n- **fix(providers):** Update Xiaomi MiMo endpoints to the live token-plan, migrating away from dead API URLs (#1238)\n- **fix:** Forward client `x-initiator` header to GitHub Copilot upstream to accurately distinguish agent vs user turns (#1227)\n- **fix:** Resolve backlog bugs including streaming edge cases, unhandled rejections, and quota parse failures (#1206, #1220, #1231, #1175, #1187, #1218, #1202)\n- **fix(tests):** Resolve memory migration and skills route pagination bugs arising from PR overlaps\n- **fix(i18n):** Add missing Chinese i18n support to dashboard components (`DataTable`, `EmptyState`, etc), update `en.json/zh-CN.json` routing keys, and natively resolve JSX defaults via `next-intl` (#1274)\n\n### 🔧 Internal Improvements\n\n- **Compliance Audit Expansion:** `src/lib/compliance/index.ts` expanded with structured metadata, pagination support, request context enrichment, and new `providerAudit.ts` module logging auth and provider credential events, SSRF-blocked validation attempts, and provider CRUD operations\n- **Config Sync Bundle:** `src/lib/sync/bundle.ts` exports `buildConfigBundle()` generating a versioned JSON snapshot of settings, provider connections, nodes, model aliases, combos, and API keys (passwords redacted) with ETag support for bandwidth-efficient polling\n- **Codex Client Constants:** Centralized `CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT_PLATFORM`, and pattern-validated env overrides (`CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT`) in `open-sse/config/codexClient.ts`\n- **Antigravity Upstream Constants:** `open-sse/config/antigravityUpstream.ts` consolidates all Antigravity base URLs and model/fetchAvailableModels discovery path builders\n- **Model Alias Seed:** `src/lib/modelAliasSeed.ts` seeds 30+ cross-proxy model dialect aliases (e.g. `openai/gpt-5` → `gpt-5`, `anthropic/claude-opus-4-6` → `cc/claude-opus-4-6`) at startup via idempotent `upsert`\n- **Test Coverage:** 15+ new unit test suites covering sync routes, WebSocket bridge, compliance index, GLM provider config, cooldown-aware retry, safe outbound fetch, stream utilities, Codex executor, provider validation branches, model cross-proxy compatibility, and model alias seeding\n- **TypeScript Migration:** Finalized migration of remaining JS tests (`proxy-load` and `testFromFile`) to TypeScript ES modules, ensuring a fully synchronized TS stack.\n- **Reliability & Resilience:** Added exponential backoff to `models.dev` auto-sync to combat transient network failures, raised interval floor to 1 hour, and added LKGP debug logging for enhanced observability during routing. (#1286)\n\n---\n\n## [3.6.5] — 2026-04-13\n\n### ✨ New Features\n\n- **Antigravity AI Credits Fallback:** Automatically retries with `GOOGLE_ONE_AI` credit injection when free-tier quota is exhausted. Per-account credit balance (5-hour TTL) is cached from SSE `remainingCredits` and exposed as a numeric badge in the Provider Usage dashboard (#1190 — thanks @sFaxsy)\n- **Claude Code Native Parity:** Full header/body signing parity with the Claude Code 2.1.87 OAuth client — CCH xxHash64 body signing with singleton WASM initialization promise (fixing race conditions), dynamic per-request fingerprint, bidirectional TitleCase ↔ lowercase tool name remapping (14 tools), API constraint enforcement (`temperature=1` for thinking, max 4 `cache_control` blocks, auto-inject ephemeral on last user message), and optional ZWJ obfuscation. Wired into `BaseExecutor` for automatic CCH signing on all `anthropic-compatible-cc-*` providers and into `chatCore` for synchronous parity pipeline steps (#1188 — thanks @RaviTharuma)\n- **Per-Connection Codex Defaults:** Codex Fast Service Tier and Reasoning Effort settings are now per-connection instead of a single global toggle. Existing connections are migrated automatically on startup via an idempotent backfill migration (#1176 — thanks @rdself)\n- **Cursor Usage Dashboard:** New `getCursorUsage()` fetches quotas from Cursor's `/api/usage`, `/api/auth/me`, and `/api/subscription` endpoints. Displays standard requests, on-demand usage, and per-plan limits (Free/Pro/Business/Team). Client version bumped to `3.1.0` and `x-cursor-user-agent` header added for parity\n- **Database Health Check System:** Automated periodic SQLite integrity monitoring via `runDbHealthCheck()` — detects orphan quota/domain rows, broken combo references, stale snapshots, and invalid JSON state. Runs every 6 hours (configurable via `OMNIROUTE_DB_HEALTHCHECK_INTERVAL_MS`), with auto-repair and pre-repair backup. Exposed as **MCP tool #18** (`omniroute_db_health_check`) with Zod schemas and `autoRepair` option. Dashboard panel in Health page with status card, issue count, repaired count, and one-click repair button\n- **OpenAI Responses API Store Opt-In:** Per-connection `openaiStoreEnabled` flag controls whether the `store` field is preserved or forced to `false` on Codex Responses API requests. When enabled, `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields are round-tripped through the Chat Completions → Responses translation, enabling multi-turn context caching on supported providers\n- **Email Privacy Toggle (Combos Page):** Global email visibility toggle (`EmailPrivacyToggle`) added to the Combos page header with responsive layout, tooltip guidance, and per-connection label masking via `pickDisplayValue()`. All combo builder options, provider connection lists, and quota screens now respect the global privacy state from `emailPrivacyStore`\n- **skills.sh Integration:** Added `skills.sh` as an external skill provider. Users can now search, browse, and install agent skills directly from a new \"skills.sh\" tab in the Skills dashboard. Includes backend API resolvers, frontend implementation with search/install states, and a dedicated unit test suite (#1223 — thanks @RaviTharuma)\n- **Stabilization Settings:** Added persistence support for `lkgpEnabled` and `backgroundDegradation` settings, integrated into `instrumentation-node.ts` for improved lifecycle awareness (#1212)\n- **xxhash-wasm dependency:** Added `xxhash-wasm@^1.1.0` for CCH signing (xxHash64 with seed `0x6E52736AC806831E`)\n\n### 🐛 Bug Fixes\n\n- **Codex `stream: false` via Combo (ALL_ACCOUNTS_INACTIVE):** Fixed a critical bug where Codex combos returned `ALL_ACCOUNTS_INACTIVE` or empty content when the client sent `stream: false`. Root cause was triple: (1) `CodexExecutor.transformRequest()` mutated `body.stream` in-place to `true`, contaminating the combo's quality check which skipped validation thinking it was streaming; (2) the non-stream SSE parser used the wrong format (Chat Completions instead of Responses API) for Codex SSE output; (3) combo quality validation read the mutated `body.stream` instead of the client's original intent. Fixed by: cloning the body via `structuredClone()` in CodexExecutor, detecting Codex/Responses SSE format in the non-stream fallback path (with auto-translation back to Chat Completions), and capturing `clientRequestedStream` before the combo loop\n- **Gemini CLI Tool Schema Rejection:** Fixed 400 Bad Request errors from the Google API by strictly filtering non-standard vendor extensions (starting with `x-`) and `deprecated` fields from tool parameter schemas (#1206)\n- **SOCKS5 Proxy Interop (Node.js 22):** Resolved `invalid onRequestStart method` crashes caused by `undici` version mismatches between dispatchers and the built-in fetch. Hardened `proxyFetch.ts` to strictly use the library's fetch implementation for custom dispatchers (#1219)\n- **Search Cache Coalescing with TTL=0:** Fixed a bug where providers configured with `cacheTTLMs: 0` (caching explicitly disabled) still had concurrent requests coalesced and returned `{ cached: true }`. Now each call gets its own independent upstream fetch (#1178 — thanks @sjhddh)\n- **Antigravity Credit Cache Alignment (PR #1190):** Reconciled `accountId` derivation between `AntigravityExecutor.collectStreamToResponse` and `getAntigravityUsage` to use consistent cache keys (`email || sub || \"unknown\"`). Previously, SSE-parsed credit balances could be written under a different key than the one read by the usage dashboard, causing stale/missing credit badges\n- **Non-streaming reasoning_content Duplication:** Fixed clients rendering duplicated reasoning panels when both `reasoning_content` and visible `content` were present in non-streaming responses. `responseSanitizer` now strips `reasoning_content` from messages that already have visible text content, preserving it only for reasoning-only messages\n- **Streaming Regression Fix:** Hardened the `sanitize` TransformStream in the combo engine to strip both literal and JSON-escaped newline sequences, eliminating leading `\\n\\n` prefixes in assistant responses (#1211)\n- **Gemini Empty Choice Fix:** Ensured initial assistant deltas always include an empty `content: \"\"` string to satisfy strict OpenAI client requirements and prevent empty choice responses in tools (#1209)\n- **Gemini Tools Sanitizer Deduplication:** Extracted shared tool conversion logic into `buildGeminiTools()` helper (`geminiToolsSanitizer.ts`), eliminating duplicate implementations between `openai-to-gemini.ts` and `claude-to-gemini.ts`. The new helper correctly handles `web_search` / `web_search_preview` tool types by emitting `googleSearch` tools with priority over function declarations\n- **Qwen/Qoder Thinking+Tool_Choice Conflict:** Added `sanitizeQwenThinkingToolChoice()` to both `DefaultExecutor` (for Qwen provider) and `QoderExecutor` to prevent provider-side 400 errors when clients send `tool_choice` alongside thinking/reasoning parameters that are mutually exclusive upstream\n- **API Key Deletion Orphan Cleanup:** Deleting an API key now also removes associated `domain_budgets` and `domain_cost_history` rows, preventing orphan data accumulation\n- **CC-compatible test assertion:** Fixed pre-existing test that expected no `cache_control` on system blocks — the billing header system block now carries `cache_control: { type: \"ephemeral\" }` per PR #1188 design\n- **Codex Combo Smoke Test False Positives:** Fixed combo tests incorrectly reporting `ERROR` for valid Codex streaming responses when `response.output` is empty but text deltas were emitted. The summary now falls back to accumulated delta text (#1176 — thanks @rdself)\n- **Electron Builder Version Mismatch:** Fixed Electron desktop startup failures on Windows packaged builds caused by native modules (`better-sqlite3`) being under `app.asar.unpacked` while helpers were in `app/node_modules`. `resolveServerNodePath()` now merges both locations with deduplication and existence checks (#1172 — thanks @backryun)\n\n### 🔧 Internal Improvements\n\n- **SSE Parser: Responses API Non-Stream Conversion:** Added full `parseSSEToResponsesOutput()` implementation in `sseParser.ts` (255+ lines) — reconstructs complete Responses API objects from SSE event streams, handling `response.output_text.delta/done`, `response.reasoning_summary_text.delta/done`, `response.function_call_arguments.delta/done`, and terminal events. Used by the new chatCore non-stream fallback path for Codex\n- **Cursor Executor Version Sync:** Updated Cursor client User-Agent to `3.1.0` and centralized version constants (`CURSOR_CLIENT_VERSION`, `CURSOR_USER_AGENT`) for consistent fingerprinting across executor, usage fetcher, and OAuth flows\n- **Responses API Translator Parity:** `convertResponsesApiFormat()` now accepts credentials and passes them through to the translator, enabling store-aware field propagation. Round-trip preservation of `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields\n- **Provider Schema Validation:** Added `openaiStoreEnabled` boolean validation to `providerSpecificData` Zod schema\n- **Combo Error Response Normalization:** Empty combo targets now return 404 (`comboModelNotFoundResponse`) instead of generic 503, improving client-side error differentiation\n- **Dependency Updates:** Bumps `typescript-eslint` to `8.58.2` (dev), `axios` to `1.15.0` (prod), and `next` to `16.2.2` (prod) (#1224, #1225)\n\n### ⚠️ Breaking Changes\n\n- **`DELETE /api/settings/codex-service-tier` removed:** This endpoint no longer exists. Codex Service Tier configuration has moved to per-connection `providerSpecificData.requestDefaults`. Existing connections are migrated automatically on first startup after upgrade. Any external scripts or integrations that call this endpoint should be updated — use `PUT /api/providers/:id` with `providerSpecificData.requestDefaults.serviceTier` instead (#1176).\n- **CCH signing on CC-compatible providers:** All requests to `anthropic-compatible-cc-*` providers now include an xxHash64 integrity token (`cch=...`) in the billing header. Providers that do not validate CCH will ignore it (no behavioral change), but any custom middleware inspecting the billing header should expect a 5-character hex token instead of the `00000` placeholder\n\n---\n\n## [3.6.4] — 2026-04-12\n\n### ✨ New Features\n\n- **Combo Builder v2 (Wizard UI):** Completely redesigned the combo creation/editing interface as a multi-stage wizard with stages: Basics → Steps → Strategy → Review. The builder fetches provider, model, and connection metadata via a new `GET /api/combos/builder/options` endpoint, enabling precise provider/model/account selection with duplicate detection and automatic next-connection suggestion. Heavy UI components (`ModelSelectModal`, `ProxyConfigModal`, `ModelRoutingSection`) are now lazily loaded via `next/dynamic` for faster initial page render\n- **Combo Step Architecture (Schema v2):** Introduced a structured step model (`ComboModelStep`, `ComboRefStep`) replacing the legacy flat string/object combo entries. Steps carry explicit `id`, `kind`, `providerId`, `connectionId`, `weight`, and `label` fields, enabling pinned-account routing, cross-combo references, and per-step metrics. All combo CRUD operations normalize entries through the new `src/lib/combos/steps.ts` module. Zod schemas updated with `comboModelStepInputSchema` and `comboRefStepInputSchema` unions\n- **Composite Tiers System:** Added tiered model routing via `config.compositeTiers` — each tier maps a named stage to a specific combo step with optional fallback chains. Includes comprehensive validation (`src/lib/combos/compositeTiers.ts`) ensuring step existence, preventing circular fallback, and validating default tier references. Zod schema enforcement blocks composite tiers on global defaults (concrete combos only)\n- **Model Capabilities Registry:** Created `src/lib/modelCapabilities.ts` providing `getResolvedModelCapabilities()` — a unified resolver that merges static specs, provider registry data, and live-synced capabilities into a single `ResolvedModelCapabilities` object covering tool calling, reasoning, vision, context window, thinking budget, modalities, and model lifecycle metadata\n- **Observability Module:** Extracted health and telemetry payload construction into `src/lib/monitoring/observability.ts` with `buildHealthPayload()`, `buildTelemetryPayload()`, and `buildSessionsSummary()` builders. The health endpoint now returns session activity, quota monitor status, and per-provider breakdowns alongside existing system metrics\n- **Session & Quota Monitor Dashboard:** Added live Session Activity and Quota Monitors panels to the Health dashboard, showing active session counts, sticky-bound sessions, per-API-key breakdowns, and top session details alongside quota monitor alerting/exhausted/error status with per-provider drill-down\n- **Combo Health Per-Target Analytics:** The combo-health API now resolves per-target metrics using the new `resolveNestedComboTargets()` function, providing step-level success rates, latency, and historical usage breakdowns per execution key — enabling per-account, per-connection health visibility\n- **Auto-Combo → Combos Unification:** Merged the separate `/dashboard/auto-combo` page into the main `/dashboard/combos` page. Auto/LKGP combos are now managed alongside all other combos with a new strategy filter tabs system (All / Intelligent / Deterministic). The old auto-combo route redirects to `/dashboard/combos?filter=intelligent`. Removed the `auto-combo` sidebar entry, consolidating navigation into the single `Combos` item\n- **Intelligent Routing Panel (`IntelligentComboPanel`):** New inline panel (371 lines) within the combos page that shows real-time provider scores, 6-factor scoring breakdown (quota, health, cost, latency, task fitness, stability), mode pack selector, incident mode status, and excluded providers for `auto`/`lkgp` combos — replacing the former standalone auto-combo dashboard\n- **Builder Intelligent Step (`BuilderIntelligentStep`):** New conditional wizard step (280 lines) that appears in the Builder v2 flow only when `strategy=auto` or `strategy=lkgp` is selected. Exposes candidate pool selection, mode pack presets, router sub-strategy selector, exploration rate slider, budget cap, and collapsible advanced scoring weights configuration\n- **Intelligent Routing Module (`intelligentRouting.ts`):** Extracted strategy categorization and filtering logic into a dedicated shared module (210 lines) with `getStrategyCategory()`, `isIntelligentStrategy()`, `filterCombosByStrategyCategory()`, `normalizeIntelligentRoutingFilter()`, and `normalizeIntelligentRoutingConfig()` utility functions\n- **LKGP Standalone Strategy:** Implemented `lkgp` (Last Known Good Provider) as a fully functional standalone combo strategy. Previously, `lkgp` as a combo strategy silently fell through to `priority` ordering — the LKGP lookup only ran inside the `auto` engine. Now `strategy: \"lkgp\"` correctly queries the LKGP state, moves the last successful provider to the top of the target list, and saves the LKGP state after each successful request. Falls back to priority ordering when no LKGP state exists\n- **Unified Routing Rules & Model Aliases:** Consolidated the routing rules and model alias management controls into the Settings page, reducing fragmentation across the dashboard\n\n### ⚡ Performance\n\n- **Middleware Lazy Loading:** Refactored `src/proxy.ts` to lazy-import `apiAuth`, `db/settings`, and `modelSyncScheduler` modules, reducing middleware cold-start overhead. Added inline `isPublicApiRoute()` to avoid loading the full auth module for public routes\n- **E2E Auth Bypass:** Added `NEXT_PUBLIC_OMNIROUTE_E2E_MODE` environment flag to bypass authentication gates for dashboard and management API routes during Playwright E2E test runs\n\n### 🐛 Bug Fixes\n\n- **P2C Credential Selection:** Implemented Power-of-Two-Choices (P2C) connection scoring in `src/sse/services/auth.ts` with quota headroom awareness, error/recency penalties, and forced/excluded connection support. The new `getProviderCredentialsWithQuotaPreflight()` function integrates quota preflight checks directly into credential selection, eliminating the separate Codex-only preflight path\n- **Fixed-Account Combo Steps:** Combo steps with explicit `connectionId` now correctly bypass provider-level model cooldowns and circuit breakers, preventing a single account failure from blocking pinned-connection routing for the same model\n- **Combo Metrics Per-Target Tracking:** Extended `comboMetrics.ts` to track `byTarget` metrics keyed by execution path, recording per-step `provider`, `providerId`, `connectionId`, and `label` alongside existing per-model aggregates\n- **Call Logs Schema Expansion:** Added `requested_model`, `request_type`, `tokens_cache_read`, `tokens_cache_creation`, `tokens_reasoning`, `combo_step_id`, and `combo_execution_key` columns to `call_logs` with auto-migration. Added composite index `idx_cl_combo_target` for efficient per-target historical queries\n- **Quota Monitor Enrichment:** Expanded `quotaMonitor.ts` with full lifecycle state tracking (`status`, `startedAt`, `lastPolledAt`, `consecutiveFailures`, `totalPolls`, `totalAlerts`), ISO-formatted snapshots via `getQuotaMonitorSnapshots()`, and sorted summary via `getQuotaMonitorSummary()`\n- **Codex Quota Fetcher Hardening:** Improved `codexQuotaFetcher.ts` with safer connection registration and quota fetch error handling\n- **LKGP Save Refactored to Async/Await:** Replaced fire-and-forget `.then()` chain for LKGP persistence after successful combo routing with proper `async/await` + `try/catch`, preventing unhandled promise rejections and ensuring LKGP state is reliably saved before the response is returned\n- **Duplicate `auto` in Combo Strategy Schema:** Removed duplicate `\"auto\"` entry from `comboStrategySchema` (was listed on both line 104 and 108). Harmless to Zod runtime but cleaned up to avoid confusion. Schema now has exactly 13 unique strategy values\n- **Legacy Combo Refs Normalization:** Fixed combo step normalization to preserve legacy string combo references during CRUD operations, preventing data loss when editing combos created before the v2 step architecture\n\n### Sicurezza\n\n- **Auth Bypass on Backup Routes (Critical):** Added `isAuthenticated` guards to `/api/db-backups/exportAll` (full database export) and `/api/db-backups` (list, create, and restore backups) — both were previously accessible without authentication\n- **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency\n- **API Key Secret Hardening:** Removed the hardcoded `\"omniroute-default-insecure-api-key-secret\"` fallback from `apiKey.ts` — the function now fails fast if `API_KEY_SECRET` is unset, relying on the startup validator to auto-generate it\n- **NPM Tarball Leak Fix:** Added `app/.env*` to `.npmignore` to prevent the working `.env` file from being shipped inside the npm tarball distribution\n- **Electron Builder CVE Fix:** Bumped `electron-builder` to 26.8.1 to resolve `tar` CVEs in the desktop build pipeline\n\n### 🔧 Maintenance & Infrastructure\n\n- **DB Migration 021:** Added `combo_call_log_targets` migration for `combo_step_id` and `combo_execution_key` columns in call_logs\n- **Combo CRUD Normalization:** `db/combos.ts` now normalizes all stored combo entries through the step normalization pipeline on read, ensuring consistent step IDs and kind annotations regardless of when the combo was created\n- **Playwright Config:** Updated Playwright configuration and `run-next-playwright.mjs` script for improved E2E test orchestration\n- **Build Script:** Updated `build-next-isolated.mjs` with additional reliability improvements\n- **Auto-Combo UI Cleanup:** Deleted `AutoComboModal.tsx` (161 lines), replaced `auto-combo/page.tsx` (478→5 lines) with a server-side redirect to `/dashboard/combos?filter=intelligent`\n- **Sidebar Consolidation:** Removed `\"auto-combo\"` from `HIDEABLE_SIDEBAR_ITEM_IDS` and `PRIMARY_SIDEBAR_ITEMS` — `normalizeHiddenSidebarItems()` silently discards any stale `\"auto-combo\"` entries in user settings\n- **Schema Cleanup:** Removed obsolete `createAutoComboSchema` from `schemas.ts`. Exported `comboStrategySchema` for direct use in test and filter modules\n- **A2A Agent Card Update:** Renamed skill ID from `auto-combo` to `intelligent-routing` with updated description referencing the unified combos dashboard\n- **Builder Draft Refactor:** Extended `builderDraft.ts` with dynamic stage list generation via `getComboBuilderStages()` and `isIntelligentBuilderStrategy()`. Stage navigation (`getNextComboBuilderStage`, `getPreviousComboBuilderStage`, `canAccessComboBuilderStage`) now accepts options to conditionally include/skip the `intelligent` wizard step\n- **i18n Consolidation:** Removed the standalone `\"autoCombo\"` i18n block (22 keys) from all 30 language files. Migrated keys into the `\"combos\"` block with new additions for filter tabs, intelligent panel, and builder step labels\n\n### 🧪 Tests\n\n- **16 New Test Suites:** Added comprehensive test coverage including:\n - `combo-builder-draft.test.mjs` (186 lines) — Builder draft step construction and validation\n - `combo-builder-options-route.test.mjs` (228 lines) — Builder options API endpoint\n - `combo-health-route.test.mjs` (266 lines) — Combo health analytics with per-target metrics\n - `combo-routes-composite-tiers.test.mjs` (157 lines) — Composite tiers API integration\n - `composite-tiers-validation.test.mjs` (131 lines) — Composite tier validation rules\n - `db-combos-crud.test.mjs` — Combo CRUD with step normalization\n - `db-core-init.test.mjs` (129 lines) — DB initialization and column migrations\n - `model-capabilities-registry.test.mjs` (105 lines) — Model capabilities resolution\n - `observability-payloads.test.mjs` (165 lines) — Health/telemetry payload construction\n - `openapi-spec-route.test.mjs` — OpenAPI spec generation\n - `proxy-e2e-mode.test.mjs` (74 lines) — E2E mode auth bypass\n - `quota-monitor.test.mjs` — Quota monitor lifecycle state\n - `run-next-playwright.test.mjs` (119 lines) — Playwright runner script\n - `sse-auth.test.mjs` (154 lines) — P2C credential selection and quota preflight\n - `telemetry-summary-route.test.mjs` (35 lines) — Telemetry summary endpoint\n - Plus updates to 12 existing test files for compatibility with new step architecture\n- **Auto-Combo Unification Tests:**\n - `autocombo-unification.test.mjs` (156 lines) — Strategy categorization, schema deduplication, sidebar cleanup, and routing strategies metadata validation\n - `combo-unification.spec.ts` (189 lines) — Playwright E2E tests for filter tabs, intelligent panel rendering, redirect from old route, sidebar entry removal, and Builder v2 intelligent step flow\n - 3 new LKGP standalone tests in `combo-routing-engine.test.mjs` — Validates LKGP provider prioritization, fallback to priority when no state exists, and LKGP state persistence after successful requests\n - Updated `combo-builder-draft.test.mjs` with intelligent stage navigation tests\n - Updated `sidebar-visibility.test.mjs` to reflect `auto-combo` removal\n\n---\n\n## [3.6.3] — 2026-04-11\n\n### ✨ New Features\n\n- **OpenAI-Compatible Loose Validation:** Empty API keys can now be naturally submitted and saved for any `openai-compatible-*` providers (e.g. Pollinations, localized routes) directly in the UI instead of blocking save actions (#1152)\n- **Cloudflare Configuration:** Updated the provider schema and UI integration for Cloudflare AI to officially expose and support the backend `accountId` field securely without overrides (#1150)\n\n### 🐛 Bug Fixes\n\n- **Vertex JSON Validation Crash:** Prevented `invalid character in header` crashes inside the `/validate` endpoint by creating a native authentication parser that correctly handles Google Identity Service Account JSON flows prior to pinging endpoints (#1153)\n- **Extraneous Payload Rejection:** Globally prevented upstream `400 Bad Request` execution crashes by stripping the non-standard `prompt_cache_retention` attribute forcibly attached by Cursor/Cline IDE engines when targeting strict OpenAI/Anthropic routes (#1154)\n- **Reasoning Content Drop:** Prevented pure reasoning packets, common in advanced fallback models like DeepSeek, from being aborted mid-stream by explicitly adjusting the `Empty Content (502)` circuit breakers to acknowledge `reasoning_content` states as valid (#1155)\n- **Desktop Windows Build Crash:** Fixed `better_sqlite3.node is not a valid Win32 application` preventing OmniRoute Desktop from launching on Windows by properly removing the ABI-mismatched sqlite cache from Next.js standalone and falling back to the cross-compiled Electron equivalent during packager build steps (#1163)\n- **Login Visual Security:** Removed the raw fallback hash dump that artificially rendered underneath the login modal in Docker instances missing `OMNIROUTE_API_KEY_BASE64` flags (#1148)\n\n### 🔧 Maintenance & Dependencies\n\n- **Dependabot Updates:** Safely bumped GitHub Actions `docker/build-push-action` to v7 and `actions/download-artifact` to v8\n- **Electron Updates:** Upgraded desktop wrapper core to Electron `41.2.0` and `electron-builder` to `26.8.1`, incorporating essential V8/Chromium security patches\n- **NPM Package Groups:** Updated `production` and `development` NPM groups to securely handle minor audit warnings and keep toolchains modern\n- **CI/CD Reliability:** Fixed persistent `Snyk` token-absence failures on automated pull requests by appropriately bypassing on dependabot actions\n\n## [3.6.2] — 2026-04-11\n\n### ✨ New Features\n\n- **33 New API Key Providers:** Massive provider expansion adding DeepInfra, Vercel AI Gateway, Lambda AI, SambaNova, nScale, OVHcloud AI, Baseten, PublicAI, Moonshot AI, Meta Llama API, v0 (Vercel), Morph, Featherless AI, FriendliAI, LlamaGate, Galadriel, Weights & Biases Inference, Volcengine, AI21 Labs, Venice.ai, Codestral, Upstage, Maritalk, Xiaomi MiMo, Inference.net, NanoGPT, Predibase, Bytez, Heroku AI, Databricks, Snowflake Cortex, and GigaChat (Sber). OmniRoute now supports **100+ providers** (4 Free + 8 OAuth + 91 API Key + Custom compatible)\n- **Global Email Privacy Toggle:** Added a persistent eye-icon toggle button across all dashboard pages (Providers, Usage Limits, Playground) that reveals or hides masked email addresses. Toggle state is stored in localStorage and synced globally via Zustand store\n- **Documentation Refresh:** Updated README, ARCHITECTURE, FEATURES, AGENTS.md, and API_REFERENCE for v3.6.2 with accurate provider counts (100+), new executor list, and system API documentation\n- **Uninstall Guide:** Created comprehensive `docs/UNINSTALL.md` covering clean uninstallation for all deployment methods (npm, Docker, Electron, source)\n\n### 🐛 Bug Fixes\n\n- **PDF Attachments:** Unlocked deep string object parsing (`geminiHelper`) ensuring Gemini translation successfully passes complex PDF payloads from OpenAI-compatible streams without dropping them silently (#993)\n- **SkillsMP Engine:** Corrected object extraction path mappings inside the API router to fix UI marketplace rendering under Docker/Standalone Node isolated deployments (#988)\n\n---\n\n## [3.6.1] — 2026-04-10\n\n### ✨ New Features\n\n- **OAuth Env Repair Action:** Added a \"Repair env\" button to the OAuth Providers dashboard that detects and restores missing OAuth client IDs from `.env.example` — with timestamped backup and append-only safety. Includes full 33-language i18n support and sanitized API responses (#1116, by @yart)\n\n### 🐛 Bug Fixes\n\n- **i18n: Missing Provider Keys:** Added missing `filterModels`, `modelsActive`, `showModel`, `hideModel` keys across all 32 locale files, fixing runtime `MISSING_MESSAGE` errors in the providers UI. Also cleaned up duplicate keys in `en.json` (#1111, by @rilham97)\n- **GPT-5.4 Routing:** Added missing `targetFormat: \"openai-responses\"` to `gpt-5.4` and `gpt-5.4-mini` models in both the Codex and GitHub Copilot providers, fixing `[400]: model not accessible via /chat/completions` errors (#1114, by @ask33r)\n\n---\n\n## [3.6.0] — 2026-04-10\n\n### ✨ New Features & Analytics\n\n- **Combo Smoke Test:** Raised the default token budget to 2048 to prevent truncation of thinking models during preflight checks, and fully randomized the arithmetic probe prompt to bypass deterministic caching from upstream relays (#1105)\n\n### 🐛 Bug Fixes & Compliance\n\n- **DB Bloat / Row Limits:** Added `CALL_LOGS_TABLE_MAX_ROWS` and `PROXY_LOGS_TABLE_MAX_ROWS` (default: 100,000) to the backend DB compliance cleaner to prevent runaway SQLite growth. Limits are enforced automatically on the TTL cycle (#1104, fixes #1101)\n- **HTML Error Handling:** The router now correctly identifies unexpected HTML responses (e.g. ``) sent by upstream providers (like Azure/Copilot) instead of throwing obscure `Unexpected token '<'` JSON parse errors, bubbling up a clean 502 Bad Gateway (#1104, fixes #1066)\n- **Android/Termux SQLite Native Support:** `better-sqlite3` is now correctly built from source with cross-compilation flags in ARM64 local Termux deployments without failing on missing prebuilt binaries (#1107)\n\n---\n\n## [3.5.9] — 2026-04-09\n\n### ✨ New Features\n\n- **Persistent Combo Ordering:** Drag combo cards by handle to reorder them in the dashboard; order is persisted to SQLite via a new `sort_order` column and `POST /api/combos/reorder` endpoint. Includes DB migration `020_combo_sort_order.sql` and JSON import preservation (#1095)\n- **Sidebar Group Reorder:** Moved \"Logs\" before \"Health\" in the System section and \"Limits & Quotas\" after \"Cache\" in the Primary section for a more logical navigation flow (#1095)\n\n### 🐛 Bug Fixes\n\n- **Stream Failure Surfacing:** Upstream `response.failed` events (e.g. Codex rate-limit errors) are now properly surfaced as non-200 errors instead of being silently swallowed as empty 200 OK streams. Rate-limit failures return HTTP 429 (#1098, closes #1093)\n- **Upstream Model Preservation:** The Responses-to-OpenAI stream translator now preserves the actual upstream model (e.g. `gpt-5.4`) instead of hardcoding a `gpt-4` fallback (#1098, closes #1094)\n- **Docker EXDEV Fix:** `build-next-isolated.mjs` now falls back from `fs.rename()` to `cp/rm` when Docker buildx raises `EXDEV` (cross-device link), unblocking the Docker image publish workflow (#1097)\n- **macOS CLI Path Resolution:** `cliRuntime.ts` resolves symlink parents with `fs.realpath()` to handle macOS `/var` → `/private/var` chains, preventing false `symlink_escape` rejections (#1097)\n- **Request Log Token Layout:** Split token badges into separate Input (Total In, Cache Read, Cache Write) and Output (Total Out, Reasoning) groups for clearer readability; renamed \"Time\" label to \"Completed Time\" (#1096)\n\n---\n\n## [3.5.8] — 2026-04-09\n\n### ✨ New Features & Analytics\n\n- **Analytics Layout Redesign:** Replaced flat metrics with a responsive `CompactStatGrid`, grouping data visually across sections (#1089)\n\n### 🐛 Bug Fixes\n\n- **Build Core:** Force Turbopack cleanup via Prepbulish script to prevent Next.js 16 app/ routing conflicts on runtime.\n- **Provider Quarantine:** Introduces model/provider circuit-breakers with adaptive TTL exponential backoff for recurring upstream errors (#1090)\n- **Oauth Keep-Alive:** Safely protects authenticated active accounts against spontaneous dropping from router due to transient token refresh failures (#1085)\n\n### 🔒 Security & Maintenance\n\n- **Dependabot:** bumped axios from 1.14.0 to 1.15.0 addressing SSRF flags (#1088)\n\n---\n\n## [3.5.7] — 2026-04-09\n\n### 🐛 Bug Fixes & Security\n\n- **Turbopack Standalone Chunks:** Fixed a critical bug in `scripts/prepublish.mjs` where Turbopack chunks missing from the `.next/standalone` trace resulted in a `500 ChunkLoadError` (e.g., `_not-found` page crash) during production deployments via NPM or Docker. Standalone chunks are now explicitly copied and correctly stripped of Turbopack hashes.\n\n---\n\n## [3.5.6] — 2026-04-09\n\n### ✨ New Features\n\n- **Email Privacy Masking:** OAuth account emails are now masked in the provider dashboard (e.g. `di*****@g****.com`) to prevent accidental exposure when sharing screenshots. Full address visible on hover via `title` attribute (#1025).\n- **OpenRouter & GitHub in Embedding/Image Registries:** OpenRouter (3 embedding models, 4 image models) and GitHub Models (2 embedding models via Azure inference) are now first-class entries in the provider registries, enabling their use for `/v1/embeddings` and `/v1/images/generations` (#960).\n- **Model Visibility Toggle & Search Filter:** The provider page model list now includes a real-time search/filter bar and a per-model visibility toggle (👁 icon). Hidden models are grayed out and excluded from the `/v1/models` catalog. An active-count badge (`N/M active`) shows at a glance how many models are enabled (#750).\n- **Chinese Localization (zh-CN):** Added missing translations for Context Relay, Memory, LKGP, and Models.dev sync features, while standardizing terminology across the application (#1079).\n- **Environment Auto-Sync:** Added `sync-env.mjs` to auto-generate and append `.env` from `.env.example` during installation, automatically generating cryptographic secrets on first run.\n- **Source Mode Dashboard Update:** Fixed real-time Source (git-checkout) updating in the dashboard, enabling secure, real-time update pipelines for non-NPM installations.\n\n### 🐛 Bug Fixes & Security\n\n- **Hardcoded Secret Cleanup:** Removed 12 hardcoded OAuth credential fallbacks from the source code, forcing secure reliance on environment variables and resolving static analysis security alerts.\n- **Next.js Security Patch:** Bumped `next` from 16.2.2 to 16.2.3 to resolve critical RSC deserialization RCE vulnerability (SNYK-JS-NEXT-15954202).\n- **Memory/Cache UI Crash:** Added null-safety guards (`?? 0`) to `.toLocaleString()` calls in Memory and Cache dashboard pages, preventing `TypeError` crashes when database tables are empty or contain null numeric values (#1083).\n- **WebSearch tool_choice Translation:** Fixed OpenAI-to-Claude translator dropping `tool_choice` objects with `type: \"function\"` as-is, which Claude rejects. Now properly maps all OpenAI `tool_choice` variants (`function`, `required`, `none`) to Claude-compatible format (`tool`, `any`, `auto`), fixing \"Did 0 searches\" in Claude Code WebSearch (#1072).\n- **Provider Validation baseUrl Override:** Added `baseUrl` passthrough from frontend validation requests to the backend validation endpoint. Chinese-site users of Alibaba Coding Plan (bailian-coding-plan) can now validate API keys against their custom Base URL instead of always hitting the international endpoint (#1078).\n- **Minimax Auth Header:** Switched Minimax provider from `x-api-key` to `Authorization: Bearer` header format, matching the current API spec (#1076).\n- **Native Fetch Fallback:** Added graceful fallback to native `fetch` when the `undici` dispatcher fails, improving resilience in environments where undici is unavailable (#1054).\n- **EPIPE Flood Fix:** Added circuit-breaker logic to prevent EPIPE errors from creating a feedback loop that fills logs at GB/s (#1006).\n- **Qoder PAT Validation:** Improved Qoder Personal Access Token validation with actionable error messages that guide users to the correct token format (#966).\n- **CI/CD Pipeline:** Fixed `check:docs-sync` failure by syncing OpenAPI version to 3.5.6 and finalizing CHANGELOG release heading. Commented out `DATA_DIR` in `.env.example` to prevent E2E test failures in CI runners lacking root permissions.\n\n### 🌍 i18n\n\n- **Auto Language Generation (CI):** Added CI pipeline to auto-generate missing language files and strings via `feat(CI,i18n)` workflow, covering 30+ locales (#1071).\n\n---\n\n## [3.5.5] — 2026-04-08\n\n### ✨ New Features\n\n- **Node.js 24 Compatibility Warning:** Added a proactive version incompatibility warning on the login page to guide users to the stable Node.js 22 LTS, preventing native sqlite binding crashes.\n- **Context Relay Combo Strategy:** Added the new `context-relay` combo strategy with priority-style routing, structured handoff summary generation once quota usage reaches the warning threshold, and handoff injection after the next real account switch.\n- **Global Context Relay Defaults:** Added global Settings defaults plus combo-level configuration for `handoffThreshold`, `handoffModel`, and `handoffProviders`, so new or unconfigured combos can inherit the feature consistently.\n\n### 🐛 Bug Fixes\n\n- **Proxy Connection Healthchecks:** Applied proxy resolution per connection in the sweeping loop (`tokenHealthCheck.ts`) and global provider validation sweeps, resolving Node 22 bypass and improving proxy stability (#1051, #1056, #1061).\n- **Security Vulnerability Remediation:** Resolved multiple CodeQL scanning alerts including SSRF in model sync, insecure randomness in web crypto (`generateSessionId`), and incomplete URL sanitization.\n- **Context Relay Typing & Synchronization:** Reverted out-of-scope test breakages and resolved `handoffProvider` and response `input` extraction payload typing.\n- **Legacy OpenAI-Compatible Responses Routing:** Fixed legacy/imported OpenAI-compatible providers (for example `openai-compatible-sp-openai`) incorrectly routing Chat Completions traffic to `/chat/completions` when the real provider node was configured as `apiType: \"responses\"`. OmniRoute now treats `providerSpecificData.apiType` as authoritative across routing, executors, and translator tools, avoiding false empty-content failures during combo/provider smoke tests (#1069).\n- **Gemini PDF Attachment Integration:** Fixed payload generation and format for parsing `inline_data` and generic base64 sources for deep Gemini PDF routing (#993, #1021).\n- **Vercel AI SDK Fallbacks:** Mapped `max_output_tokens` to `max_tokens` for strict OpenAI-compatible providers, resolving errors from standard AI agents and frameworks (#994).\n- **External Auth & UI Reliability:** Handled null `state` failures in Cline OAuth exchange (#1016), added 3rd-party 400 error patterns to combo fallback (#1024), and resolved desktop sidebar layout and popover overflows (#1039, #1001).\n- **Context Relay In-Flight Deduplication:** Prevented duplicate handoff generation for the same session/combo while an earlier summary request is still in flight.\n- **Context Relay Provider Gating:** Aligned runtime behavior with configuration so explicit `handoffProviders` exclusions, including an empty array, now disable handoff generation as expected.\n\n### 🛠️ Maintenance & Dependabot\n\n- **Updated Sub-dependencies:** Bumped `hono` to `4.12.12` and `@hono/node-server` to `1.19.13` to patch critical security gaps (#1063, #1064, #1067, #1068).\n\n### Documentazione\n\n- **Documentation Synchronization:** Updated system documentation (README, Architecture, Features, Tools, Troubleshooting) and synced `i18n` configurations to match the v3.5.5 context relay patterns and proxy troubleshooting steps.\n- **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance.\n\n---\n\n## [3.5.4] — 2026-04-07\n\n### ✨ New Features\n\n- **Detailed Token Tracking:** Added granular token breakdown columns (cache read, cache write, reasoning) to call logs with proper null vs zero distinction. Includes DB migration 018 and 5-label UI display per provider capability (#1017 — thanks @rdself).\n- **Legacy JSON Config Import/Export:** Restored JSON-based settings export and import for migration from legacy 9router configurations. Security-hardened with Zero-Trust redaction of passwords and `requireLogin` fields, and automatic pre-import database backups (#1012 — thanks @luandiasrj).\n- **Non-Stream Aliases:** Added API support for explicit non-streaming aliases (`non_stream`, `disable_stream`, `disable_streaming`, `streaming=false`), normalized at the boundary before provider translation (#1036 — thanks @wlfonseca).\n- **Russian Dashboard Localization:** Comprehensive Russian translation for the dashboard UI, including fixes for 2 Ukrainian locale keys (#1003 — thanks @mercs2910).\n\n### 🐛 Bug Fixes\n\n- **Anthropic Streaming Input Undercount:** Fixed a critical bug where Anthropic streaming `prompt_tokens` only reported non-cached tokens (e.g., `in=3` when actual total was 113,616). Cache tokens are now summed into prompt_tokens during streaming (#1017).\n- **Built-in Responses API Tool Types:** Preserved built-in Responses API tools (`web_search`, `file_search`, `computer`, `code_interpreter`, `image_generation`) from being silently stripped by the empty-name tool filter — these tools carry no `.name` field (#1014 — thanks @rdself).\n- **Cursor/Codex Responses Compatibility:** Fixed empty output in Cursor when using Codex models by hoisting system input items to `instructions`, sanitizing invalid tool names, and detecting Responses-format payloads on chat/completions endpoint (#1002 — thanks @mercs2910).\n- **OAuth Token Expiry Display:** Fixed OAuth connections showing \"expired\" badge even with valid tokens by reading `tokenExpiresAt` (updated on refresh) instead of `expiresAt` (original grant timestamp) (#1032 — thanks @tombii).\n- **Codex Fast-Tier Copy:** Corrected dashboard settings copy from `service_tier=fast` to `service_tier=priority`, matching the actual Codex wire format (#1045 — thanks @kfiramar).\n- **macOS Desktop App Startup:** Stabilized packaged macOS app launch by excluding desktop artifacts from the standalone bundle and improving launch path detection (#1004 — thanks @mercs2910).\n- **macOS Sidebar Layout:** Fixed macOS traffic light overlap, sidebar spacing, and button overflow in the Electron desktop app (#1001 — thanks @mercs2910).\n\n### ⚡ Performance\n\n- **Analytics Page Load:** Dramatically reduced analytics page load times (30s→1-2s for 50K entries) via date-filtered DB queries, parallel `Promise.all()` cost calculations, and merged 6 COUNT queries into a single CASE WHEN aggregate (#1038 — thanks @oyi77).\n\n### 🔒 Security & Dependencies\n\n- **Node Base Image:** Upgraded Docker base from `22-bookworm-slim` to `22.22.2-trixie-slim` (#1011 — Snyk).\n- **Production Dependencies:** Bumped 5 production dependencies (#1044 — Dependabot).\n- **Vite:** Bumped from 8.0.3 to 8.0.5 (#1031 — Dependabot).\n- **Development Dependencies:** Bumped 4 development dependencies (#1030 — Dependabot).\n\n### 🧪 Tests\n\n- **Token Accounting Tests:** Added 18 new unit tests covering detailed token breakdown, null vs zero semantics, per-provider token extraction, and Anthropic streaming input fix (#1017).\n- **Built-in Tool Tests:** Added 3 new test cases for built-in Responses API tool type preservation (#1014).\n- **ChatCore Sanitization:** Updated sanitization tests to accommodate Responses format detection (PR #1002) and built-in tool preservation (PR #1014).\n\n### 🛠️ Maintenance\n\n- **PR Workflow:** Updated `/review-prs` workflow to merge PRs into the release branch (`release/vX.Y.Z`) instead of directly into `main`, ensuring proper pre-release staging.\n\n### Coverage\n\n- **2537 tests, 2532 passing** — Statement coverage: 91.95%, Branch coverage: 78.79%, Function coverage: 93.19%\n\n## [3.5.3] - 2026-04-07\n\n### Sicurezza\n\n- **Vulnerabilities:** Fully remediated 12 High-Severity CodeQL vulnerabilities by migrating from Math.random to `crypto.randomUUID()`, wrapping SSE injection points with aggressive backslash escaping, sanitizing trailing HTTP fragments, and enforcing rigid SSRF HTTP verification schemes across internal routes.\n- **Dependencies:** Upgraded Next.js to `^16.2.2` and Vite to `>=8.0.5` resolving critical DoS, arbitrary file reads and CSRF vectors in the build/server environments.\n\n### Fixed\n\n- **E2E Stability:** Eliminated extreme CI unreliability and transient test timeouts (Playwright) by propagating internal standalone `_next/static` assets properly and refactoring deep UI interactions inside defensive `expect().toPass()` loops.\n- **Middleware:** Resolved infinite redirect loop on dashboard for fresh instances when requireLogin is disabled.\n- **Core Fallbacks:** Preserved primary failure contexts and enhanced Edge-case error handling pipelines across chat and fallback loops.\n- **Proxy/Hooks:** Optimized local git hooks, normalized token coverage endpoints into `/coverage`, and guarded GLM region lookups.\n\n### 🛠️ Maintenance\n\n- **CI/CD Stabilization:** Prevented random GitHub Runner freezes by decoupling sharded processes, adjusting test concurrencies, unref-ing active connections on server teardown, and strictly capping job timeout durations.\n\n### Documentazione\n\n- **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned).\n\n### Coverage\n\n- **Testing:** Consolidated the workspace test coverage framework hitting 92.1% statement line coverage, with new rigid unit-tests matching API key policies and tool scopes.\n\n---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n- **Qoder API Native Integration:** Completely refactored the Qoder Executor to bypass the legacy COSY AES/RSA encryption algorithm, routing directly into the native DashScope OpenAi-compatible URL. Eliminates complex dependencies on Node `crypto` modules while improving stream fidelity.\n- **Resilience Engine Overhaul:** Integrated context overflow graceful fallbacks, proactive OAuth token detection, and empty-content emission prevention (#990).\n- **Context-Optimized Routing Strategy:** Added new intelligent routing capability to natively maximize context windows in automated combo deployments (#990).\n\n### 🐛 Bug Fixes\n\n- **Responses API Stream Corruption:** Fixed deep-cloning corruption where Anthropic/OpenAI translation boundaries stripped `response.` specific SSE prefixes from streaming boundaries (#992).\n- **Claude Cache Passthrough Alignment:** Aligned CC-Compatible cache markers consistently with upstream Client Pass-Through mode preserving prompt caching.\n- **Turbopack Memory Leak:** Pinned Next.js to strict `16.0.10` preventing memory leaks and build staleness from recent upstream Turbopack hashed module regressions (#987).\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **Models.dev Integration:** Integrated models.dev as the authoritative runtime source for model pricing, capabilities, and specifications, overriding hardcoded prices. Includes a settings UI to manage sync intervals, translation strings for all 30 languages, and robust test coverage.\n- **Provider Native Capabilities:** Added support for declaring and checking native API features (e.g. `systemInstructions_supported`) preventing failures by sanitizing invalid roles. Currently configured for Gemini Base and Antigravity OAuth providers.\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Sicurezza\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Funzionalità\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Sicurezza\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicurezza\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicurezza\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Documentazione\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Documentazione\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funzionalità\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funzionalità\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funzionalità\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicurezza\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funzionalità\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funzionalità\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funzionalità\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funzionalità\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funzionalità\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funzionalità\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funzionalità\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funzionalità\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicurezza\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\bany\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funzionalità\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funzionalità\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funzionalità\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funzionalità\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funzionalità\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funzionalità\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Documentazione\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funzionalità\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "fa886231d331109bf2fd260dcff72880fc2acca0": {"t": 1785765402.8428004, "n": 199209, "h": "cbe4fc0ce8cd7a58", "c": "# Changelog (Italiano)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.5.3] - 2026-04-05\n\n### Fixed\n\n-**Middleware:**Risolto loop di reindirizzamento infinito sul dashboard per nuove istanze quando requireLogin è disabilitato.---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n-**Integrazione nativa dell'API Qoder:**Refactoring completo dell'Executor Qoder per bypassare l'algoritmo di crittografia COZY AES/RSA legacy, instradando direttamente nell'URL nativo compatibile con DashScope OpenAi. Elimina le dipendenze complesse dai moduli \"crypto\" del nodo migliorando al contempo la fedeltà del flusso. -**Revisione del motore di resilienza:**fallback integrati per l'overflow del contesto, rilevamento proattivo dei token OAuth e prevenzione delle emissioni di contenuti vuoti (#990). -**Strategia di routing ottimizzata per il contesto:**Aggiunta una nuova funzionalità di routing intelligente per massimizzare in modo nativo le finestre di contesto nelle distribuzioni combinate automatizzate (#990).### 🐛 Bug Fixes\n\n-**Corruzione del flusso dell'API di risposta:**Risolto il problema della clonazione profonda in cui i confini della traduzione Anthropic/OpenAI rimuovevano i prefissi SSE specifici di `response.` dai confini dello streaming (#992). -**Allineamento Passthrough di Claude Cache:**Allineati gli indicatori di cache compatibili con CC in modo coerente con la modalità Passthrough del client upstream preservando la memorizzazione nella cache dei prompt. -**Perdita di memoria Turbopack:**Bloccato Next.js nel rigido `16.0.10` per prevenire perdite di memoria e creare obsolescenza a causa delle recenti regressioni del modulo hash Turbopack upstream (#987).---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n-**Integrazione Models.dev:**Models.dev integrato come fonte runtime autorevole per prezzi, funzionalità e specifiche dei modelli, sovrascrivendo i prezzi codificati. Include un'interfaccia utente delle impostazioni per gestire gli intervalli di sincronizzazione, stringhe di traduzione per tutte le 30 lingue e una solida copertura dei test. -**Funzionalità native del provider:**Aggiunto supporto per dichiarare e controllare le funzionalità API native (ad esempio `systemInstructions_supported`) prevenendo errori disinfettando i ruoli non validi. Attualmente configurato per i provider Gemini Base e Antigravity OAuth. -**Impostazioni avanzate del provider API:**Aggiunte sostituzioni personalizzate di \"User-Agent\" per connessione per le connessioni del provider di chiavi API. L'override è archiviato in \"providerSpecificData.customUserAgent\" e ora si applica ai sondaggi di convalida e alle richieste di esecuzione upstream.### 🐛 Bug Fixes\n\n-**Affidabilità OAuth di Qwen:**Risolti una serie di problemi di integrazione OAuth tra cui un blocco 400 Bad Request su token scaduti, generazione di fallback per l'analisi delle proprietà OIDC \"access_token\" quando \"id_token\" viene omesso, errori di rilevamento del catalogo modelli e filtraggio rigoroso delle intestazioni \"X-Dashscope-\\*\" per evitare il rifiuto 400 da endpoint compatibili con OpenAI.## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n-**Auto-Combo e Routing:**Completata l'integrazione nativa del ciclo di vita CRUD per il motore avanzato Auto-Combo (#955). -**Operazioni principali:**Risolte le traduzioni mancanti per le nuove opzioni native di Auto-Combo (#955). -**Convalida della sicurezza:**Disabilitate le attività di backup automatico di SQLite in modo nativo durante l'esecuzione del CI di test unitario per risolvere in modo esplicito le perdite di memoria sospese del loop di eventi del nodo 22 (#956). -**Proxy dell'ecosistema:**completati gli scheduler di sincronizzazione del modello di mappatura dell'integrazione esplicita, i cicli OAuth e gli aggiornamenti di controllo token in modo sicuro tramite i proxy upstream del sistema nativo di OmniRoute (#953). -**Estensibilità MCP:**Aggiunto e registrato con successo il nuovo strumento framework MCP `omniroute_web_search` fuori versione beta negli schemi di produzione (#951). -**Logica del buffer dei token:**Aggiunti limiti di configurazione di runtime che estendono i buffer dei token di input/output configurabili per metriche precise di monitoraggio dell'utilizzo (#959).### 🐛 Bug Fixes\n\n-**Rimedio CodeQL:**Operazioni di indicizzazione di stringhe critiche completamente risolte e protette che prevengono l'euristica di indicizzazione degli array SSRF (Server-Side Request Forgery) insieme al backtracking algoritmico polinomiale (ReDoS) all'interno dei moduli dispatcher proxy profondi. -**Hash crittografici:**sostituiti gli hash OAuth 1.0 legacy deboli e non verificati con robuste primitive di convalida standard HMAC-SHA-256 che garantiscono controlli di accesso rigorosi. -**Protezione dei confini dell'API:**Protezioni del percorso strutturale correttamente verificate e mappate che applicano la rigorosa logica del middleware `isAuthenticated()` che copre i nuovi endpoint dinamici mirati alla manipolazione delle impostazioni e al caricamento delle competenze native. -**Compatibilità ecosistema CLI:**Risolti i collegamenti non funzionanti del parser runtime nativo che bloccavano i rilevatori dell'ambiente `where` rigorosamente sui casi limite `.cmd/.exe` per i plugin esterni (#969). -**Architettura della cache:**Refactoring dell'esatta memorizzazione nella cache della struttura del layout dei parametri del dashboard di analisi e impostazioni di sistema per mantenere stabili i cicli di persistenza della reidratazione risolvendo i flash visivi dello stato non allineato (#952). -**Standard di memorizzazione nella cache di Claude:**Indicatori di blocchi critici effimeri rigorosamente normalizzati e accuratamente conservati Ordini TTL di memorizzazione nella cache \"effimeri\" per i nodi downstream che impongono la mappatura delle richieste CC compatibili con gli standard in modo pulito senza metriche eliminate (#948). -**Autenticazione alias interni:**Mappature runtime interne semplificate che normalizzano le ricerche del payload delle credenziali Codex all'interno dei parametri di traduzione globali risolvendo 401 drop non autenticati (#958).### 🛠️ Maintenance\n\n-**Individuabilità dell'interfaccia utente:**categorizzazioni del layout corrette che separano esplicitamente la logica dei fornitori del livello gratuito migliorando i flussi di ordinamento UX all'interno delle pagine generali del registro API (#950). -**Topologia di distribuzione:**artefatti di distribuzione Docker unificati che garantiscono che la radice \"fly.toml\" corrisponda immediatamente ai parametri previsti dell'istanza cloud, gestendo in modo nativo le distribuzioni automatizzate con il corretto dimensionamento. -**Strumenti di sviluppo:**parametri di runtime `LKGP` disaccoppiati in utilità di caching esplicite di astrazione del livello DB che garantiscono una rigorosa copertura di isolamento dei test per i livelli di caching principali in modo sicuro.---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n-**Pannello Dashboard Auto-Combo:**completamente rifattorizzata l'interfaccia utente `/dashboard/auto-combo` per integrarsi perfettamente con le Dashboard Card native e con imbottiture/intestazioni visive standardizzate. Aggiunte barre di avanzamento visive dinamiche che mappano i meccanismi di peso della selezione del modello. -**Sincronizzazione del routing delle impostazioni:**bersagli dello schema \"prioritario\" e \"ponderato\" di routing avanzato completamente esposti internamente all'interno degli elenchi di fallback delle impostazioni globali.### Bug Fixes\n\n-**Nodi locali di memoria e competenze:**Risolti i tag di rendering vuoti per le opzioni di memoria e competenze direttamente all'interno delle visualizzazioni delle impostazioni globali collegando tutti i valori di mappatura `settings.*` internamente in `en.json` (mappati anche implicitamente per gli strumenti di traduzione incrociata).### Internal Integrations\n\n- PR n. 946 integrato: correzione: preserva la compatibilità del codice Claude nella conversione delle risposte\n- PR integrato n. 944 - correzione (gemini): preserva le firme dei pensieri durante le chiamate degli strumenti antigravità\n- PR n. 943 integrato: correzione: ripristino del corpo di GitHub Copilot\n- PR n. 942 integrato: corretti i marcatori di cache compatibili con cc\n- PR n. 941 integrato: refactor (autenticazione): migliora la ricerca dell'alias NVIDIA + aggiunge la registrazione degli errori LKGP\n- PR n. 939 integrato: ripristina la gestione del callback dell'host locale Claude OAuth\n- _(Nota: il PR n. 934 è stato omesso dal ciclo 3.4.9 per prevenire regressioni dei conflitti fondamentali)_---\n\n## [3.4.8] — 2026-04-03\n\n### Sicurezza\n\n- Risolti completamente tutti i risultati in sospeso di Github Advanced Security (CodeQL) e gli avvisi di Dependabot.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Comandi shell protetti in script automatizzati dall'iniezione di stringhe.\n- Migrazione dei modelli di analisi RegEx di backtracking catastrofico vulnerabile nelle pipeline di chat/traduzione.\n- Controlli migliorati sulla sanificazione dell'output all'interno dei componenti dell'interfaccia utente di React e sull'iniezione di tag SSE (Server Sent Events).---\n\n## [3.4.7] — 2026-04-03\n\n### Funzionalità\n\n- Aggiunto il nodo \"Crittografia\" al monitoraggio e ai controlli di salute MCP (#798)\n- Mappatura rafforzata dei permessi del percorso del catalogo modelli (`/models`) (#781)### Bug Fixes\n\n- Risolto il problema con l'aggiornamento del token Claude OAuth che non riusciva a preservare i contesti della cache (#937)\n- Risolti gli errori del provider compatibile con CC che rendevano irraggiungibili i modelli memorizzati nella cache (#937)\n- Risolti errori di GitHub Executor relativi a array di contesto non validi (#937)\n- Risolti gli errori di controllo dello stato degli strumenti CLI installati da NPM su Windows (#935)\n- Risolto il problema con la traduzione del payload che eliminava contenuti validi a causa di campi API non validi (#927)\n- Risolto crash di runtime nel Nodo 25 relativo all'esecuzione della chiave API (#867)\n- Risolta la risoluzione del modulo autonomo MCP (`ERR_MODULE_NOT_FOUND`) tramite `esbuild` (#936).\n- Risolta la mancata corrispondenza dell'alias di risoluzione delle credenziali di routing NVIDIA NIM (#931)### Sicurezza\n\n- Aggiunta una protezione rigorosa e sicura dei limiti di input contro le iniezioni di esecuzione di codice remoto \"shell: true\" non elaborate.---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n-**Fornitori:**registrati nuovi fornitori di immagini, video e generazione di audio dall'elenco richiesto dalla comunità (#926). -**Interfaccia utente dashboard:**aggiunta la navigazione autonoma nella barra laterale per i nuovi moduli Memoria e Abilità (#926). -**i18n:**Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.### 🐛 Bug Fixes\n\n-**Resilienza:**ha impedito che l'interruttore proxy del circuito rimanesse bloccato in uno stato APERTO per un tempo indefinito gestendo le transizioni dirette allo stato CHIUSO all'interno dei percorsi combinati di fallback (#930). -**Traduzione del protocollo:**patchato il trasformatore di streaming per disinfettare i blocchi di risposta in base al protocollo _source_ previsto anziché al protocollo _target_ del provider, risolvendo i modelli Anthropics racchiusi nei payload OpenAI che causavano l'arresto anomalo del codice Claude (#929). -**Specifiche API e Gemini:**Risolto il problema con l'analisi di `thinked_signature` nei traduttori `openai-to-gemini` e `claude-to-gemini`, prevenendo errori HTTP 400 in tutte le chiamate agli strumenti API Gemini 3. -**Provider:**ripuliti gli endpoint non compatibili con OpenAI che impedivano connessioni upstream valide (#926). -**Cache Trends:**Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n-**Integrazione dell'ecosistema CLIProxyAPI:**aggiunto l'esecutore `cliproxyapi` con caching a livello di modulo integrato e routing proxy. Introdotto un servizio completo di gestione delle versioni per testare automaticamente l'integrità, scaricare file binari da GitHub, generare processi in background isolati e gestire in modo pulito il ciclo di vita degli strumenti CLI esterni direttamente tramite l'interfaccia utente. Include tabelle DB per la configurazione proxy per abilitare il routing incrociato automatico con controllo SSRF di richieste OpenAI esterne tramite il livello dello strumento CLI locale (#914, #915, #916). -**Supporto Qoder PAT:**Supporto PAT (Personal Access Tokens) integrato direttamente tramite il trasporto locale `qodercli` invece delle configurazioni del browser remoto `.cn` legacy (#913). -**Gemini 3.1 Pro Preview (GitHub):**Aggiunto il supporto del modello esplicito canonico `gemini-3.1-pro-preview` in modo nativo nel provider GitHub Copilot preservando gli alias di routing precedenti (#924).### 🐛 Bug Fixes\n\n-**Stabilità token Copilot GitHub:**Riparato il ciclo di aggiornamento dei token Copilot in cui i token obsoleti non venivano integrati nel DB e rimossi i campi `reasoning_text` che interrompevano fatalmente le conversioni dei blocchi antropici downstream per le chat multi-turno (#923). -**Matrice di timeout globale:**Timeout delle richieste centralizzate e parametrizzate esplicitamente da `REQUEST_TIMEOUT_MS` per evitare che i buffer di recupero predefiniti nascosti (~300 s) interrompano prematuramente le risposte di streaming SSE di lunga durata da modelli di ragionamento pesanti (#918). -**Stato dei tunnel rapidi di Cloudflare:**Risolta una grave incoerenza di stato in cui le istanze OmniRoute riavviate mostravano erroneamente i tunnel distrutti come attivi e il tunneling cloudflared predefinito era \"HTTP/2\" per eliminare lo spam del log del buffer di ricezione UDP (#925). -**Revisione della traduzione i18n (ceco e hindi):**Risolto il problema con il codice hindi da \"in.json\" DEPRECATO a \"hi.json\" canonico, revisionate le mappature del testo ceco, estratto \"untranslatable-keys.json\" per correggere le convalide di falsi positivi CI/CD e generati documenti \"I18N.md\" completi per guidare i traduttori (#912). -**Ripristino del provider di token:**risolto il problema per cui Qwen perdeva endpoint `resourceUrl` specifici dopo l'aggiornamento automatico del token di controllo dello stato a causa della mancanza di unioni profonde di DB (#917). -**UX e streaming compatibili con CC:**unificate le azioni Aggiungi CC/OpenAI/compatibili con Anthropic attorno al trattamento dell'interfaccia utente di Anthropic, forzato le richieste upstream compatibili con CC a utilizzare SSE continuando a restituire risposte in streaming o non streaming in base alla richiesta del client, rimosso il supporto di configurazione/importazione dell'elenco di modelli CC in favore di un errore esplicito di elenco di modelli non supportato e reso i modelli disponibili compatibili con CC rispecchiano l'elenco di registro del codice OAuth Claude (#921).---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n-**Report sui token API di risposta:**emette `response.completed` con i campi `input_tokens`/`output_tokens` corretti per i client CLI Codex, correggendo la visualizzazione dell'utilizzo dei token (#909 — grazie @christopher-s). -**Checkpoint WAL SQLite allo spegnimento:**scarica le modifiche WAL nel file del database primario durante l'arresto/riavvio regolare, prevenendo la perdita di dati agli arresti del contenitore Docker (#905 — grazie @rdself). -**Segnale di spegnimento ordinato:**Modificati i percorsi `/api/restart` e `/api/shutdown` da `process.exit(0)` a `process.kill(SIGTERM)`, assicurando che il gestore di spegnimento venga eseguito prima dell'uscita. -**Docker Stop Grace Period:**Aggiunto `stop_grace_period: 40s` ai file Docker Compose e `--stop-timeout 40` agli esempi di esecuzione Docker.### 🛠️ Maintenance\n\n- Chiusi 5 problemi risolti/non-bug (#872, #814, #816, #890, #877).\n- Valutato 6 problemi con richieste di informazioni sui bisogni (#892, #887, #886, #865, #895, #870).\n- Risposta al problema di tracciamento del rilevamento della CLI (n. 863) con le indicazioni del collaboratore.---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n-**Memoria e competenze antigravità:**completata l'iniezione di memoria remota e competenze per il provider Antigravità a livello di rete proxy. -**Compatibilità con il codice Claude:**creato un bridge di compatibilità nascosto in modo nativo per Claude Code, passando strumenti e formattazione in modo pulito. -**Web Search MCP:**Aggiunto lo strumento `omniroute_web_search` con l'ambito `execute:search`. -**Componenti della cache:**Implementati componenti della cache dinamica che utilizzano TDD. -**UI e personalizzazione:**aggiunto supporto favicon personalizzato, schede di aspetto, whitelabeling cablato sulla barra laterale e aggiunti passaggi della guida Windsurf in tutte le 33 lingue. -**Conservazione dei registri:**Conservazione unificata dei registri delle richieste e degli artefatti in modo nativo. -**Miglioramenti del modello:**Aggiunto `contextLength` esplicito per tutti i modelli opencode-zen. -**i18n e traduzioni:**Traduzioni in 33 lingue integrate in modo nativo, comprese convalide CI segnaposto e aggiornamenti della documentazione cinese (#873, #869).### 🐛 Bug Fixes\n\n-**Mappatura OAuth Qwen:**Ripristinata la dipendenza da `id_token` a `access_token` e abilitata l'iniezione dinamica dell'endpoint API `resource_url` per il corretto routing regionale (#900). -**Motore di sincronizzazione del modello:**memorizzato il rigoroso ID provider interno nelle routine di sincronizzazione `getCustomModels()` invece del formato dell'alias del canale dell'interfaccia utente, prevenendo errori di inserimento del catalogo SQLite (#903). -**Codice e Codex Claude:**Risposte vuote standardizzate non in streaming a \"(risposta vuota)\" in formato Anthropic per evitare arresti anomali del proxy CLI (#866). -**Instradamento compatibile CC:**Risolta la collisione duplicata dell'endpoint `/v1` durante la concatenazione del percorso per i gateway Claude Code generici (#904). -**Dashboard antigravità:**è stato impedito ai modelli con quota illimitata di registrarsi erroneamente come stati limite di \"Utilizzo al 100%\" esauriti nell'interfaccia utente di utilizzo del provider (#857). -**Passthrough immagine Claude:**Risolto il problema per cui nei modelli Claude mancavano i passthrough del blocco immagine (#898). -**Instradamento CLI Gemini:**Risolti 403 blocchi di autorizzazione e problemi di accumulo di contenuti aggiornando l'ID progetto tramite \"loadCodeAssist\" (#868). -**Stabilità antigravità:**elenchi di accesso ai modelli corretti, blocchi 404 applicati, cascate 429 bloccate che bloccano le connessioni standard e token di output `gemini-3.1-pro` limitati (#885). -**Cadenza di sincronizzazione del provider:**Risolto il problema relativo ai limiti della cadenza di sincronizzazione del provider tramite lo scheduler interno (#888). -**Ottimizzazione del dashboard:**Risolto il blocco dell'interfaccia utente di `/dashboard/limits` durante l'elaborazione di oltre 70 account tramite parallelizzazione di blocchi (#784). -**Potenziamento SSRF:**applicato un rigoroso filtraggio dell'intervallo IP SSRF e bloccato l'interfaccia di loopback `::1`. -**Tipi MIME:**`mime_type` standardizzato in snake_case per corrispondere alle specifiche dell'API Gemini. -**Stabilizzazione CI:**Risolti problemi di analisi/impostazioni dei selettori del drammaturgo e delle asserzioni delle richieste in modo che le esecuzioni di GitHub Actions E2E passino in modo affidabile attraverso le interfacce utente localizzate e i controlli basati su switch. -**Test deterministici:**rimossi gli elementi di quota sensibili alla data dai test di utilizzo di Copilot e allineati i test di idempotenza/catalogo dei modelli con il comportamento di runtime unito. -**Indurimento del tipo MCP:**rimosse le regressioni esplicite \"qualsiasi\" a budget zero dal percorso di registrazione dello strumento server MCP. -**Motore di sincronizzazione modelli:**Ignorati gli override distruttivi di \"sostituzione\" quando la sincronizzazione automatica del provider produce un elenco di modelli vuoto, mantenendo la stabilità per i cataloghi dinamici (#899).### 🛠️ Maintenance\n\n-**Registrazione della pipeline:**perfezionamento degli artefatti di registrazione della pipeline e applicazione dei limiti di conservazione (#880). -**AGENTS.md Revisione:**condensato da 297→153 righe. Aggiunte linee guida per build/test/stile, flussi di lavoro del codice (Prettier, TypeScript, ESLint) e tabelle dettagliate ritagliate (#882). -**Integrazione dei rami di rilascio:**consolidati i rami delle funzionalità attive in \"release/v3.4.2\" sopra l'attuale \"main\" e convalidato il ramo con lint, unità, copertura, build ed esecuzioni E2E in modalità CI. -**Test:**aggiunta la configurazione Vitest per il test dei componenti e le specifiche di Playwright per attivare/disattivare le impostazioni. -**Aggiornamenti documenti:**Leggimi root espansi, traduzione nativa di documenti cinesi e ripulitura di file obsoleti.## [3.4.1] - 2026-03-31\n\n> [!ATTENZIONE]\n> **MODIFICA IMPORTANTE: le variabili di ambiente di registrazione, conservazione e registrazione delle richieste sono state riprogettate.**\n> Al primo avvio dopo l'aggiornamento, OmniRoute archivia i registri delle richieste legacy da `DATA_DIR/logs/`, `DATA_DIR/call_logs/` legacy e `DATA_DIR/log.txt` in `DATA_DIR/log_archives/*.zip`, quindi rimuove il layout obsoleto e passa al nuovo formato artefatto unificato in `DATA_DIR/call_logs/`.### ✨ New Features\n\n-**Utilità di migrazione .ENV:**Incluso `scripts/migrate-env.mjs` per migrare senza problemi le configurazioni `` quando è attivo l'accesso limitato (#781) -**Integrazione Qoder:**Integrazione nativa per Qoder AI che sostituisce nativamente le mappature della piattaforma iFlow legacy (#660) -**Tracciamento della cache dei prompt:**Aggiunte funzionalità di tracciamento e visualizzazione frontend (scheda Statistiche) per la memorizzazione nella cache semantica e dei prompt nell'interfaccia utente della dashboard### 🐛 Bug Fixes\n\n-**Ridimensionamento della dashboard della cache:**migliorate le dimensioni del layout dell'interfaccia utente e le intestazioni di contesto per le pagine della cache avanzate (#835) -**Visibilità della barra laterale di debug:**Risolto un problema per cui l'interruttore di debug non mostrava/nascondeva correttamente i dettagli di debug della barra laterale (#834) -**Prefisso del modello Gemini:**Modificato il fallback dello spazio dei nomi per instradare correttamente tramite `gemini-cli/` anziché `gc/` per rispettare le specifiche upstream (#831) -**OpenRouter Sync:**Migliorata la sincronizzazione della compatibilità per acquisire automaticamente e correttamente il catalogo dei modelli disponibili da OpenRouter (#830) -**Mappatura dei payload in streaming:**La riserializzazione dei campi di ragionamento risolve in modo nativo i percorsi degli alias in conflitto quando l'output viene trasmesso in streaming ai dispositivi edge---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n-**Configurazione OpenCode:**Ristrutturato il file \"opencode.json\" generato per utilizzare lo schema basato su record \"@ai-sdk/openai-compatibili\" con \"opzioni\" e \"modelli\" come mappe di oggetti anziché array piatti, risolvendo gli errori di convalida della configurazione (#816) -**Chiavi mancanti i18n:**Aggiunta la chiave di traduzione `cloudflaredUrlNotice` mancante in tutti i 30 file di lingua per prevenire errori della console `MISSING_MESSAGE` nella pagina Endpoint (#823)---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n-**Contabilità token:**Inclusi i token della cache dei prompt in modo sicuro nei calcoli degli input di utilizzo storico per le corrette detrazioni delle quote (PR n. 822) -**Sonde di test combinati:**Risolti i falsi negativi della logica dei test combinati risolvendo l'analisi per le risposte di solo ragionamento e abilitando la parallelizzazione massiccia tramite Promise.all (PR #828) -**Docker Quick Tunnels:**certificati ca richiesti incorporati all'interno del contenitore di runtime di base per risolvere gli errori di avvio di Cloudflared TLS e gli errori di rete stdout emersi che sostituiscono i codici di uscita generici (PR #829)---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n-**Monitoraggio delle quote Gemini:**Aggiunto il monitoraggio delle quote della CLI Gemini in tempo reale tramite l'API `retrieveUserQuota` (PR #825) -**Dashboard della cache:**migliorato il Dashboard della cache per visualizzare i parametri della cache dei prompt, le tendenze 24 ore e il risparmio sui costi stimato (PR n. 824)### 🐛 Bug Fixes\n\n-**Esperienza utente:**Rimossi i loop modali OAuth invasivi con apertura automatica sulle pagine dettagliate dei provider sterili (PR n. 820) -**Aggiornamenti alle dipendenze:**Dipendenze migliorate e bloccate per alberi di sviluppo e produzione tra cui Next.js 16.2.1, Recharts e TailwindCSS 4.2.2 (PR #826, #827)---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n-**Compatibilità Codex e Claude:**Risolti i fallback dell'interfaccia utente, corretti i problemi di integrazione non streaming del Codex e risolto il rilevamento del runtime della CLI su Windows. -**Automazione del rilascio:**Autorizzazioni estese richieste per la build dell'app Electron in GitHub Actions. -**Cloudflare Runtime:**Risolti i codici di uscita corretti di isolamento del runtime per i componenti del tunnel Cloudflared.### 🧪 Tests\n\n-**Aggiornamenti della suite di test:**copertura dei test estesa per rilevatori di volume, diversità dei provider, verifica della configurazione e FSM.---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n-**Affidabilità CI/CD:**Azioni GitHub patchate per versioni di dipendenza stabili (`actions/checkout@v4`, `actions/upload-artifact@v4`) per mitigare le deprecazioni non annunciate dell'ambiente builder. -**Fallback di immagini:**sostituite le catene di fallback arbitrarie in \"ProviderIcon.tsx\" con una convalida esplicita delle risorse per impedire il caricamento dell'interfaccia utente dei componenti \"\" per file che non esistono, eliminando gli errori \"404\" nei log della console del dashboard (#745). -**Admin Updater:**Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743). -**Errore ERESOLVE di aggiornamento:**Inserito `package.json` sostituisce `react`/`react-dom` e abilitato `--legacy-peer-deps` negli script interni di aggiornamento automatico per risolvere i conflitti dell'albero delle dipendenze con `@lobehub/ui`.---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n-**Tunnel Cloudflare:**Integrazione di Cloudflare Quick Tunnel con controlli dashboard (PR n. 772). -**Diagnostica:**Bypass della cache semantica per test live combinati (PR n. 773).### 🐛 Bug Fixes\n\n-**Stabilità dello streaming:**applica `FETCH_TIMEOUT_MS` alla chiamata iniziale `fetch()` delle richieste di streaming per evitare che il timeout TCP di Node.js 300 s causi errori delle attività silenziose (#769). -**i18n:**Aggiunte le voci mancanti `windsurf` e `copilot` a `toolDescriptions` in tutti i 33 file locali (#748). -**Verifica della codifica GLM:**Verifica completa del fornitore che risolve le vulnerabilità ReDoS, il dimensionamento della finestra di contesto (128k/16k) e la sincronizzazione del registro dei modelli (PR n. 778).---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n-**Codice OpenAI:**Correzione dell'elaborazione di fallback per elementi `type: \"text\"` che trasportavano set di dati nulli o vuoti che causavano il rifiuto 400 (#742). -**Opencode:**Aggiorna l'allineamento dello schema al \"provider\" singolare per corrispondere alle specifiche ufficiali (#774). -**Gemini CLI:**inserisce intestazioni di quota dell'utente finale mancanti che impediscono i blocchi di autorizzazione 403 (#775). -**Recupero DB:**Refactoring delle importazioni di payload multiparte in array binari non elaborati con buffer per bypassare i limiti massimi del corpo del proxy inverso (#770).---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Stabilizzazione del rilascio**: rilascio v3.2.9 finalizzato (diagnostica combinata, controlli di qualità, correzione dello strumento Gemini) e creazione del tag git mancante. Consolidate tutte le modifiche graduali in un unico commit di rilascio atomico.### 🐛 Bug Fixes\n\n-**Test di aggiornamento automatico**— Risolto il problema con l'asserzione di test `buildDockerComposeUpdateScript` per far corrispondere i riferimenti alle variabili della shell non espanse (`$TARGET_TAG`, `${TARGET_TAG#v}`) nello script di distribuzione generato, allineandosi con il modello rifattorizzato dalla v3.2.8. -**Circuit Breaker Test**— Rafforzato `combo-circuit-breaker.test.mjs` inserendo `maxRetries: 0` per evitare che l'inflazione dei tentativi distorca le asserzioni del conteggio degli errori durante le transizioni dello stato dell'interruttore.---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Combo Diagnostics**: introdotto un flag di bypass del test in tempo reale (`forceLiveComboTest`) che consente agli amministratori di eseguire controlli di integrità reali a monte che ignorano tutti gli interruttori automatici locali e i meccanismi di stato di raffreddamento, consentendo una diagnostica precisa durante le interruzioni di corrente (PR n. 759) -**Quality Gate**: aggiunta la convalida automatizzata della qualità della risposta per le combo e il supporto del modello `claude-4.6` ufficialmente integrato negli schemi di routing principali (PR #762)### 🐛 Bug Fixes\n\n-**Convalida della definizione dello strumento**: corretta l'integrazione dell'API Gemini normalizzando i tipi di enumerazione all'interno delle definizioni dello strumento, prevenendo errori dei parametri HTTP 400 upstream (PR n. 760)---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Interfaccia utente di aggiornamento automatico Docker**: integrato un processo di aggiornamento in background separato per le distribuzioni Docker Compose. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability. -**Cache Analytics**— Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.### 🐛 Bug Fixes\n\n-**Logica di autenticazione**: risolto un bug per cui il salvataggio delle impostazioni del dashboard o l'aggiunta di modelli non riusciva con un errore 401 Non autorizzato quando `requireLogin` era disabilitato. Gli endpoint API ora valutano correttamente l'attivazione/disattivazione dell'autenticazione globale. Risolto il reindirizzamento globale riattivando `src/middleware.ts`. -**Rilevamento strumento CLI (Windows)**— Impedisce eccezioni irreversibili di inizializzazione durante il rilevamento dell'ambiente CLI rilevando correttamente gli errori ENOENT `cross-spawn`. Aggiunge percorsi di rilevamento espliciti per `\\AppData\\Local\\droid\\droid.exe`. -**Passthrough nativo del Codex**: parametri di traduzione del modello normalizzati che impediscono l'avvelenamento del contesto in modalità passthrough proxy, applicando esplicitamente i vincoli generici \"store: false\" per tutte le richieste originate dal Codex. -**Report sui token SSE**: rilevamento normalizzato del blocco `finish_reason` della chiamata allo strumento del provider, correzione dell'analisi dell'utilizzo dello 0% per le risposte solo streaming prive di indicatori \"\" rigorosi. -**Tag di DeepSeek**— Implementata una mappatura esplicita di estrazione di `` all'interno di `responsesHandler.ts`, garantendo che i flussi di ragionamento di DeepSeek siano mappati in modo equivalente alle strutture `` antropiche native.---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n-**Aggiornamenti semplici dell'interfaccia utente**: la funzione \"Aggiorna ora\" sulla dashboard ora fornisce feedback in tempo reale e trasparenti utilizzando gli eventi inviati dal server (SSE). Esegue l'installazione dei pacchetti, la ricostruzione dei moduli nativi (better-sqlite3) e PM2 si riavvia in modo affidabile mostrando caricatori in tempo reale invece di bloccarsi silenziosamente.---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Rivelazione chiave API (#740)**— Aggiunto un flusso di copia della chiave API con ambito nel Gestore API, protetto dalla variabile di ambiente `ALLOW_API_KEY_REVEAL`. -**Controlli di visibilità della barra laterale (#739)**: gli amministratori ora possono nascondere qualsiasi collegamento di navigazione della barra laterale tramite le impostazioni di Aspetto per ridurre l'ingombro visivo. -**Test combinato rigoroso (#735)**: rafforzato l'endpoint del controllo dello stato della combo per richiedere risposte di testo in tempo reale dai modelli invece di semplici segnali di raggiungibilità. -**Registri dettagliati in streaming (#734)**: modificato il registro dettagliato delle richieste per i flussi SSE per ricostruire il payload finale, risparmiando enormi quantità di dimensioni del database SQLite e ripulendo in modo significativo l'interfaccia utente.### 🐛 Bug Fixes\n\n-**OpenCode Go MiniMax Auth (#733)**— Corretta la logica dell'intestazione di autenticazione per i modelli \"minimax\" su OpenCode Go per utilizzare \"x-api-key\" invece dei token di connessione standard nel protocollo \"/messages\".---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Void Linux Deployment Support (#732)**— Modello di packaging `xbps-src` integrato e istruzioni per compilare e installare in modo nativo OmniRoute con collegamenti `better-sqlite3` tramite target di compilazione incrociata.## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Migrazione Qoder AI (#660)**: migrazione completa del provider principale legacy `iFlow` su `Qoder AI` mantenendo funzionalità di routing API stabili.### 🐛 Bug Fixes\n\n-**Argomento non valido del payload HTTP 400 di Gemini Tools (#731)**: impedito l'inserimento di array `thinkSignature` all'interno delle sequenze Gemini `functionCall` standard che bloccavano i flussi di routing degli agenti.---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Interfaccia utente quota limiti provider (#728)**: logica del limite quota normalizzata ed etichettatura dei dati all'interno dell'interfaccia Limiti.### 🐛 Bug Fixes\n\n-**Schemi e perdite di routing principali**: `comboStrategySchema` espanso per supportare in modo nativo le strategie `fill-first` e `p2c` per sbloccare la modifica combinata complessa in modo nativo. -**Thinking Tags Extraction (CLI)**— Risposte token CLI ristrutturate disinfettano RegEx catturando le strutture di ragionamento del modello all'interno dei flussi evitando estrazioni \"\" interrotte che interrompono il formato di output del testo della risposta. -**Applicazioni rigorose dei formati**: esecuzione rafforzata della sanificazione della pipeline che la rende applicabile universalmente agli obiettivi della modalità di traduzione.---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n-**Pipeline del registro delle richieste in quattro fasi (#705)**: refactoring della persistenza del registro per salvare payload completi in quattro fasi distinte della pipeline: richiesta del cliente, richiesta del fornitore tradotto, risposta del fornitore e risposta del cliente tradotto. Introdotto \"streamPayloadCollector\" per un robusto troncamento del flusso SSE e la serializzazione del payload.### 🐛 Bug Fixes\n\n-**Correzioni dell'interfaccia utente mobile (#659)**— Impedisce ai componenti della tabella sul dashboard di interrompere il layout su finestre strette aggiungendo lo scorrimento orizzontale corretto e il contenimento dell'overflow a `DashboardLayout`. -**Correzioni di Claude Prompt Cache (#708)**— Garantito che i blocchi `cache_control` nei loop di fallback da Claude a Claude siano conservati fedelmente e passati in modo sicuro ai modelli antropici. -**Definizioni strumento Gemini (#725)**— Risolti errori di traduzione dello schema durante la dichiarazione di tipi di parametri semplici \"oggetto\" per la chiamata della funzione Gemini.## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n-**Provider di fallback globale (#689)**: quando tutti i modelli combinati sono esauriti (502/503), OmniRoute ora tenta un modello di fallback globale configurabile prima di restituire l'errore. Imposta \"globalFallbackModel\" nelle impostazioni per abilitare.### 🐛 Bug Fixes\n\n-**Correzione #721**— Risolto il problema relativo al bypass del blocco del contesto durante le risposte alle chiamate allo strumento. Il tagging non streaming utilizzava un percorso JSON errato (`json.messages` → `json.choices[0].message`). L'inserimento dello streaming ora si attiva sui blocchi \"finish_reason\" per i flussi di sole chiamate allo strumento. `injectModelTag()` ora aggiunge messaggi pin sintetici per contenuti non di tipo stringa. -**Correzione #709**— Confermato già corretto (v3.1.9) — `system-info.mjs` crea directory in modo ricorsivo. Chiuso. -**Correzione #707**— Confermata già corretta (v3.1.9) — Sanificazione del nome dello strumento vuoto in `chatCore.ts`. Chiuso.### 🧪 Tests\n\n- Aggiunti 6 unit test per il blocco del contesto con risposte alle chiamate agli strumenti (contenuto nullo, contenuto dell'array, andata e ritorno, re-iniezione)## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n-**Interfaccia utente di gestione della cache**: aggiunta una dashboard dedicata alla memorizzazione nella cache semantica in \\`/dashboard/cache\\` con invalidazione API mirata e supporto i18n in 31 lingue (PR n. 701 di @oyi77) -**Tracciamento quota GLM**: aggiunto il monitoraggio dell'utilizzo in tempo reale e della quota della sessione per il provider GLM Coding (Z.AI) (PR n. 698 di @christopher-s) -**Payload di registro dettagliati**: acquisizione cablata del payload completo della pipeline in quattro fasi (originale, tradotto, risposta del fornitore, delta in streaming) direttamente nell'interfaccia utente (PR n. 705 di @rdself)### 🐛 Bug Fixes\n\n-**Correzione #708**: impedimento del tokenbleed per gli utenti di Claude Code che instradano tramite OmniRoute preservando correttamente le intestazioni \\`cache_control\\` native durante il passthrough Claude-to-Claude (PR #708 di @tombii) -**Correzione #719**— Imposta i limiti di autenticazione interni per \\`ModelSyncScheduler\\` per prevenire errori del demone non autenticato all'avvio (PR #719 di @rdself) -**Correzione n. 718**: rendering del badge ricostruito nell'interfaccia utente dei limiti del fornitore per evitare sovrapposizioni errate dei limiti delle quote (PR n. 718 di @rdself) -**Correzione #704**— Risolti i fallback combinati che interrompevano gli errori di policy dei contenuti HTTP 400 che impedivano il dead-routing della rotazione del modello (PR #704 di @rdself)### 🔒 Security & Dependencies\n\n- \\`path-to-regexp\\` aggiornato a \\`8.4.0\\` per risolvere le vulnerabilità di dependabot (PR #715)## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n-**Correzione #706**— Risolto il problema con il rendering di fallback delle icone causato dall'override di `font-sans` di Tailwind V4 applicando `!important` a `.material-symbols-outlined`. -**Correzione #703**— Risolti i problemi relativi ai flussi di GitHub Copilot interrotti abilitando \"risposte\" alla traduzione del formato \"openai\" per qualsiasi modello personalizzato che sfruttava \"apiFormat: \"risposte\"\". -**Correzione #702**— Sostituito il monitoraggio dell'utilizzo a tariffa fissa con calcoli accurati dei prezzi DB sia per le risposte in streaming che per quelle non in streaming. -**Correzione #716**— Ripulito lo stato di traduzione delle chiamate agli strumenti di Claude, analizzando correttamente gli argomenti di streaming e impedendo ai blocchi `tool_calls` di OpenAI di ripetere il campo `id`.## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n-**Coercizione schema**: forza automaticamente i vincoli dello schema JSON numerico con codifica stringa (ad esempio `\"minimo\": \"1\"`) ai tipi corretti, impedendo errori 400 da Cursor, Cline e altri client che inviano schemi di strumenti non validi. -**Sanificazione della descrizione dello strumento**: garantisce che le descrizioni degli strumenti siano sempre stringhe; converte descrizioni `null`, `unfine` o numeriche in stringhe vuote prima dell'invio ai provider. -**Pulsante Cancella tutti i modelli**: aggiunte le traduzioni i18n per l'azione del provider \"Cancella tutti i modelli\" in tutte le 30 lingue. -**Esportazione autenticazione Codex**: aggiunti i pulsanti di esportazione e applicazione locale del Codex `auth.json` per una perfetta integrazione della CLI. -**Note su Windsurf BYOK**: aggiunti avvisi di limitazione ufficiali alla scheda dello strumento CLI di Windsurf che documentano i vincoli BYOK.### 🐛 Bug Fixes\n\n-**Correzione #709**— `system-info.mjs` non si blocca più quando la directory di output non esiste (aggiunto `mkdirSync` con flag ricorsivo). -**Correzione #710**— Il singleton A2A `TaskManager` ora utilizza `globalThis` per prevenire perdite di stato attraverso le ricompilazioni del percorso API Next.js in modalità dev. Suite di test E2E aggiornata per gestire correttamente 401. -**Correzione #711**— Aggiunta l'applicazione del limite massimo `max_tokens` specifico del provider per le richieste upstream. -**Correzione #605 / #592**— Elimina il prefisso `proxy_` dai nomi degli strumenti nelle risposte di Claude non in streaming; corretto l'URL di convalida LongCat. -**Call Logs Max Cap**— Aggiornato `getMaxCallLogs()` con livello di caching, supporto env var (`CALL_LOGS_MAX`) e integrazione delle impostazioni DB.### 🧪 Tests\n\n- Suite di test ampliata da 964 → 1027 test (63 nuovi test)\n- Aggiunto `schema-coercion.test.mjs` - 9 test per la coercizione del campo numerico e la sanificazione della descrizione dello strumento\n- Aggiunto `t40-opencode-cli-tools-integration.test.mjs` — Test di integrazione CLI OpenCode/Windsurf\n- Ramo di test delle funzionalità migliorato con strumenti di copertura completi### 📁 New Files\n\n| File | Scopo |\n| ------------------------------------------------------- | ------------------------------------------------------------------------------- | ---------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema di coercizione e descrizione degli strumenti di utilità di sanificazione |\n| `test/unità/schema-coercion.test.mjs` | Unit test per la coercizione dello schema |\n| `test/unit/t40-opencode-cli-tools-integration.test.mjs` | Test di integrazione dello strumento CLI |\n| `COVERAGE_PLAN.md` | Documento di pianificazione della copertura del test | ### 🐛 Bug Fixes |\n\n-**Claude Prompt Caching Passthrough**— Risolto il problema con i marcatori cache_control che venivano eliminati nella modalità passthrough di Claude (Claude → OmniRoute → Claude), che causava agli utenti di Claude Code l'esaurimento della quota API Anthropic 5-10 volte più velocemente delle connessioni dirette. OmniRoute ora preserva gli indicatori cache_control del client quando sourceFormat e targetFormat sono entrambi Claude, garantendo che la memorizzazione nella cache dei prompt funzioni correttamente e riducendo drasticamente il consumo di token.## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n-**Platform Core:**Implementata la gestione dello stato globale per modelli e combo nascosti impedendo loro di ingombrare il catalogo o di fuoriuscire negli agenti MCP connessi (#681). -**Stabilità:**sono stati corretti arresti anomali dello streaming relativi al fallimento dell'integrazione del provider Antigravity nativo a causa di array di stati non definiti non gestiti (#684). -**Sincronizzazione della localizzazione:**Distribuito un sincronizzatore `i18n` completamente revisionato che rileva le proprietà JSON nidificate mancanti e adatta 30 localizzazioni in sequenza (#685).## [3.1.7] - 27-03-2026### 🐛 Bug Fixes\n\n-**Stabilità dello streaming:**Risolto il problema con `hasValuableContent` che restituiva `undefinito` per blocchi vuoti nei flussi SSE (#676). -**Chiamate degli strumenti:**È stato risolto un problema in \"sseParser.ts\" per cui le risposte di Claude non in streaming con più chiamate agli strumenti perdevano l'\"id\" delle successive chiamate agli strumenti a causa di una deduplicazione errata basata sull'indice (#671).---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n-**Ripristino del nome dello strumento nativo di Claude**: i nomi degli strumenti come \"TodoWrite\" non hanno più il prefisso \"proxy\\_\" nelle risposte passthrough di Claude (sia in streaming che non in streaming). Include la copertura del test unitario (PR n. 663 di @coobabm) -**Cancella tutti gli alias dei modelli**: il pulsante \"Cancella tutti i modelli\" ora rimuove anche gli alias dei modelli associati, impedendo i modelli fantasma nell'interfaccia utente (PR #664 di @rdself)---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n-**Decadimento automatico backoff**: gli account con velocità limitata ora si ripristinano automaticamente alla scadenza della finestra di recupero, risolvendo un deadlock in cui un `backoffLevel` elevato depriorizzava permanentemente gli account (PR n. 657 di @brendandebeasi)### 🌍 i18n\n\n-**Revisione della traduzione cinese**: riscrittura completa di `zh-CN.json` con maggiore precisione (PR n. 658 di @only4copilot)---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n-**Correzione dell'override dello streaming**— L'esplicito `stream: true` nel corpo della richiesta ora ha la priorità sull'intestazione `Accept: application/json`. I client che inviano entrambi riceveranno correttamente le risposte in streaming SSE (#656)### 🌍 i18n\n\n-**Miglioramenti alle stringhe in ceco**— Terminologia raffinata in `cs.json` (PR #655 di @zen0bit)---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n-**~70 chiavi di traduzione mancanti**aggiunte a `en.json` e 12 lingue (PR #652 di @zen0bit) -**Documentazione ceca aggiornata**: guide CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT (PR n. 652) -**Script di convalida della traduzione**— `check_translations.py` e `validate_translation.py` per CI/QA (PR n. 651 di @zen0bit)---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n-**Critico: regressione delle chiamate agli strumenti**— Risolti gli errori `proxy_Bash` disabilitando il prefisso del nome dello strumento `proxy_` nel percorso passthrough di Claude. Strumenti come `Bash`, `Read`, `Write` venivano rinominati in `proxy_Bash`, `proxy_Read`, ecc., costringendo Claude a rifiutarli (#618) -**Documentazione sull'esclusione dell'account Kiro**: documentata come falso positivo antifrode AWS upstream, non un problema di OmniRoute (#649)### 🧪 Tests\n\n-**936 test, 0 fallimenti**---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n-**Metadati sulla capacità di visione**: aggiunti `capabilities.vision`, `input_modalities` e `output_modalities` alle voci \"/v1/models\" per i modelli con capacità di visione (PR #646) -**Modelli Gemini 3.1**: aggiunti `gemini-3.1-pro-preview` e `gemini-3.1-flash-lite-preview` al provider Antigravity (#645)### 🐛 Bug Fixes\n\n-**Errore Ollama Cloud 401**: corretto l'URL di base API errato: modificato da \"api.ollama.com\" a \"ollama.com/v1/chat/completions\" ufficiale (#643) -**Riprova token scaduto**: aggiunto nuovo tentativo limitato con backoff esponenziale (5→10→20 min) per le connessioni OAuth scadute invece di saltarle permanentemente (PR n. 647)### 🧪 Tests\n\n-**936 test, 0 fallimenti**---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n-**Modelli di problemi GitHub**: aggiunti report di bug standardizzati, richieste di funzionalità e modelli di problemi di configurazione/proxy (#641) -**Cancella tutti i modelli**: aggiunto un pulsante \"Cancella tutti i modelli\" alla pagina dei dettagli del fornitore con supporto i18n in 29 lingue (#634)### 🐛 Bug Fixes\n\n-**Conflitto locale (`in.json`)**: rinominato il file locale hindi da `in.json` (codice ISO indonesiano) a `hi.json` per correggere i conflitti di traduzione in Weblate (#642) -**Nomi strumenti vuoti del Codex**: spostata la sanificazione del nome dello strumento prima del passthrough del Codex nativo, corretti 400 errori dai fornitori upstream quando gli strumenti avevano nomi vuoti (#637) -**Streaming di artefatti di fine riga**: aggiunto `collapseExcessiveNewlines` al sanitizzatore di risposta, comprimendo esecuzioni di 3+ caratteri di fine riga consecutivi dai modelli pensanti in un doppio fine riga standard (#638) -**Sforzo di ragionamento di Claude**: convertito il parametro \"reasoning_effort\" di OpenAI nel blocco di budget \"thinking\" nativo di Claude su tutti i percorsi di richiesta, incluso l'aggiustamento automatico di \"max_tokens\" (#627). -**Aggiornamento del token Qwen**: implementato l'aggiornamento proattivo del token OAuth pre-scadenza (buffer di 5 minuti) per evitare che le richieste falliscano quando si utilizzano token di breve durata (#631)### 🧪 Tests\n\n-**936 test, 0 fallimenti**(+10 test dalla versione 3.0.9)---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n-**Token NaN nel codice Claude/risposte del cliente (#617):**\n\n- `sanitizeUsage()` ora esegue il cross-map di `input_tokens`→`prompt_tokens` e `output_tokens`→`completion_tokens` prima del filtro whitelist, correggendo le risposte che mostrano i conteggi dei token NaN/0 quando i provider restituiscono nomi di campi di utilizzo in stile Claude### Sicurezza\n\n- Pacchetto `yaml` aggiornato per correggere la vulnerabilità di overflow dello stack (GHSA-48c2-rrv3-qjmp)### 📋 Issue Triage\n\n- Chiuso n. 613 (Codestral: risolto con la soluzione alternativa del fornitore personalizzato)\n- Commento su #615 (OpenCode dual-endpoint: soluzione alternativa fornita, tracciata come richiesta di funzionalità)\n- Commento su #618 (visibilità chiamata strumento - richiesta test v3.0.9)\n- Commentato su #627 (livello di sforzo - già supportato)---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n-**Errori di traduzione per i provider di formato OpenAI nella CLI Claude (#632):**\n\n- Gestisci il formato array `reasoning_details[]` da StepFun/OpenRouter: converte in `reasoning_content`\n- Gestisci l'alias del campo \"reasoning\" di alcuni provider → normalizzato in \"reasoning_content\".\n- Nomi dei campi di utilizzo su più mappe: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n- Risolto il problema con `extractUsage` per accettare sia `input_tokens`/`output_tokens` che `prompt_tokens`/`completion_tokens` come campi di utilizzo validi\n- Applicato sia ai percorsi di streaming (`sanitizeStreamingChunk`, traduttore `openai-to-claude.ts`) che a quelli non streaming (`sanitizeMessage`)---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n-**Aggiornamento token antigravità:**Risolto errore `client_secret mancante` per gli utenti con installazione npm: `clientSecretDefault` era vuoto in providerRegistry, causando il rifiuto da parte di Google delle richieste di aggiornamento dei token (#588) -**Modelli OpenCode Zen:**Aggiunto `modelsUrl` alla voce del registro OpenCode Zen in modo che \"Importa da /models\" funzioni correttamente (#612) -**Artefatti in streaming:**Risolti i caratteri eccessivi di fine riga lasciati nelle risposte dopo la rimozione della firma del think-tag (#626). -**Proxy Fallback:**Aggiunto nuovo tentativo automatico senza proxy quando il relè SOCKS5 fallisce -**Test proxy:**L'endpoint di test ora risolve le credenziali reali dal DB tramite proxyId### ✨ New Features\n\n-**Selettore account/chiave Playground:**menu a discesa persistente e sempre visibile per selezionare account/chiavi provider specifici per il test: recupera tutte le connessioni all'avvio e filtra in base al provider selezionato -**Modelli dinamici degli strumenti CLI:**la selezione del modello ora viene recuperata dinamicamente dall'API `/v1/models`: fornitori come Kiro ora mostrano il loro catalogo di modelli completo -**Elenco modelli antigravità:**Aggiornato con Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; abilitato `passthroughModels` per l'accesso al modello dinamico (#628)### 🔧 Maintenance\n\n- PR n. 625 unito: correzione dello sfondo della modalità luce dei limiti del provider---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n-**Limiti/Proxy:**Risolto il problema con il recupero del limite del Codex per gli account dietro proxy SOCKS5: l'aggiornamento del token ora viene eseguito all'interno del contesto proxy -**CI:**Risolto problema relativo all'asserzione del test di integrazione `v1/models` in ambienti CI senza connessioni al provider -**Impostazioni:**Il pulsante del test proxy ora mostra immediatamente i risultati di successo/fallimento (precedentemente nascosto dietro i dati sanitari)### ✨ New Features\n\n-**Parco giochi:**aggiunto menu a discesa del selettore dell'account: testa connessioni specifiche individualmente quando un provider ha più account### 🔧 Maintenance\n\n- PR n. 623 unito: correzione del percorso URL di base dell'API LongCat---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n-**Limiti dell'interfaccia utente:**Aggiunta la funzionalità di raggruppamento dei tag alla dashboard delle connessioni per migliorare l'organizzazione visiva per gli account con tag personalizzati.---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n-**Streaming:**Risolto il problema del danneggiamento dello stato di `TextDecoder` all'interno della combo `sanitize` TransformStream che causava l'output confuso di SSE corrispondente ai caratteri multibyte (PR #614). -**Interfaccia utente dei provider:**visualizza in modo sicuro i tag HTML all'interno dei suggerimenti sugli errori di connessione del provider utilizzando \"dangerouslySetInnerHTML\" -**Impostazioni proxy:**Aggiunte le proprietà mancanti del corpo del payload \"nome utente\" e \"password\" che consentono la verifica corretta dei proxy autenticati dalla dashboard. -**API del provider:**l'eccezione soft associata ritorna a `getCodexUsage` impedendo errori dell'API HTTP 500 quando il recupero del token non riesce---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n-**Modelli con sincronizzazione automatica:**Aggiunto un interruttore dell'interfaccia utente e un endpoint \"sync-models\" per sincronizzare automaticamente gli elenchi di modelli per provider utilizzando uno scheduler a intervalli pianificati (PR n. 597)### 🐛 Bug Fixes\n\n-**Timeouts:**Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609) -**Rilevamento strumento CLI:**Rilevamento multipiattaforma migliorato per la gestione dei percorsi NVM, `PATHEXT` di Windows (prevenzione del problema dei wrapper `.cmd`) e prefissi NPM personalizzati (PR #598) -**Log di streaming:**Implementato l'accumulo delta `tool_calls` nei log di risposta di streaming in modo che le chiamate alle funzioni vengano tracciate e mantenute accuratamente nel DB (PR n. 603) -**Catalogo modelli:**Rimossa l'esenzione dall'autenticazione, nascondendo correttamente i modelli `comfyui` e `sdwebui` quando nessun provider è esplicitamente configurato (PR #599)### 🌐 Translations\n\n-**cs:**Stringhe di traduzione in ceco migliorate nell'app (PR n. 601)## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Aggiunto un campo Tag/Gruppo a \"EditConnectionModal\" (memorizzato in \"providerSpecificData.tag\") senza richiedere migrazioni dello schema DB.\n- Le connessioni nella vista del provider ora vengono raggruppate dinamicamente per tag con divisori visivi.\n- Le connessioni senza tag vengono visualizzate per prime senza intestazione, seguite dai gruppi contrassegnati in ordine alfabetico.\n- Il raggruppamento dei tag si applica automaticamente alla sezione Codex/Copilot/Limiti di antigravità poiché esistono dei commutatori all'interno delle righe di connessione.### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n-**Badge mancanti sulle schede di connessione:**Risolto utilizzando `resolveProxyForConnection()` anziché la mappatura statica. -**Test connessione disabilitato in modalità salvata:**abilitato il pulsante Test risolvendo la configurazione proxy dall'elenco salvato. -**Blocco modale configurazione:**Aggiunte chiamate `onClose()` dopo il salvataggio/cancella per impedire il blocco dell'interfaccia utente. -**Conteggio doppio dell'utilizzo:**`ProxyRegistryManager` ora carica con entusiasmo l'utilizzo sul supporto con deduplicazione tramite `scope` + `scopeId`. I conteggi di utilizzo sono stati sostituiti con un pulsante Test che mostra IP/latenza in linea.#### fix(translator): `function_call` prefix stripping\n\n- Risolto un problema incompleto dal PR #607 in cui solo i blocchi `tool_use` rimuovevano il prefisso dello strumento `proxy_` di Claude. Ora, i client che utilizzano il formato API OpenAI Responses riceveranno correttamente anche gli strumenti senza il prefisso \"proxy\\_\".---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nSono state risolte tre regressioni critiche segnalate dagli utenti dopo il lancio della versione 3.0.0.#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nIl prefisso `proxy_` aggiunto da Claude OAuth è stato rimosso solo dalle risposte**streaming**. In modalità**non streaming**, \"translateNonStreamingResponse\" non aveva accesso a \"toolNameMap\", facendo sì che i client ricevessero nomi di strumenti alterati come \"proxy_read_file\" invece di \"read_file\".\n\n**Correzione:**Aggiunto il parametro facoltativo `toolNameMap` a `translateNonStreamingResponse` e ​​applicata la rimozione del prefisso nel gestore del blocco Claude `tool_use`. `chatCore.ts` ora passa attraverso la mappa.#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI non espone `GET /v1/models`. Il validatore generico `validateOpenAICompatibleProvider` è passato a un fallback di completamento chat solo se era impostato `validationModelId`, cosa che LongCat non configura. Ciò ha causato il fallimento della convalida del provider con un errore fuorviante durante l'aggiunta/salvataggio.\n\n**Correzione:**Aggiunto `longcat` alla mappa dei validatori specializzati, esaminando direttamente `/chat/completions` e trattando qualsiasi risposta non di autenticazione come un passaggio.#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nGli strumenti MCP (ad esempio `pencil`, `computer_use`) inoltrano le definizioni degli strumenti con `{type:\"object\"}` ma senza un campo `properties`. L'API di Anthropic li rifiuta con: \"proprietà mancanti dello schema dell'oggetto\".\n\n**Correzione:**In `openai-to-claude.ts`, inserire `properties: {}` come impostazione predefinita sicura quando `type` è `\"object\"` e `properties` è assente.---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Autore | Sommario |\n| -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------- | --- |\n| **#589** | @flobo3 | docs(i18n): corretta la traduzione russa per Playground e Testbed |\n| **#591** | @rdself | correzione (ui): miglioramento del contrasto della modalità luce dei limiti del fornitore e della visualizzazione del livello del piano | --- |\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`---\n\n### 🧪 Tests\n\n-**926 test, 0 fallimenti**(invariato rispetto alla v3.0.0)---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **La più grande release di sempre.**Da 36 provider nella versione 2.9.5 a**67+ provider**nella versione 3.0.0 — con server MCP, protocollo A2A, motore di combinazione automatica, icone dei provider, API per chiavi registrate, 926 test e contributi di**12 membri della comunità**in**10 PR uniti**.\n>\n> Consolidato da v3.0.0-rc.1 a rc.17 (17 release candidate in 3 giorni di intenso sviluppo).---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Fornitore | Alias ​​ | Livello | Note |\n| ------------------------------ | -------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| **OpenCode Zen** | `opencode-zen` | Gratuito | 3 modelli tramite `opencode.ai/zen/v1` (PR #530 di @kang-heewon) |\n| **OpenCode Vai** | `opencode-go` | Pagato | 4 modelli tramite `opencode.ai/zen/go/v1` (PR #530 di @kang-heewon) |\n| **AI LongCat** | `lc` | Gratuito | 50 milioni di token/giorno (Flash-Lite) + 500.000/giorno (Chat/Thinking) durante la beta pubblica |\n| **Impollinazioni AI** | `pol` | Gratuito | Non è necessaria alcuna chiave API: GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 richiesta/15 secondi) |\n| **AI di Cloudflare Workers** | `cf` | Gratuito | 10.000 neuroni al giorno: ~150 risposte LLM o 500 Audio sussurrato, inferenza sui bordi |\n| **AI di Scaleway** | `scw` | Gratuito | 1 milione di token gratuiti per i nuovi account: conforme a UE/GDPR (Parigi) |\n| **API AI/ML** | `scopo` | Gratuito | Crediti gratuiti di $ 0,025 al giorno: oltre 200 modelli tramite singolo endpoint |\n| **IA del computer** | `pu` | Gratuito | Oltre 500 modelli (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Pagato | Endpoint internazionali + cinesi tramite `alicode`/`alicode-intl` |\n| **Piano di codifica Alibaba** | `bcp` | Pagato | Alibaba Model Studio con API compatibile con l'ambiente antropico |\n| **Codifica Kimi (chiave API)** | `kmca` | Pagato | Accesso Kimi dedicato basato su chiave API (separato da OAuth) |\n| **Codifica MiniMax** | `minimax` | Pagato | Endpoint internazionale |\n| **MiniMax (Cina)** | `minimax-cn` | Pagato | Endpoint specifico per la Cina |\n| **Z.AI (GLM-5)** | `zai` | Pagato | Modelli GLM di nuova generazione Zhipu AI |\n| **AI vertice** | `vertice` | Pagato | Google Cloud: account di servizio JSON o OAuth access_token |\n| **Ollama Nuvola** | `ollamacloud` | Pagato | Servizio API ospitato da Ollama |\n| **Sintetico** | `sintetico` | Pagato | Gateway modelli passthrough |\n| **Chilo Gateway** | `kg` | Pagato | Gateway modelli passthrough |\n| **Ricerca perplessità** | `pplx-ricerca` | Pagato | Endpoint dedicato basato sulla ricerca |\n| **Ricerca Serper** | `serper-search` | Pagato | Integrazione API di ricerca Web |\n| **Ricerca coraggiosa** | `ricerca coraggiosa` | Pagato | Integrazione API Brave Search |\n| **Ricerca Exa** | `exa-ricerca` | Pagato | Integrazione API di ricerca neurale |\n| **Ricerca Tavily** | `tavily-search` | Pagato | Integrazione API di ricerca AI |\n| **NanoBanana** | `nb` | Pagato | API per la generazione di immagini |\n| **UndiciLabs** | `el` | Pagato | Sintesi vocale da testo a voce |\n| **Cartesia** | `cartesia` | Pagato | Sintesi vocale TTS ultraveloce |\n| **RiproduciHT** | `gioca` | Pagato | Clonazione vocale e TTS |\n| **Nel mondo** | `nel mondo` | Pagato | Chat vocale del personaggio AI |\n| **UI WebSD** | `sdwebui` | Ospitato autonomamente | Generazione di immagini locali a diffusione stabile |\n| **ComodaUI** | `comfyui` | Ospitato autonomamente | Generazione basata su nodo del flusso di lavoro locale ComfyUI |\n| **Codifica GLM** | `glm` | Pagato | Endpoint specifico della codifica BigModel/Zhipu | **Totale: oltre 67 provider**(4 gratuiti, 8 OAuth, 55 chiavi API) + provider personalizzati illimitati OpenAI/compatibili con l'ambiente antropico.--- |\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nGenera automaticamente ed emetti chiavi API OmniRoute a livello di codice con l'applicazione delle quote per provider e per account.\n\n| Punto finale | Metodo | Descrizione |\n| -------------------------------- | ----------------- | ---------------------------------------------------------------------------- |\n| `/api/v1/chiavi-registrate` | \"POST\" | Emetti una nuova chiave: la chiave grezza viene restituita**solo una volta** |\n| `/api/v1/chiavi-registrate` | `OTTIENI` | Elenco chiavi registrate (mascherate) |\n| `/api/v1/chiave-registrata/{id}` | `OTTIENI/ELIMINA` | Ottieni metadati / Revoca |\n| `/api/v1/quote/check` | `OTTIENI` | Pre-convalidare la quota prima di emettere |\n| `/api/v1/providers/{id}/limits` | `OTTIENI/METTI` | Configurare i limiti di emissione per provider |\n| `/api/v1/accounts/{id}/limits` | `OTTIENI/METTI` | Configura i limiti di emissione per account |\n| `/api/v1/problemi/rapporto` | \"POST\" | Segnala eventi di quota a GitHub Problemi |\n\n**Sicurezza:**chiavi archiviate come hash SHA-256. Chiave grezza mostrata una volta al momento della creazione, mai più recuperabile.#### 🎨 Provider Icons via @lobehub/icons (#529)\n\nOltre 130 loghi di fornitori che utilizzano i componenti React \"@lobehub/icons\" (SVG). Catena di fallback:**Lobehub SVG → PNG esistente → icona generica**. Applicato alle pagine Dashboard, Provider e Agenti con il componente \"ProviderIcon\" standardizzato.#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAggiorna automaticamente gli elenchi dei modelli per i fornitori connessi ogni**24 ore**. Viene eseguito all'avvio del server. Configurabile tramite `MODEL_SYNC_INTERVAL_HOURS`.#### 🔀 Per-Model Combo Routing (#563)\n\nMappare i modelli di nome del modello (glob) su combinazioni specifiche per il routing automatico:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- Nuova tabella `model_combo_mappings` con corrispondenza glob-to-regex\n- Sezione dell'interfaccia utente del dashboard: \"Regole di routing del modello\" con aggiunta/modifica/attivazione/disattivazione/eliminazione in linea#### 🧭 API Endpoints Dashboard\n\nCatalogo interattivo, gestione webhook, visualizzatore OpenAPI: tutto in un'unica pagina a schede in `/dashboard/endpoint`.#### 🔍 Web Search Providers\n\n5 nuove integrazioni dei provider di ricerca:**Perplexity Search**,**Serper**,**Brave Search**,**Exa**,**Tavily**— consentendo risposte basate sull'intelligenza artificiale con dati web in tempo reale.#### 📊 Search Analytics\n\nNuova scheda in `/dashboard/analytics`: suddivisione dei fornitori, percentuale di riscontri nella cache, monitoraggio dei costi. API: \"GET /api/v1/search/analytics\".#### 🛡️ Per-API-Key Rate Limits (#452)\n\nColonne \"max_requests_per_day\" e \"max_requests_per_minute\" con applicazione della finestra scorrevole in memoria che restituisce HTTP 429.#### 🎵 Media Playground\n\nParco giochi completo per la generazione di media su `/dashboard/media`: generazione di immagini, video, musica, trascrizione audio (limite di caricamento di 2 GB) e sintesi vocale.---\n\n### 🔒 Security & CI/CD\n\n-**Rimedio CodeQL**— Risolti più di 10 avvisi: 6 ripetizioni polinomiali, 1 casualità non sicura (`Math.random()` → `crypto.randomUUID()`), 1 iniezione di comandi shell -**Convalida del percorso**— Schemi Zod + `validateBody()` su**percorsi API 176/176**— CI applicata -**Correzione CVE**: vulnerabilità dompurify XSS (GHSA-v2wj-7wpq-c8vv) risolta tramite override npm -**Appiattito**— Rimbalzato 3.3.3 → 3.4.2 (inquinamento del prototipo CWE-1321) -**Docker**— Aggiornato `docker/setup-buildx-action` v3 → v4---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n-**#537**— Gemini CLI OAuth: cancella l'errore risolvibile quando `GEMINI_OAUTH_CLIENT_SECRET` manca in Docker -**#549**— I percorsi delle impostazioni CLI ora risolvono la chiave API reale da `keyId` (stringhe non mascherate) -**#574**: l'accesso non si blocca più dopo aver saltato l'impostazione della password della procedura guidata -**#506**— `machineId` multipiattaforma riscritto (Windows REG.exe → macOS ioreg → Linux → nome host fallback)#### Providers & Routing\n\n-**#536**— LongCat AI: corretti `baseUrl` e `authHeader` -**#535**— Sostituzione del modello bloccato: `body.model` impostato correttamente su `pinnedModel` -**#570**— I modelli Claude senza prefisso ora si risolvono in provider antropico -**#585**— I tag interni `` non vengono più trasmessi ai client nello streaming SSE -**#493**: la denominazione del modello di provider personalizzato non è più alterata dalla rimozione del prefisso -**#490**— Streaming + protezione della cache di contesto tramite injection `TransformStream` -**#511**— Tag `` inserito nel primo blocco di contenuto (non dopo `[DONE]`)#### CLI & Tools\n\n-**#527**— Codice Claude + ciclo Codex: i blocchi `tool_result` ora sono convertiti in testo -**#524**: configurazione OpenCode salvata correttamente (formato XDG_CONFIG_HOME, TOML) -**#522**— Gestore API: rimosso il pulsante fuorviante \"Copia chiave mascherata\". -**#546**— `--version` restituisce `unknown` su Windows (PR di @k0valik) -**#544**: rilevamento sicuro dello strumento CLI tramite percorsi di installazione noti (PR di @k0valik) -**#510**: percorsi Windows MSYS2/Git-Bash normalizzati automaticamente -**#492**— La CLI rileva il nodo gestito da `mise`/`nvm` quando manca `app/server.js`#### Streaming & SSE\n\n-**PR #587**— Ripristina l'importazione di `resolveDataDir` nelle risposteCompatibile con Transformers per Cloudflare Workers (@k0valik) -**PR #495**— Collo di bottiglia 429 attesa infinita: elimina i lavori in attesa sul limite di velocità (@xandr0s) -**#483**— Interrompe il trascinamento di `data: null` dopo il segnale `[DONE]` -**#473**— Stream SSE Zombie: timeout ridotto a 300 → 120 secondi per un fallback più rapido#### Media & Transcription\n\n-**Trascrizione**— Deepgram `video/mp4` → `audio/mp4` Mappatura MIME, rilevamento automatico della lingua, punteggiatura -**TTS**— Visualizzazione dell'errore `[oggetto oggetto]` corretta per errori nidificati in stile ElevenLabs -**Upload limits**— Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n-**T01**: colonna \"requested_model\" nei registri delle chiamate (migrazione 009) -**T02**— Elimina i blocchi di testo vuoti dal `tool_result.content' nidificato\n-**T03**— Analizza le intestazioni di quota `x-codex-5h-_`/`x-codex-7d-_`-**T04**— Intestazione`X-Session-Id` per sticky routing esterno\n-**T05**: persistenza del DB con limite di velocità con API dedicata\n-**T06**— Account disattivato → blocco permanente (tempo di recupero di 1 anno)\n-**T07**— X-Forwarded-Per convalida IP (`extractClientIp()`) -**T08**— Per-API-key session limits with sliding-window enforcement -**T09**— Ambiti Codex vs Spark rate-limit (pool separati) -**T10**— Crediti esauriti → fallback distinto con tempo di recupero di 1 ora -**T11**— sforzo di ragionamento \"max\" → 131072 gettoni di budget -**T12**: voci di prezzo MiniMax M2.7 -**T13**— Correzione della visualizzazione delle quote obsolete (ripristino del riconoscimento della finestra) -**T14**: controllo TCP proxy fast-fail (≤2s, cache 30s) -**T15**: normalizzazione del contenuto dell'array per Anthropic -**T23**: fallback intelligente per la reimpostazione della quota (estrazione dell'intestazione) -**T24**— Tempo di recupero \"503\" + mappatura \"406\". -**T25**: fallback di convalida del provider -**T29**: autenticazione JWT dell'account del servizio Vertex AI -**T33**: livello di riflessione per conversione del budget -**T36**— Classificazione degli errori \"403\" e \"429\". -**T38**: specifiche del modello centralizzato (\"modelSpecs.ts\") -**T39**— Fallback dell'endpoint per \"fetchAvailableModels\". -**T41**: reindirizzamento automatico delle attività in background ai modelli Flash -**T42**: mappatura delle proporzioni di generazione dell'immagine#### Other Improvements\n\n-**Intestazioni personalizzate upstream per modello**— tramite interfaccia utente di configurazione (PR n. 575 di @zhangqiang8vip) -**Lunghezza del contesto del modello**: configurabile nei metadati del modello (PR #578 di @hijak) -**Rimozione del prefisso del modello**: opzione per rimuovere il prefisso del fornitore dai nomi dei modelli (PR n. 582 di @jay77721) -**Deprecazione della CLI Gemini**: contrassegnata come deprecata con avviso di restrizione OAuth di Google -**Paser YAML**: sostituito il parser personalizzato con `js-yaml` per la corretta analisi delle specifiche OpenAPI -**ZWS v5**— Correzione di perdite HMR (connessioni 485 DB → 1, memoria 2,4 GB → 195 MB) -**Esportazione log**: nuovo pulsante di esportazione JSON sulla dashboard con menu a discesa dell'intervallo di tempo -**Banner di notifica aggiornamento**: la home page del dashboard mostra quando sono disponibili nuove versioni---\n\n### 🌐 i18n & Documentation\n\n-**30 lingue**con parità al 100%: 2.788 chiavi mancanti sincronizzate -**Ceco**— Traduzione completa: 22 documenti, 2.606 stringhe UI (PR di @zen0bit) -**Cinese (zh-CN)**— Ritraduzione completa (PR di @only4copilot) -**Guida alla distribuzione delle VM**: tradotta in inglese come documento di origine -**API Reference**— Added `/v1/embeddings` and `/v1/audio/speech` endpoints -**Conteggio provider**: aggiornato da 36+/40+/44+ a**67+**nel README e in tutti i 30 README i18n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Autore | Sommario |\n| -------- | --------------- | -------------------------------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): ripristina l'importazione diresolveDataDir per la compatibilità Cloudflare Workers |\n| **#582** | @jay77721 | feat(proxy): opzione di eliminazione del prefisso del nome del modello |\n| **#581** | @jay77721 | fix(npm): collega il rilascio di elettroni al flusso di lavoro npm-publish |\n| **#578** | @hijak | feat: lunghezza del contesto configurabile nei metadati del modello |\n| **#575** | @zhangqiang8vip | caratteristica: intestazioni upstream per modello, PATCH compatibile, allineamento chat |\n| **#562** | @coobabm | correzione: gestione della sessione MCP, passthrough Claude, discoverFormat |\n| **#561** | @zen0bit | fix(i18n): correzioni di traduzione ceca |\n| **#555** | @k0valik | fix(sse): `resolveDataDir()` centralizzato per la risoluzione del percorso |\n| **#546** | @k0valik | fix(cli): `--version` restituisce `unknown` su Windows |\n| **#544** | @k0valik | fix(cli): rilevamento sicuro dello strumento CLI tramite percorsi di installazione |\n| **#542** | @rdself | fix(ui): variabili del tema CSS con contrasto in modalità luce |\n| **#530** | @kang-heewon | feat: provider OpenCode Zen + Go con `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: compatibilità del modello per protocollo (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | correzione: perdite di risorse HMR in modalità sviluppo (ZWS v5) |\n| **#495** | @xandr0s | correzione: collo di bottiglia 429 attesa infinita (eliminazione dei lavori in attesa) |\n| **#494** | @zhangqiang8vip | feat: sviluppatore MiniMax→correzione ruolo di sistema |\n| **#480** | @prakersh | correzione: estrazione dell'utilizzo dello svuotamento del flusso |\n| **#479** | @prakersh | feat: Codice 5.3/5.4 e voci sui prezzi antropici |\n| **#475** | @only4copilot | feat(i18n): migliorata la traduzione cinese |\n\n**Grazie a tutti i contributori!**🙏---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`---\n\n### 🧪 Tests\n\n-**926 test, 0 errori**(rispetto agli 821 della versione 2.9.5)\n\n- Oltre 105 nuovi test che coprono: mappature di combinazioni di modelli, chiavi registrate, OpencodeExecutor, provider Bailian, convalida del percorso, classificazione degli errori, mappatura delle proporzioni e altro ancora---\n\n### 📦 Database Migrations\n\n| Migrazione | Descrizione |\n| ---------- | ---------------------------------------------------------------------- | --- |\n| **008** | Tabelle `registered_keys`, `provider_key_limits`, `account_key_limits` |\n| **009** | Colonna \"requested_model\" in \"call_logs\" |\n| **010** | Tabella `model_combo_mappings` per il routing combinato per modello | --- |\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Modifiche importanti:**Nessuna. Tutte le configurazioni, le combinazioni e le chiavi API esistenti vengono conservate.\n> Le migrazioni del database 008-010 vengono eseguite automaticamente all'avvio.---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n-**Rimedio CodeQL**: risolti più di 10 avvisi:\n\n- 6 ripetizioni polinomiali in `provider.ts` / `chatCore.ts` (sostituiti i modelli di alternanza `(?:^|/)` con la corrispondenza basata sui segmenti)\n- 1 casualità insicura in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n- 1 iniezione di comandi shell in `prepublish.mjs` (escape del percorso `JSON.stringify()`) -**Convalida del percorso**— Aggiunti schemi Zod + `validateBody()` a 5 percorsi privi di convalida:\n- `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n- CI `check:route-validation:t06` ora passa:**176/176 rotte convalidate**### 🐛 Bug Fixes\n\n-**#585**— `` internal tags no longer leak to clients in SSE responses. Aggiunta la sanificazione in uscita \"TransformStream\" in \"combo.ts\".### ⚙️ Infrastructure\n\n-**Docker**: `docker/setup-buildx-action` aggiornato da v3 → v4 (correzione per la deprecazione di Node.js 20) -**Pulizia CI**: eliminate oltre 150 esecuzioni del flusso di lavoro non riuscite/annullate### 🧪 Tests\n\n- Suite di test:**926 test, 0 fallimenti**(+3 nuovi)---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Aumento dei limiti di trascrizione dei media\n- Aggiunta la lunghezza del contesto del modello ai metadati del registro\n- Aggiunte intestazioni personalizzate upstream per modello tramite l'interfaccia utente di configurazione\n- Risolti diversi bug, convalida Zod per le patch e risolti vari problemi della community.## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n-**#563**— Routing combinato per modello: mappa i modelli di nomi del modello (glob) su combo specifiche per il routing automatico\n\n- Nuova tabella `model_combo_mappings` (migrazione 010) con pattern, combo_id, priorità, abilitato\n- Funzione DB `resolveComboForModel()` con corrispondenza da glob a regex (senza distinzione tra maiuscole e minuscole, caratteri jolly `*` e `?`)\n- `getComboForModel()` in `model.ts`: aumenta `getCombo()` con il fallback del modello-modello\n- `chat.ts`: la decisione di routing ora controlla le mappature modello-combo prima della gestione del modello singolo\n- API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n- Dashboard: sezione \"Regole di routing del modello\" aggiunta alla pagina Combo con aggiunta/modifica/attivazione/disattivazione/eliminazione in linea\n- Esempi: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo### 🌐 i18n\n\n-**Sincronizzazione i18n completa**: 2.788 chiavi mancanti aggiunte su 30 file di lingua: tutte le lingue ora hanno una parità del 100% con `en.json` -**Pagina agenti i18n**: sezione Integrazione OpenCode completamente internazionalizzata (titolo, descrizione, scansione, etichette di download) -**6 nuove chiavi**aggiunte allo spazio dei nomi `agents` per la sezione OpenCode### 🎨 UI/UX\n\n-**Icone del provider**: aggiunte 16 icone del provider mancanti (3 copiate, 2 scaricate, 11 SVG create) -**SVG fallback**: componente `ProviderIcon` aggiornato con strategia a 4 livelli: Lobehub → PNG → SVG → Icona generica -**Fingerprinting degli agenti**: sincronizzato con gli strumenti CLI: aggiunti droid, openclaw, copilot, opencode all'elenco delle impronte digitali (14 in totale)### Sicurezza\n\n-**Correzione CVE**: risolta la vulnerabilità dompurify XSS (GHSA-v2wj-7wpq-c8vv) tramite npm esegue l'override forzando `dompurify@^3.3.2`\n\n- \"npm audit\" ora segnala**0 vulnerabilità**### 🧪 Tests\n\n- Suite di test:**923 test, 0 fallimenti**(+15 nuovi test di mappatura modello-combo)---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Autore | Sommario |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------ | ------------ |\n| **#562** | @coobabm | fix(ux): gestione delle sessioni MCP, normalizzazione passthrough Claude, modale OAuth, discoverFormat |\n| **#561** | @zen0bit | fix(i18n): correzioni della traduzione ceca: nomi dei metodi HTTP e aggiornamenti della documentazione | ### 🧪 Tests |\n\n- Suite di test:**908 test, 0 errori**---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n-**config:**risolve la chiave API reale da `keyId` nei percorsi delle impostazioni CLI (`codex-settings`, `droid-settings`, `kilo-settings`) per impedire la scrittura di stringhe mascherate (#549)---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Autore | Sommario |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |\n| **#546** | @k0valik | fix(cli): `--version` restituisce `unknown` su Windows — usa `JSON.parse(readFileSync)` invece dell'importazione ESM |\n| **#555** | @k0valik | fix(sse): `resolveDataDir()` centralizzato per la risoluzione del percorso in credenziali, autoCombo, registratore di risposte e registratore di richieste |\n| **#544** | @k0valik | fix(cli): rilevamento sicuro dello strumento CLI tramite percorsi di installazione noti (8 strumenti) con convalida del collegamento simbolico, controlli del tipo di file, limiti di dimensione, ambiente minimo nel controllo dello stato |\n| **#542** | @rdself | fix(ui): migliora il contrasto della modalità chiara — aggiungi variabili mancanti del tema CSS (`bg-primary`, `bg-subtle`, `text-primary`) e correggi i colori solo scuri nei dettagli del registro | ### 🔧 Bug Fixes |\n\n-**Correzione TDZ in `cliRuntime.ts`**— `validateEnvPath` veniva utilizzato prima dell'inizializzazione all'avvio del modulo da `getExpectedParentPaths()`. Dichiarazioni riordinate per correggere \"ReferenceError\". -**Correzioni alla build**— Aggiunti `pino` e `pino-pretty` a `serverExternalPackages` per impedire a Turbopack di interrompere il caricamento del lavoratore interno di Pino.### 🧪 Tests\n\n- Suite di test:**905 test, 0 fallimenti**---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n-**#509 / #508**— Regressione alla creazione di Electron: declassato Next.js da `16.1.x` a `16.0.10` per eliminare l'instabilità dell'hashing del modulo Turbopack che causava schermate vuote nel bundle desktop Electron. -**Correzioni per i test unitari**— Corrette due asserzioni di test obsolete (proporzioni/risoluzione di `nanobanana-image-handler`, mappatura dei campi `thinking-budget` Gemini `thinkingConfig`) che erano andate alla deriva dopo le recenti modifiche all'implementazione. -**#541**: risposta al feedback degli utenti sulla complessità dell'installazione; non sono necessarie modifiche al codice.---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n-**T29**— Esecutore Vertex AI SA JSON: implementato utilizzando la libreria `jose` per gestire l'autenticazione JWT/account di servizio, insieme ad aree configurabili nell'interfaccia utente e alla creazione automatica dell'URL del modello partner. -**T42**— Mappatura delle proporzioni di generazione delle immagini: creata la logica \"sizeMapper\" per formati OpenAI generici (\"size\"), aggiunta la gestione nativa di \"imagen3\" e aggiornati gli endpoint NanoBanana per utilizzare automaticamente le proporzioni mappate. -**T38**— Specifiche del modello centralizzato: \"modelSpecs.ts\" creato per limiti e parametri per modello.### 🔧 Improvements\n\n-**T40**: integrazione degli strumenti CLI di OpenCode: integrazione nativa di \"opencode-zen\" e \"opencode-go\" completata nel precedente PR.---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n-**T24**— Correzione attesa ricarica \"503\" + mappatura \"406\": mappata \"406 Non accettabile\" su \"503 Servizio non disponibile\" con intervalli di ricarica adeguati. -**T25**— Fallback di convalida del provider: fallback corretto ai modelli di convalida standard quando uno specifico `validationModelId` non è presente. -**T36**— Perfezionamento della gestione del provider \"403\" vs \"429\": estratto in \"errorClassifier.ts\" per separare correttamente gli errori relativi alle autorizzazioni hardware (`403`) dai limiti di velocità (`429`). -**T39**— Fallback endpoint per `fetchAvailableModels`: implementato un meccanismo a tre livelli (`/models` -> `/v1/models` -> catalogo generico locale) + aggiornamenti dello strumento MCP `list_models_catalog` per riflettere `source` e `warning`. -**T33**— Conversione dal livello di riflessione al budget: traduce i livelli di riflessione qualitativa in allocazioni di budget precise. -**T41**: reindirizzamento automatico delle attività in background: indirizza automaticamente attività di valutazione in background pesanti a modelli flash/efficienti. -**T23**— Fallback intelligente per il ripristino della quota: estrae con precisione i valori dell'intestazione \"x-ratelimit-reset\" / \"retry-after\" o mappa i tempi di recupero statici.---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Aggiornamento dalla versione 2.9.5:**16 problemi risolti · 2 PR della community uniti · 2 nuovi fornitori · 7 nuovi endpoint API · 3 nuove funzionalità · Migrazione DB 008+009 · 832 test superati · 15 miglioramenti del gap sub2api (T01–T15 completo).### 🆕 New Providers\n\n| Fornitore | Alias ​​ | Livello | Note |\n| ---------------- | -------------- | -------- | ------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Gratuito | 3 modelli tramite `opencode.ai/zen/v1` (PR #530 di @kang-heewon) |\n| **OpenCode Vai** | `opencode-go` | Pagato | 4 modelli tramite `opencode.ai/zen/go/v1` (PR #530 di @kang-heewon) |\n\nEntrambi i provider utilizzano il nuovo `OpencodeExecutor` con routing multiformato (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nGenera automaticamente ed emetti chiavi API OmniRoute a livello di codice con l'applicazione delle quote per provider e per account.\n\n| Punto finale | Metodo | Descrizione |\n| ------------------------------------- | --------------- | ---------------------------------------------------------------------------- |\n| `/api/v1/chiavi-registrate` | \"POST\" | Emetti una nuova chiave: la chiave grezza viene restituita**solo una volta** |\n| `/api/v1/chiavi-registrate` | `OTTIENI` | Elenco chiavi registrate (mascherate) |\n| `/api/v1/chiave-registrata/{id}` | `OTTIENI` | Ottieni metadati chiave |\n| `/api/v1/chiave-registrata/{id}` | \"ELIMINA\" | Revoca una chiave |\n| `/api/v1/registered-keys/{id}/revoke` | \"POST\" | Revoca (per client senza supporto DELETE) |\n| `/api/v1/quote/check` | `OTTIENI` | Pre-convalidare la quota prima di emettere |\n| `/api/v1/providers/{id}/limits` | `OTTIENI/METTI` | Configurare i limiti di emissione per provider |\n| `/api/v1/accounts/{id}/limits` | `OTTIENI/METTI` | Configura i limiti di emissione per account |\n| `/api/v1/problemi/rapporto` | \"POST\" | Segnala eventi di quota a GitHub Problemi |\n\n**DB — Migrazione 008:**Tre nuove tabelle: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Sicurezza:**chiavi archiviate come hash SHA-256. Chiave grezza mostrata una volta al momento della creazione, mai più recuperabile.\n**Tipi di quota:**`maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider e per account.\n**Idempotency:**il campo `idempotency_key` impedisce l'emissione duplicata. Restituisce \"409 IDEMPOTENCY_CONFLICT\" se la chiave era già utilizzata.\n**Budget per chiave:**`dailyBudget` / `hourlyBudget`: limita il numero di richieste che una chiave può instradare per finestra.\n**Report GitHub:**facoltativo. Imposta `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` per creare automaticamente problemi GitHub in caso di superamento della quota o di errori di emissione.#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nTutte le icone dei provider nella dashboard ora utilizzano i componenti React `@lobehub/icons` (oltre 130 provider con SVG).\nCatena di fallback:**Lobehub SVG → esistente `/providers/{id}.png` → icona generica**. Utilizza un pattern React `ErrorBoundary` corretto.#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute ora aggiorna automaticamente gli elenchi di modelli per i fornitori connessi ogni**24 ore**.\n\n- Viene eseguito all'avvio del server tramite l'hook `/api/sync/initialize` esistente\n- Configurabile tramite la variabile di ambiente `MODEL_SYNC_INTERVAL_HOURS`\n- Copre 16 principali fornitori\n- Registra l'ora dell'ultima sincronizzazione nel database delle impostazioni---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n-**#537 — Gemini CLI OAuth:**Cancella l'errore che richiede azione quando `GEMINI_OAUTH_CLIENT_SECRET` manca nelle distribuzioni Docker/self-hosted. In precedenza è stato mostrato il criptico \"client_secret mancante\" da Google. Ora fornisce istruzioni specifiche per `docker-compose.yml` e `~/.omniroute/.env`.#### Providers & Routing\n\n-**#536 — LongCat AI:**Corretti `baseUrl` (`api.longcat.chat/openai`) e `authHeader` (\"Autorizzazione: Bearer`).\n-**#535 — Sostituzione del modello bloccato:**`body.model`ora è impostato correttamente su`pinnedModel`quando la protezione della cache di contesto è attiva.\n-**#532 — Convalida della chiave OpenCode Go:**ora utilizza l'endpoint di test`zen/v1` (`testKeyBaseUrl`) — la stessa chiave funziona per entrambi i livelli.#### CLI & Tools\n\n-**#527 — Codice Claude + Ciclo Codex:**i blocchi `tool_result` ora vengono convertiti in testo invece che eliminati, interrompendo infiniti cicli di risultati strumento. -**#524 — Salvataggio della configurazione OpenCode:**Aggiunto il gestore `saveOpenCodeConfig()` (consapevole di XDG_CONFIG_HOME, scrive TOML). -**#521 — Accesso bloccato:**L'accesso non si blocca più dopo aver saltato l'impostazione della password: reindirizza correttamente all'onboarding. -**#522 — Gestore API:**Rimosso il pulsante fuorviante \"Copia chiave mascherata\" (sostituito con la descrizione comando dell'icona di un lucchetto). -**#532 — Configurazione OpenCode Go:**Il gestore delle impostazioni della guida ora gestisce il toolId `opencode`.#### Developer Experience\n\n-**#489 — Antigravità:**`googleProjectId` mancante restituisce un errore strutturato 422 con guida alla riconnessione invece di un arresto anomalo criptico. -**#510 — Percorsi Windows:**I percorsi MSYS2/Git-Bash (`/c/Program Files/...`) vengono ora normalizzati automaticamente in `C:\\Program Files\\...`. -**#492 — Avvio della CLI:**La CLI di `omniroute` ora rileva il nodo gestito da `mise`/`nvm` quando manca `app/server.js` e mostra istruzioni di correzione mirate.---\n\n### 📖 Documentation Updates\n\n-**#513**— Reimpostazione della password Docker: `INITIAL_PASSWORD` env var soluzione alternativa documentata -**#520**— pnpm: passaggio `pnpm approve-builds better-sqlite3` documentato---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`---\n\n### 🔀 Community PRs Merged\n\n| PR | Autore | Sommario |\n| -------- | ------------ | ------------------------------------------------------------------- | --- |\n| **#530** | @kang-heewon | Provider OpenCode Zen + Go con `OpencodeExecutor` e test migliorati | --- |\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n-**T05**— Persistenza del DB con limite di velocità: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `provviders.ts`. La colonna esistente \"rate_limited_until\" è ora esposta come API dedicata: l'aggiornamento del token OAuth NON deve toccare questo campo per evitare loop di limiti di velocità. -**T08**— Limite sessione per chiave API: \"max_sessions INTEGER DEFAULT 0\" aggiunto ad \"api_keys\" tramite migrazione automatica. `sessionManager.ts` ottiene `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()` e `getActiveSessionCountForKey()`. I chiamanti in \"chatCore.js\" possono applicare il limite e diminuirlo su \"req.close\". -**T09**— Ambiti del limite di velocità Codex vs Spark: `getCodexModelScope()` e `getCodexRateLimitKey()` in `codex.ts`. I modelli standard (`gpt-5.x-codex`, `codex-mini`) ottengono l'ambito `\"codex\"`; i modelli spark (`codex-spark*`) ottengono l'ambito \"spark\"`. Le chiavi del limite di velocità dovrebbero essere `${accountId}:${scope}`in modo che l'esaurimento di un pool non blocchi l'altro.\n-**T13**— Correzione della visualizzazione delle quote obsolete:`getEffectiveQuotaUsage(used, resetAt)`restituisce`0`una volta superata la finestra di ripristino;`formatResetCountdown(resetAt)`restituisce una stringa di conto alla rovescia leggibile dall'uomo (ad esempio`\"2h 35m\"`). Entrambi esportati da `provviders.ts`+`localDb.ts`per l'utilizzo del dashboard.\n-**T14**— Proxy fast-fail: nuovo`src/lib/proxyHealth.ts`con`isProxyReachable(proxyUrl, timeoutMs=2000)`(controllo TCP, timeout ≤2s invece di 30s),`getCachedProxyHealth()`, `invalidateProxyHealth()`e`getAllProxyHealthStatuses()`. I risultati vengono memorizzati nella cache per 30 secondi per impostazione predefinita; configurabile tramite `PROXY_FAST_FAIL_TIMEOUT_MS`/`PROXY_HEALTH_CACHE_TTL_MS`.### 🧪 Tests\n\n- Suite di test:**832 test, 0 errori**---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n-**T01**— Colonna \"requested_model\" in \"call_logs\" (migrazione 009): traccia il modello originariamente richiesto dal client rispetto al modello effettivamente instradato. Abilita l'analisi del tasso di fallback. -**T02**— Elimina i blocchi di testo vuoti dal `tool_result.content` nidificato: previene gli errori Anthropic 400 (\"i blocchi di contenuto testuale devono essere non vuoti\") quando Claude Code concatena i risultati dello strumento. -**T03**— Analizza le intestazioni `x-codex-5h-*` / `x-codex-7d-*`: `parseCodexQuotaHeaders()` + `getCodexResetTime()` estrae le finestre delle quote Codex per una pianificazione precisa del cooldown invece del generico fallback di 5 minuti. -**T04**— Intestazione `X-Session-Id` per sticky routing esterno: `extractExternalSessionId()` in `sessionManager.ts` legge le intestazioni `x-session-id` / `x-omniroute-session` con il prefisso `ext:` per evitare collisioni con gli ID di sessione SHA-256 interni. Compatibile con Nginx (intestazione con trattino). -**T06**— Account disattivato → blocco permanente: `isAccountDeactivated()` in `accountFallback.ts` rileva 401 segnali di disattivazione e applica un tempo di recupero di 1 anno per impedire di riprovare con account definitivamente morti. -**T07**— Convalida IP X-Forwarded-For: nuovo `src/lib/ipUtils.ts` con `extractClientIp()` e `getClientIpFromRequest()` — salta le voci `sconosciute`/non IP nelle catene `X-Forwarded-For` (richieste inoltrate da Nginx/proxy). -**T10**— Crediti esauriti → fallback distinto: `isCreditsExhausted()` in `accountFallback.ts` restituisce 1 ora di recupero con il flag `creditsExhausted`, distinto dal limite di velocità generico 429. -**T11**— sforzo di ragionamento `max` → 131072 token di budget: `EFFORT_BUDGETS` e `THINKING_LEVEL_MAP` aggiornati; la mappatura inversa ora restituisce \"max\" per le risposte a budget completo. Test unitario aggiornato. -**T12**— Aggiunte voci di prezzo MiniMax M2.7: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` aggiunte alla tabella dei prezzi (sub2api PR #1120). I prezzi M2.5/GLM-4.7/GLM-5/Kimi esistevano già. -**T15**— Normalizzazione del contenuto dell'array: l'helper `normalizeContentToString()` in `openai-to-claude.ts` comprime correttamente i messaggi di sistema/strumento formattati come array in una stringa prima di inviarli ad Anthropic.### 🧪 Tests\n\n- Suite di test:**832 test, 0 fallimenti**(invariato rispetto a rc.5)---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n-**#464**: API di provisioning delle chiavi registrate: chiavi API emesse automaticamente con applicazione della quota per provider e per account\n\n- `POST /api/v1/registered-keys`: rilascia chiavi con supporto per idempotenza\n- `GET /api/v1/registered-keys` — elenca le chiavi registrate (mascherate).\n- `GET /api/v1/registered-keys/{id}`: ottieni i metadati della chiave\n- `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoca le chiavi\n- `GET /api/v1/quotas/check`: preconvalida prima dell'emissione\n- `PUT /api/v1/providers/{id}/limits`: imposta i limiti di emissione del provider\n- `PUT /api/v1/accounts/{id}/limits`: imposta i limiti di emissione dell'account\n- `POST /api/v1/issues/report`: segnalazione facoltativa dei problemi di GitHub\n- Migrazione DB 008: tabelle `registered_keys`, `provider_key_limits`, `account_key_limits`---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n-**#530 (PR)**: aggiunti i provider OpenCode Zen e OpenCode Go (di @kang-heewon)\n\n- Nuovo `OpencodeExecutor` con routing multiformato (`/chat/completions`, `/messages`, `/responses`)\n- 7 modelli su entrambi i livelli---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n-**#529**— Le icone dei provider ora utilizzano [@lobehub/icons](https://github.com/lobehub/lobe-icons) con un grazioso fallback PNG e un componente `ProviderIcon` (oltre 130 provider supportati) -**#488**— Aggiorna automaticamente gli elenchi dei modelli ogni 24 ore tramite `modelSyncScheduler` (configurabile tramite `MODEL_SYNC_INTERVAL_HOURS`)### 🔧 Bug Fixes\n\n-**#537**— Gemini CLI OAuth: ora mostra un chiaro errore eseguibile quando `GEMINI_OAUTH_CLIENT_SECRET` manca nelle distribuzioni Docker/self-hosted---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n-**#536**— Convalida della chiave AI LongCat: baseUrl fissa (`api.longcat.chat/openai`) e authHeader (`Autorizzazione: Bearer`) -**#535**— Override del modello bloccato: `body.model` è ora impostato su `pinnedModel` quando la protezione della cache di contesto rileva un modello bloccato -**#524**— La configurazione OpenCode ora viene salvata correttamente: aggiunto il gestore `saveOpenCodeConfig()` (XDG_CONFIG_HOME consapevole, scrive TOML)---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n-**#521**: l'accesso non si blocca più dopo aver saltato l'impostazione della password (reindirizza all'onboarding) -**#522**— Gestore API: rimosso il pulsante fuorviante \"Copia chiave mascherata\" (sostituito con la descrizione comando dell'icona del lucchetto) -**#527**— Ciclo dei superpoteri Claude Code + Codex: i blocchi `tool_result` ora sono convertiti in testo invece che eliminati -**#532**— La convalida della chiave API OpenCode GO ora utilizza l'endpoint `zen/v1` corretto (`testKeyBaseUrl`) -**#489**— Antigravità: `googleProjectId` mancante restituisce un errore strutturato 422 con guida alla riconnessione -**#510**— Windows: i percorsi MSYS2/Git-Bash (`/c/Program Files/...`) sono ora normalizzati in `C:\\Program Files\\...` -**#492**— La CLI di `omniroute` ora rileva `mise`/`nvm` quando manca `app/server.js` e mostra la correzione mirata### Documentazione\n\n-**#513**— Reimpostazione della password Docker: `INITIAL_PASSWORD` env var soluzione alternativa documentata -**#520**— pnpm: `pnpm approve-builds better-sqlite3` documented### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: nuovi provider OpenCode, correzione delle credenziali di incorporamento, bug della chiave mascherata CLI, correzione CACHE_TAG_PATTERN.### 🐛 Bug Fixes\n\n-**Gli strumenti CLI salvano la chiave API mascherata nei file di configurazione**— I percorsi POST di `claude-settings`, `cline-settings` e `openclaw-settings` ora accettano un parametro `keyId` e risolvono la chiave API reale dal DB prima di scrivere sul disco. `ClaudeToolCard` aggiornato per inviare `keyId` invece della stringa di visualizzazione mascherata. Correzioni #523, #526. -**Provider di incorporamento personalizzati: errore `Nessuna credenziale`**— `/v1/embeddings` ora tiene traccia di `credentialsProviderId` separatamente dal prefisso di routing, quindi le credenziali vengono recuperate dall'ID del nodo del provider corrispondente anziché dalla stringa del prefisso pubblico. Risolve una regressione in cui `google/gemini-embedding-001` e modelli simili di provider personalizzati fallivano sempre con un errore di credenziali. Correzioni relative al #532. (PR n. 528 di @jacob2826) -**L'espressione regolare di protezione della cache del contesto non riesce a `\n` prefisso**— `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` aggiornato per corrispondere a entrambi i valori letterali `\n` (barra rovesciata-n) e il ritorno a capo effettivo U+000A che lo streaming `combo.ts` inserisce attorno al tag `` dopo la correzione #515. Correzioni #531.### ✨ New Providers\n\n-**OpenCode Zen**— Gateway di livello gratuito su `opencode.ai/zen/v1` con 3 modelli: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano` -**OpenCode Go**— Servizio in abbonamento su `opencode.ai/zen/go/v1` con 4 modelli: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (formato Claude), `minimax-m2.5` (formato Claude)\n\n- Entrambi i provider utilizzano il nuovo `OpencodeExecutor` che instrada dinamicamente a `/chat/completions`, `/messages`, `/responses` o `/models/{model}:generateContent` in base al modello richiesto. (PR n. 530 di @kang-heewon)---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: correzioni di bug: preserva la chiave della cache del prompt del Codex, correggi l'escape JSON del tagContent, sincronizza lo stato del token scaduto nel DB.### 🐛 Bug Fixes\n\n-**fix(translator)**: preserva `prompt_cache_key` nell'API di risposta → traduzione dei completamenti chat (#517)\n— Il campo è un segnale di affinità cache utilizzato dal Codex; eliminandolo si impedivano i riscontri rapidi della cache.\nRisolto il problema con \"openai-responses.ts\" e \"responsesApiHelper.ts\".\n\n-**correzione(combo)**: Escape `\n` in `tagContent` quindi la stringa JSON inserita è valida (#515)\n— Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\nSostituito con `\\n` sequenze letterali in `open-sse/services/combo.ts`.\n\n-**correzione (utilizzo)**: sincronizza lo stato del token scaduto nel DB in caso di errore di autenticazione in tempo reale (#491)\n— Quando il controllo in tempo reale di Limiti e quote restituisce 401/403, la connessione \"testStatus\" viene ora aggiornata\nsu \"scaduto\" nel database in modo che la pagina Provider rifletta lo stesso stato degradato.\nRisolto il problema in \"src/app/api/usage/[connectionId]/route.ts\".---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: aggiungi 5 nuovi provider AI gratuiti: LongCat, Pollinations, Cloudflare AI, Scaleway, API AI/ML.### ✨ New Providers\n\n-**feat(providers/longcat)**: aggiunta LongCat AI (`lc/`) — 50 milioni di token al giorno gratuiti (Flash-Lite) + 500.000 al giorno (Chat/Thinking) durante la beta pubblica. Compatibile con OpenAI, autenticazione al portatore standard. -**feat(providers/pollinations)**: aggiunta di Pollinations AI (`pol/`) — non è richiesta alcuna chiave API. Proxy GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 richiesta/15 secondi gratis). L'esecutore personalizzato gestisce l'autenticazione opzionale. -**feat(providers/cloudflare-ai)**: aggiungi Cloudflare Workers AI (`cf/`) — 10.000 neuroni al giorno gratuiti (~150 risposte LLM o 500 audio Whisper). Oltre 50 modelli all'avanguardia a livello globale. L'esecutore personalizzato crea un URL dinamico con \"accountId\" dalle credenziali. -**feat(providers/scaleway)**: aggiungi le API generative Scaleway (`scw/`) — 1 milione di token gratuiti per i nuovi account. Conforme all'UE/GDPR (Parigi). Qwen3 235B, Lama 3.1 70B, Maestrale Piccolo 3.2. -**feat(providers/aimlapi)**: aggiunta API AI/ML (`aiml/`): credito gratuito di $ 0,025 al giorno, oltre 200 modelli (GPT-4o, Claude, Gemini, Llama) tramite un singolo endpoint aggregatore.### 🔄 Provider Updates\n\n-**feat(providers/together)**: aggiunto `hasFree: true` + 3 ID modello permanentemente gratuiti: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free` -**feat(providers/gemini)**: aggiunto `hasFree: true` + `freeNote` (1.500 req/giorno, non è necessaria la carta di credito, aistudio.google.com) -**chore(providers/gemini)**: rinomina il nome visualizzato in \"Gemini (Google AI Studio)\" per maggiore chiarezza### ⚙️ Infrastructure\n\n-**feat(executors/pollinations)**: Nuovo `PollinationsExecutor` — omette l'intestazione `Authorization` quando non viene fornita alcuna chiave API -**feat(executors/cloudflare-ai)**: nuovo `CloudflareAIExecutor`: la costruzione di URL dinamici richiede `accountId` nelle credenziali del provider -**feat(esecutori)**: registra le mappature degli esecutori `pollinations`, `pol`, `cloudflare-ai`, `cf`### Documentazione\n\n-**docs(readme)**: stack combinato gratuito espanso a 11 provider ($ 0 per sempre) -**docs(readme)**: aggiunte 4 nuove sezioni gratuite del provider (LongCat, Pollinations, Cloudflare AI, Scaleway) con tabelle modello -**docs(readme)**: tabella dei prezzi aggiornata con 4 nuove righe del livello gratuito -**docs(i18n/pt-BR)**: tabella dei prezzi aggiornata + aggiunte sezioni LongCat/Pollinations/Cloudflare AI/Scaleway in portoghese -**docs(new-features/ai)**: 10 file di specifiche delle attività + piano di implementazione principale in `docs/new-features/ai/`### 🧪 Tests\n\n- Suite di test:**821 test, 0 fallimenti**(invariato)---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: corretta la trascrizione multimediale (Deepgram/HuggingFace Content-Type, rilevamento della lingua) e la visualizzazione degli errori TTS.### 🐛 Bug Fixes\n\n-**correzione (trascrizione)**: la trascrizione audio di Deepgram e HuggingFace ora mappa correttamente `video/mp4` → `audio/mp4` e altri tipi MIME multimediali tramite il nuovo helper `resolveAudioContentType()`. In precedenza, il caricamento di file \".mp4\" restituiva costantemente \"Nessun parlato rilevato\" perché Deepgram riceveva \"Tipo di contenuto: video/mp4\". -**fix(trascrizione)**: aggiunto `detect_lingual=true` alle richieste Deepgram: rileva automaticamente la lingua audio (portoghese, spagnolo, ecc.) anziché l'inglese per impostazione predefinita. Corregge le trascrizioni non inglesi che restituiscono risultati vuoti o spazzatura. -**fix(trascrizione)**: aggiunto `punctuate=true` alle richieste di Deepgram per output di trascrizione di qualità superiore con punteggiatura corretta. -**fix(tts)**: visualizzazione dell'errore `[object Object]` nelle risposte di sintesi vocale corretta sia in `audioSpeech.ts` che in `audioTranscription.ts`. La funzione `upstreamErrorResponse()` ora estrae correttamente i messaggi di stringa nidificati da provider come ElevenLabs che restituiscono `{ error: { message: \"...\", status_code: 401 } }` invece di una stringa di errore semplice.### 🧪 Tests\n\n- Suite di test:**821 test, 0 fallimenti**(invariato)### Triaged Issues\n\n-**#508**— Regressione del formato della chiamata dello strumento: log proxy richiesti e informazioni sulla catena del provider (\"info sui bisogni\") -**#510**— Percorso del controllo di integrità della CLI di Windows: informazioni sulla versione della shell/nodo richieste (`needs-info`) -**#485**: chiamate dello strumento Kiro MCP: chiuse come problema Kiro esterno (non OmniRoute) -**#442**— Endpoint Baseten /models: chiuso (soluzione manuale documentata) -**#464**— API di provisioning delle chiavi: riconosciuta come elemento della roadmap---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: correzione della perdita di dati SSE omniModel, unione della compatibilità del modello per protocollo.### Bug Fixes\n\n-**#511**— Critico: il tag `` è stato inviato dopo `finish_reason:stop` nei flussi SSE, causando la perdita di dati. Il tag viene ora inserito nel primo blocco di contenuto non vuoto, garantendo la consegna prima che gli SDK chiudano la connessione.### Merged PRs\n\n-**PR #512**(@zhangqiang8vip): compatibilità del modello per protocollo: `normalizeToolCallId` e `preserveOpenAIDeveloperRole` possono ora essere configurati per protocollo client (OpenAI, Claude, Responses API). Nuovo campo `compatByProtocol` nella configurazione del modello con convalida Zod.### Triaged Issues\n\n-**#510**— Controllo integrità CLI di Windows_failed: informazioni su PATH/versione richieste -**#509**— Regressione Turbopack Electron: bug Next.js upstream, soluzioni alternative documentate -**#508**— Schermata nera di macOS: soluzione alternativa suggerita `--disable-gpu`---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: correzione machineId multipiattaforma, limiti di velocità per chiave API, cache del contesto di streaming, Alibaba DashScope, analisi di ricerca, ZWS v5 e 8 problemi chiusi.### ✨ New Features\n\n-**feat(search)**: scheda Analisi delle ricerche in `/dashboard/analytics`: suddivisione dei fornitori, percentuale di riscontri nella cache, monitoraggio dei costi. Nuova API: `GET /api/v1/search/analytics` (#feat/search-provider-routing) -**feat(provider)**: Alibaba Cloud DashScope aggiunto con convalida del percorso endpoint personalizzato: `chatPath` e `modelsPath` configurabili per nodo (#feat/custom-endpoint-paths) -**feat(api)**: limiti di conteggio delle richieste per chiave API: colonne \"max_requests_per_day\" e \"max_requests_per_minute\" con applicazione della finestra scorrevole in memoria che restituisce HTTP 429 (#452) -**feat(dev)**: ZWS v5 — Correzione di perdite HMR (connessioni 485 DB → 1), memoria 2,4 GB → 195 MB, singleton `globalThis`, correzione avviso Edge Runtime (@zhangqiang8vip)### 🐛 Bug Fixes\n\n-**correzione(#506)**: `machineId` multipiattaforma — `getMachineIdRaw()` riscritto con try/catch Waterfall (Windows REG.exe → macOS ioreg → Lettura file Linux → nome host → `os.hostname()`). Elimina la ramificazione di `process.platform` eliminata dal codice morto del bundler Next.js, correggendo il problema con `'head' non riconosciuto` su Windows. Corregge anche il problema #466. -**correzione(#493)**: denominazione personalizzata del modello del provider: rimossa l'eliminazione errata del prefisso in `DefaultExecutor.transformRequest()` che alterava gli ID dei modelli con ambito org come `zai-org/GLM-5-FP8`. -**correzione(#490)**: Streaming + protezione della cache di contesto — `TransformStream` intercetta SSE per inserire il tag `` prima del marcatore `[DONE]`, abilitando la protezione della cache di contesto per le risposte in streaming. -**correzione(#458)**: convalida dello schema combinato: i campi `system_message`, `tool_filter_regex`, `context_cache_protection` ora superano la convalida Zod al salvataggio. -**correzione(#487)**: pulizia della scheda KIRO MITM: rimosso ZWS_README, generato `AntigravityToolCard` per utilizzare i metadati dello strumento dinamico.### 🧪 Tests\n\n- Aggiunti test unitari di filtraggio degli strumenti in formato antropico (PR #397) — 8 test di regressione per `tool.name` senza wrapper `.function`\n- Suite di test:**821 test, 0 errori**(rispetto a 813)### 📋 Issues Closed (8)\n\n-**#506**— ID macchina Windows `head` non riconosciuto (risolto) -**#493**: denominazione personalizzata del modello del provider (risolto) -**#490**— Cache del contesto di streaming (risolto) -**#452**: limiti di richiesta per chiave API (implementati) -**#466**: errore di accesso a Windows (stessa causa principale di #506) -**#504**— MITM inattivo (comportamento previsto) -**#462**— Gemini CLI PSA (risolto) -**#434**— Arresto anomalo dell'app Electron (duplicato di #402)## [2.8.9] — 2026-03-20\n\n> Sprint: unisci i PR della comunità, correggi la scheda KIRO MITM, aggiornamenti delle dipendenze.### Merged PRs\n\n-**PR #498**(@Sajid11194): risolto il crash dell'ID macchina Windows (`unfine\\REG.exe`). Sostituisce `node-machine-id` con le query del registro del sistema operativo nativo.**Chiude #486.** -**PR #497**(@zhangqiang8vip): corrette le perdite di risorse HMR in modalità sviluppatore: 485 connessioni DB trapelate → 1, memoria 2,4 GB → 195 MB. Singleton \"globalThis\", correzione degli avvisi di Edge Runtime, stabilità del test di Windows. (+1168/-338 su 22 file) -**PR n. 499-503**(Dependabot): aggiornamenti di GitHub Actions: `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.### Bug Fixes\n\n-**#505**— La scheda KIRO MITM ora mostra istruzioni specifiche per lo strumento (`api.anthropic.com`) invece del testo specifico per Antigravity. -**#504**: risposta con chiarimenti sull'UX (MITM \"Inattivo\" è il comportamento previsto quando il proxy non è in esecuzione).---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: risolto il crash del test batch OAuth, aggiunto il pulsante \"Test All\" alle pagine dei singoli provider.### Bug Fixes\n\n-**Arresto anomalo del test batch OAuth**(ERR_CONNECTION_REFUSED): sostituito il ciclo for sequenziale con un limite di concorrenza di 5 connessioni + timeout di 30 secondi per connessione tramite `Promise.race()` + `Promise.allSettled()`. Previene l'arresto anomalo del server durante il test di gruppi di provider OAuth di grandi dimensioni (~30+ connessioni).### Funzionalità\n\n-**Pulsante \"Prova tutto\" sulle pagine dei provider**: le pagine dei singoli fornitori (ad esempio, `/providers/codex`) ora mostrano un pulsante \"Prova tutto\" nell'intestazione Connessioni quando sono presenti più di 2 connessioni. Utilizza `POST /api/providers/test-batch` con `{mode: \"provider\", providerId}`. Risultati visualizzati in modalità modale con riepilogo pass/fail e diagnosi per connessione.---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: unione PR #495 (drop collo di bottiglia 429), correzione #496 (fornitori di incorporamento personalizzato), funzionalità di triage.### Bug Fixes\n\n-**Collo di bottiglia 429 attesa infinita**(PR #495 di @xandr0s): su 429, `limiter.stop({ dropWaitingJobs: true })` fallisce immediatamente tutte le richieste in coda in modo che i chiamanti upstream possano attivare il fallback. Il limitatore viene eliminato dalla mappa, quindi la richiesta successiva crea una nuova istanza. -**Modelli di incorporamento personalizzati irrisolvibili**(#496): `POST /v1/embeddings` ora risolve i modelli di incorporamento personalizzati da TUTTI i provider_nodes (non solo localhost). Abilita modelli come \"google/gemini-embedding-001\" aggiunti tramite dashboard.### Issues Responded\n\n-**#452**: limiti di conteggio delle richieste per chiave API (riconosciuti, sulla roadmap) -**#464**: chiavi API emesse automaticamente con limiti di provider/account (sono necessari maggiori dettagli) -**#488**: aggiornamento automatico degli elenchi dei modelli (riconosciuto, sulla roadmap) -**#496**: risoluzione del provider di incorporamento personalizzato (risolto)---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: unione PR #494 (correzione ruolo MiniMax), correzione dashboard KIRO MITM, problemi di triage 8.### Funzionalità\n\n-**Sviluppatore MiniMax→correzione ruolo di sistema**(PR n. 494 di @zhangqiang8vip): attiva/disattiva `preserveDeveloperRole` per modello. Aggiunge l'interfaccia utente \"Compatibilità\" nella pagina dei fornitori. Risolto il problema relativo all'errore 422 \"parametro ruolo\" per MiniMax e gateway simili. -**roleNormalizer**: `normalizeDeveloperRole()` ora accetta il parametro `preserveDeveloperRole` con comportamento a tre stati (unDefinito=mantieni, true=mantieni, false=converti). -**DB**: nuovi `getModelPreserveOpenAIDeveloperRole()` e `mergeModelCompatOverride()` in `models.ts`.### Bug Fixes\n\n-**Dashboard KIRO MITM**(#481/#487): `CLIToolsPageClient` ora instrada qualsiasi strumento `configType: \"mitm\"` a `AntigravityToolCard` (controlli Start/Stop MITM). In precedenza solo Antigravity era codificato. -**AntigravityToolCard generico**: utilizza `tool.image`, `tool.description`, `tool.id` invece dei valori Antigravity codificati. Protegge dai `defaultModels` mancanti.### Cleanup\n\n- Rimosso `ZWS_README_V2.md` (documenti di solo sviluppo dal PR n. 494).### Issues Triaged (8)\n\n-**#487**— Chiuso (KIRO MITM corretto in questa versione) -**#486**— ha bisogno di informazioni (problema relativo al PATH di Windows REG.exe) -**#489**: ha bisogno di informazioni (ID progetto Antigravity mancante, è necessaria la riconnessione OAuth) -**#492**— need-info (app/server.js mancante sul nodo mal gestito) -**#490**— Riconosciuto (streaming + blocco della cache di contesto, correzione pianificata) -**#491**— Riconosciuto (incoerenza dello stato di autenticazione del Codex) -**#493**: riconosciuto (prefisso del nome del modello del provider modale, soluzione alternativa fornita) -**#488**: arretrato di richieste di funzionalità (elenchi di modelli con aggiornamento automatico)---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: risolti i flussi SSE zombie, la cache di contesto al primo turno, KIRO MITM e i problemi esterni di triage 5.### Bug Fixes\n\n-**Streaming SSE Zombie**(#473): ridotto `STREAM_IDLE_TIMEOUT_MS` da 300 → 120 secondi per un fallback combinato più rapido quando i provider si bloccano a metà streaming. Configurabile tramite env var. -**Tag cache di contesto**(#474): risolto il problema con `injectModelTag()` per gestire le richieste del primo turno (nessun messaggio di assistente): la protezione della cache di contesto ora funziona fin dalla prima risposta. -**KIRO MITM**(#481): modifica KIRO `configType` da `guide` → `mitm` in modo che la dashboard visualizzi i controlli Start/Stop MITM. -**Test E2E**(CI): correggere `providers-bailian-coding-plan.spec.ts`: ignora l'overlay modale preesistente prima di fare clic sul pulsante Aggiungi chiave API.### Closed Issues\n\n- #473 — I flussi Zombie SSE bypassano il fallback combinato\n- #474 — Tag della cache contestuale `` mancante al primo turno\n- #481 — MITM per KIRO non attivabile dal dashboard\n- #468: server remoto Gemini CLI (sostituito dalla deprecazione #462)\n- #438 — Claude non è in grado di scrivere file (problema CLI esterno)\n- #439 — AppImage non funziona (soluzione alternativa documentata con libfuse2)\n- #402 - ARM64 DMG \"danneggiato\" (soluzione alternativa documentata xattr -cr)\n- #460: CLI non eseguibile su Windows (correzione PATH documentata)---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: deprecazione della CLI Gemini, correzione i18n della guida VM, correzione della sicurezza dependabot, espansione dello schema del provider.### Funzionalità\n\n-**Deprecazione della Gemini CLI**(#462): contrassegna il provider `gemini-cli` come deprecato con un avviso: Google limita l'utilizzo di OAuth di terze parti da marzo 2026 -**Schema provider**(#462): espande la convalida Zod con i campi opzionali `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint`### Bug Fixes\n\n-**VM Guide i18n**(#471): aggiunto `VM_DEPLOYMENT_GUIDE.md` alla pipeline di traduzione i18n, rigenera tutte le 30 traduzioni locali dall'origine inglese (erano bloccate in portoghese).### Sicurezza\n\n-**deps**: Bump `flatted` 3.3.3 → 3.4.2 — risolve l'inquinamento del prototipo CWE-1321 (#484, @dependabot)### Closed Issues\n\n- #472 — Regressione degli alias del modello (risolto nella v2.8.2)\n- #471 — Traduzioni della guida VM interrotte\n- #483 — Finale `data: null` dopo `[DONE]` (risolto nella v2.8.3)### Merged PRs\n\n- #484 — deps: bump flattato da 3.3.3 a 3.4.2 (@dependabot)---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: i18n ceco, correzione del protocollo SSE, traduzione della guida VM.### Funzionalità\n\n-**Lingua ceca**(#482): ceco completo (cs) i18n: 22 documenti, 2606 stringhe UI, aggiornamenti per il cambio di lingua (@zen0bit) -**Guida alla distribuzione delle VM**: tradotto dal portoghese all'inglese come documento sorgente (@zen0bit)### Bug Fixes\n\n-**Protocollo SSE**(#483): interrompe l'invio di `data: null` finale dopo il segnale `[DONE]`: corregge `AI_TypeValidationError` nei client AI SDK rigorosi (validatori basati su Zod).### Merged PRs\n\n- #482 - Aggiungi la lingua ceca + Correggi la fonte inglese VM_DEPLOYMENT_GUIDE.md (@zen0bit)---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 PR uniti, correzione del routing degli alias del modello, esportazione dei log e valutazione dei problemi.### Funzionalità\n\n-**Esportazione registri**: nuovo pulsante di esportazione su `/dashboard/logs` con menu a discesa dell'intervallo di tempo (1 ora, 6 ore, 12 ore, 24 ore). Scarica JSON di log di richieste/proxy/chiamate tramite l'API `/api/logs/export` (#user-request)### Bug Fixes\n\n-**Instradamento degli alias del modello**(#472): Impostazioni → Gli alias del modello ora influenzano correttamente il routing del provider, non solo il rilevamento del formato. In precedenza l'output di `resolveModelAlias()` veniva utilizzato solo per `getModelTargetFormat()` ma l'ID del modello originale veniva inviato al provider -**Utilizzo dello svuotamento del flusso**(#480): i dati sull'utilizzo dell'ultimo evento SSE nel buffer vengono ora estratti correttamente durante lo scaricamento del flusso (uniti da @prakersh)### Merged PRs\n\n- #480: estrae l'utilizzo dal buffer rimanente nel gestore di flush (@prakersh)\n- #479 - Aggiunte voci di prezzo mancanti per il Codex 5.3/5.4 e l'ID del modello antropico (@prakersh)---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: cinque PR della community: correzioni del registro delle chiamate in streaming, compatibilità con Kiro, analisi dei token della cache, traduzione in cinese e ID di chiamata degli strumenti configurabili.### Funzionalità\n\n-**feat(logs)**: il contenuto della risposta del registro delle chiamate ora viene accumulato correttamente dai blocchi grezzi del provider (OpenAI/Claude/Gemini) prima della traduzione, risolvendo i payload di risposta vuoti in modalità streaming (#470, @zhangqiang8vip). -**feat(providers)**: normalizzazione dell'ID chiamata dello strumento a 9 caratteri configurabile per modello (stile Mistral): solo i modelli con l'opzione abilitata ottengono ID troncati (#470) -**feat(api)**: API Key PATCH estesa per supportare i campi `allowedConnections`, `name`, `autoResolve`, `isActive` e `accessSchedule` (#470) -**feat(dashboard)**: layout della prima risposta nell'interfaccia utente dei dettagli del registro delle richieste (#470) -**feat(i18n)**: traduzione cinese (zh-CN) migliorata — ritraduzione completa (#475, @only4copilot)### 🐛 Bug Fixes\n\n-**fix(kiro)**: rimuove il campo `model` inserito dal corpo della richiesta: l'API Kiro rifiuta i campi di livello superiore sconosciuti (#478, @prakersh) -**correzione (utilizzo)**: include la lettura della cache + i token di creazione della cache nei totali di input della cronologia di utilizzo per analisi accurate (#477, @prakersh) -**fix(callLogs)**: supporta i campi di utilizzo del formato Claude (`input_tokens`/`output_tokens`) insieme al formato OpenAI, include tutte le varianti dei token cache (#476, @prakersh)---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: fornitore del piano di codifica Bailian con URL di base modificabili, oltre a contributi della community per Alibaba Cloud e Kimi Coding.### Funzionalità\n\n-**feat(providers)**: aggiunto il piano di codifica Bailian (\"bailian-coding-plan\") — Alibaba Model Studio con API compatibile con Anthropic. Catalogo statico di 8 modelli tra cui Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5 e Kimi K2.5. Include la convalida dell'autenticazione personalizzata (400=valido, 401/403=non valido) (#467, @Mind-Dragon) -**feat(admin)**: URL predefinito modificabile nei flussi di creazione/modifica di Amministrazione del provider: gli utenti possono configurare URL di base personalizzati per connessione. Persistito in `providerSpecificData.baseUrl` con la convalida dello schema Zod che rifiutava gli schemi non http(s) (#467)### 🧪 Tests\n\n- Aggiunti oltre 30 unit test e 2 scenari e2e per il provider del piano di codifica Bailian che coprono la convalida dell'autenticazione, il rafforzamento dello schema, il comportamento a livello di percorso e l'integrazione tra livelli---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: due nuovi fornitori forniti dalla comunità (Alibaba Cloud Coding, chiave API Kimi Coding) e correzione pino Docker.### Funzionalità\n\n-**feat(providers)**: aggiunto il supporto del piano Alibaba Cloud Coding con due endpoint compatibili con OpenAI: `alicode` (Cina) e `alicode-intl` (internazionale), ciascuno con 8 modelli (#465, @dtk1985) -**feat(providers)**: aggiunto il percorso dedicato del provider `kimi-coding-apikey`: l'accesso a Kimi Coding basato su chiave API non è più forzato tramite il percorso `kimi-coding` solo OAuth. Include registro, costanti, API dei modelli, configurazione e test di convalida (#463, @Mind-Dragon)### 🐛 Bug Fixes\n\n-**fix(docker)**: aggiunta la dipendenza `split2` mancante all'immagine Docker: `pino-abstract-transport` la richiede in fase di runtime ma non veniva copiata nel contenitore autonomo, causando arresti anomali di `Impossibile trovare il modulo 'split2'` (#459)---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: passthrough del sottopercorso delle risposte del Codex supportato in modo nativo, arresto anomalo di Windows MITM risolto e schemi agente Combo modificati.### Funzionalità\n\n-**feat(codex)**: passthrough del sottopercorso delle risposte native per il Codex: instrada nativamente `POST /v1/responses/compact` al Codex a monte, mantenendo la compatibilità del codice Claude senza rimuovere il suffisso `/compact` (#457)### 🐛 Bug Fixes\n\n-**fix(combos)**: gli schemi Zod (`updateComboSchema` e `createComboSchema`) ora includono `system_message`, `tool_filter_regex` e `context_cache_protection`. Risolto un bug per cui le impostazioni specifiche dell'agente create tramite la dashboard venivano ignorate silenziosamente dal livello di convalida del backend (#458) -**fix(mitm)**: risolto il crash del profilo Kiro MITM su Windows: `node-machine-id` non è riuscito a causa della mancanza di `REG.exe` env e il fallback ha generato un errore fatale \"crypto is not define\". Il fallback ora importa in modo sicuro e corretto la crittografia (#456)---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: bug di salvataggio del budget + funzionalità combinate dell'agente UI + correzione della sicurezza del tag omniModel.### 🐛 Bug Fixes\n\n-**fix(budget)**: \"Salva limiti\" non restituisce più 422 — `warningThreshold` ora viene inviato correttamente come frazione (0–1) anziché come percentuale (0–100) (#451) -**fix(combos)**: il tag della cache interna `` viene ora rimosso prima di inoltrare le richieste ai provider, impedendo interruzioni della sessione di cache (#454)### Funzionalità\n\n-**feat(combos)**: sezione Funzionalità agente aggiunta alla modalità di creazione/modifica combo: espone l'override di `system_message`, `tool_filter_regex` e `context_cache_protection` direttamente dal dashboard (#454)---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: arresto anomalo di Docker pino, correzione del lavoratore delle risposte della CLI del Codex, sincronizzazione del blocco dei pacchetti.### 🐛 Bug Fixes\n\n-**fix(docker)**: `pino-abstract-transport` e `pino-pretty` ora copiati esplicitamente nella fase runner Docker — La traccia standalone Next.js non rileva queste dipendenze peer, causando il crash di `Impossibile trovare il modulo pino-abstract-transport` all'avvio (#449) -**risolto (risposte)**: rimosso `initTranslators()` dal percorso `/v1/responses`: si verificava l'arresto anomalo del lavoratore Next.js con `il lavoratore è uscito` uncaughtException sulle richieste CLI del Codex (#450)### 🔧 Maintenance\n\n-**chore(deps)**: `package-lock.json` ora è stato eseguito su ogni bump di versione per garantire che Docker `npm ci` utilizzi le versioni esatte delle dipendenze---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: miglioramenti UX e correzione del controllo dello stato della CLI di Windows.### 🐛 Bug Fixes\n\n-**correzione(ux)**: mostra il suggerimento password predefinito nella pagina di accesso: i nuovi utenti ora vedono `\"Password predefinita: 123456\"` sotto l'immissione della password (#437) -**fix(cli)**: Claude CLI e altri strumenti installati da npm ora vengono rilevati correttamente come eseguibili su Windows: spawn utilizza `shell:true` per risolvere i wrapper `.cmd` tramite PATHEXT (#447)---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: dashboard degli strumenti di ricerca, correzioni i18n, limiti Copilot, correzione convalida Serper.### Funzionalità\n\n-**feat(search)**: aggiunta area di gioco di ricerca (10° endpoint), pagina Strumenti di ricerca con confronto di provider/pipeline di riclassificazione/cronologia di ricerca, routing di riclassificazione locale, protezioni di autenticazione sull'API di ricerca (#443 di @Regis-RCR)\n\n- Nuovo percorso: `/dashboard/search-tools`\n- Voce della barra laterale nella sezione Debug\n- `GET /api/search/providers` e `GET /api/search/stats` con protezioni di autenticazione\n- Routing provider_nodes locale per `/v1/rerank`\n- Oltre 30 chiavi i18n nello spazio dei nomi di ricerca### 🐛 Bug Fixes\n\n-**correzione (ricerca)**: corretto il normalizzatore di notizie Brave (restituiva 0 risultati), applicazione del troncamento max_results post-normalizzazione, corretto l'URL di recupero della pagina Endpoint (#443 di @Regis-RCR) -**fix(analytics)**: localizza le etichette giorno/data di analisi: sostituisci le stringhe portoghesi hardcoded con `Intl.DateTimeFormat(locale)` (#444 di @hijak) -**fix(copilot)**: corretta visualizzazione del tipo di account GitHub Copilot, filtraggio di righe di quota illimitata fuorvianti dal dashboard dei limiti (#445 di @hijak) -**correzione(provider)**: smetti di rifiutare chiavi API Serper valide: tratta le risposte non 4xx come autenticazione valida (#446 di @hijak)---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: correzione del fallback della quota API diretta del Codex.### 🐛 Bug Fixes\n\n-**fix(codex)**: blocca gli account esauriti settimanalmente nel fallback API diretto (#440)\n\n- Corrispondenza del prefisso `resolveQuotaWindow()`: `\"weekly\"` ora corrisponde alle chiavi della cache `\"weekly (7d)\"`\n- `applyCodexWindowPolicy()` impone l'attivazione/disattivazione corretta di `useWeekly`/`use5h`\n- 4 nuovi test di regressione (766 in totale)---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: correzioni del contrasto dell'interfaccia utente in modalità Luce.### 🐛 Bug Fixes\n\n-**fix(logs)**: risolto il contrasto della modalità luce nei pulsanti del filtro dei log delle richieste e nel badge combinato (#378).\n\n- I pulsanti del filtro Errore/Riuscito/Combo ora sono leggibili in modalità luce\n- Il badge della riga combinata utilizza un viola più forte in modalità luce---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: routing di ricerca web unificato (POST /v1/search) con 5 provider + correzioni di sicurezza Next.js 16.1.7 (6 CVE).### ✨ New Features\n\n-**feat(search)**: routing di ricerca web unificato — `POST /v1/search` con 5 provider (Serper, Brave, Perplexity, Exa, Tavily)\n\n- Failover automatico tra provider, oltre 6.500 ricerche gratuite al mese\n- Cache in memoria con coalescenza delle richieste (TTL configurabile)\n- Dashboard: scheda Analisi delle ricerche in \"/dashboard/analytics\" con suddivisione dei fornitori, percentuale di riscontri nella cache, monitoraggio dei costi\n- Nuova API: `GET /api/v1/search/analytics` per le statistiche delle richieste di ricerca\n- Migrazione del DB: colonna \"request_type\" su \"call_logs\" per il monitoraggio delle richieste non chat\n- Convalida Zod (`v1SearchSchema`), autenticata, costo registrato tramite `recordCost()`### Sicurezza\n\n-**deps**: Next.js 16.1.6 → 16.1.7 — corregge 6 CVE: -**Critico**: CVE-2026-29057 (contrabbando di richieste HTTP tramite proxy http) -**Alto**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Azioni server) -**Medio**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7### 📁 New Files\n\n| File | Scopo |\n| ---------------------------------------------------------------- | ---------------------------------------------------------- | --- |\n| `open-sse/handlers/search.ts` | Gestore di ricerca con routing a 5 provider |\n| `open-sse/config/searchRegistry.ts` | Registro dei fornitori (autenticazione, costo, quota, TTL) |\n| `open-sse/services/searchCache.ts` | Cache in memoria con coalescenza delle richieste |\n| `src/app/api/v1/search/route.ts` | Percorso Next.js (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | API delle statistiche di ricerca |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Scheda dashboard Analisi |\n| `src/lib/db/migrations/007_search_request_type.sql` | Migrazione DB |\n| `test/unità/search-registry.test.mjs` | 277 righe di test unitari | --- |\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: funzionalità ispirate a ClawRouter: flag toolCalling, rilevamento intent multilingue, fallback basato su benchmark, deduplicazione delle richieste, RouterStrategy collegabile, prezzi Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5.### ✨ New Models & Pricing\n\n-**feat(prezzo)**: xAI Grok-4 Fast — `$0,20/$0,50 per 1 milione di token`, latenza p50 di 1143 ms, chiamata strumento supportata -**feat(pricing)**: xAI Grok-4 (standard) — `$0,20/$1,50 per 1 milione di token`, ragionamento di punta -**feat(prezzo)**: GLM-5 tramite Z.AI — `$0,5/1 milione`, contesto di output da 128.000 -**feat(pricing)**: MiniMax M2.5 — `$0,30/1 milione di input`, ragionamento + compiti di agente -**feat(prezzi)**: DeepSeek V3.2 — prezzo aggiornato \"$0,27/$1,10 per 1 milione\" -**feat(prezzo)**: Kimi K2.5 tramite Moonshot API: accesso diretto all'API Moonshot -**feat(providers)**: aggiunto il provider Z.AI (alias `zai`) — Famiglia GLM-5 con output 128K### 🧠 Routing Intelligence\n\n-**feat(registry)**: flag `toolCalling` per modello nel registro del provider: le combo ora possono preferire/richiedere modelli in grado di richiamare strumenti -**feat(punteggio)**: rilevamento dell'intento multilingue per il punteggio AutoCombo: i modelli di script/linguaggio PT/ZH/ES/AR influenzano la selezione del modello in base al contesto della richiesta -**feat(fallback)**: catene di fallback basate sul benchmark: dati di latenza reale (p50 da \"comboMetrics\") utilizzati per riordinare dinamicamente la priorità di fallback -**feat(dedup)**: Richiedi la deduplicazione tramite content-hash: la finestra di idempotenza di 5 secondi impedisce alle chiamate duplicate del provider di ritentare i client -**feat(router)**: interfaccia `RouterStrategy` collegabile in `autoCombo/routerStrategy.ts`: la logica di routing personalizzata può essere inserita senza modificare il core### 🔧 MCP Server Improvements\n\n-**feat(mcp)**: 2 nuovi schemi di strumenti avanzati: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) e `omniroute_explain_route` (spiegazione della decisione di routing) -**feat(mcp)**: ambiti di autenticazione dello strumento MCP aggiornati — ambito `metrics:read` aggiunto per gli strumenti di metrica del provider -**feat(mcp)**: `omniroute_best_combo_for_task` ora accetta il parametro `lingualHint` per il routing multilingue### 📊 Observability\n\n-**feat(metrics)**: `comboMetrics.ts` esteso con monitoraggio del percentile di latenza in tempo reale per provider/account -**feat(health)**: l'API Health (`/api/monitoring/health`) ora restituisce i campi \"p50Latency\" e \"errorRate\" per provider -**feat(usage)**: migrazione della cronologia di utilizzo per il monitoraggio della latenza per modello### 🗄️ DB Migrations\n\n-**feat(migrations)**: nuova colonna `latency_p50` nella tabella `combo_metrics`: zero-breaking, sicura per gli utenti esistenti### 🐛 Bug Fixes / Closures\n\n-**close(#411)**: risoluzione del modulo con hash better-sqlite3 su Windows: risolto nella v2.6.10 (f02c5b5) -**close(#409)**: i completamenti della chat di GitHub Copilot non riescono con i modelli Claude quando vengono allegati i file: risolto nella v2.6.9 (838f1d6) -**close(#405)**: duplicato di #411 — risolto## [2.6.10] — 2026-03-17\n\n> Correzione per Windows: download precompilato better-sqlite3 senza node-gyp/Python/MSVC (#426).### 🐛 Bug Fixes\n\n-**correzione(install/#426)**: Su Windows, `npm install -g omniroute` falliva con `better_sqlite3.node non è un'applicazione Win32 valida` perché il binario nativo in bundle era stato compilato per Linux. Aggiunge**Strategy 1.5**a `scripts/postinstall.mjs`: utilizza `@mapbox/node-pre-gyp install --fallback-to-build=false` (in bundle con `better-sqlite3`) per scaricare il file binario precompilato corretto per il sistema operativo/arch attuale senza richiedere alcuno strumento di compilazione (no node-gyp, no Python, no MSVC). Torna a \"npm ricostruire\" solo se il download fallisce. Aggiunge messaggi di errore specifici della piattaforma con chiare istruzioni per la correzione manuale.---\n\n## [2.6.9] — 2026-03-17\n\n> Correzioni CI (t11 con qualsiasi budget), correzione del bug n. 409 (file allegati tramite Copilot+Claude), correzione del flusso di lavoro del rilascio.### 🐛 Bug Fixes\n\n-**fix(ci)**: rimossa la parola \"any\" dai commenti in `openai-responses.ts` e `chatCore.ts` che non superavano il controllo del budget t11 `any` (falso positivo dai commenti sul conteggio delle regex) -**fix(chatCore)**: normalizza i tipi di parti di contenuto non supportati prima dell'inoltro ai provider (#409 — Il cursore invia `{type:\"file\"}` quando i file `.md` sono allegati; Copilot e altri provider compatibili con OpenAI rifiutano con \"il tipo deve essere 'image_url' o 'text'\"; la correzione converte i blocchi `file`/`document` in `text` ed elimina i tipi sconosciuti)### 🔧 Workflow\n\n-**chore(generate-release)**: aggiunta ATOMIC COMMIT RULE — il bump della versione (`npm version patch`) DEVE avvenire prima del commit dei file di funzionalità per garantire che il tag punti sempre a un commit contenente tutte le modifiche alla versione insieme---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo come agente (prompt di sistema + filtro strumento), protezione della cache del contesto, aggiornamento automatico, registri dettagliati, MITM Kiro IDE.### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n-**005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0` -**006_detailed_request_logs.sql**: nuova tabella `request_detail_logs` con trigger ring-buffer da 500 voci, attivazione tramite attivazione/disattivazione delle impostazioni### Funzionalità\n\n-**feat(combo)**: Override del messaggio di sistema per Combo (#399 — il campo `system_message` sostituisce o inserisce il prompt di sistema prima dell'inoltro al provider) -**feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` mantiene solo gli strumenti che corrispondono al pattern; supporta i formati OpenAI + Anthropic) -**feat(combo)**: Protezione della cache del contesto (#401 — `context_cache_protection` tag risposte con `provider/model` e modello pin per la continuità della sessione) -**feat(settings)**: aggiornamento automatico tramite Impostazioni (#320 — `GET /api/system/version` + `POST /api/system/update` — controlla il registro npm e gli aggiornamenti in background con il riavvio di pm2) -**feat(logs)**: registri dettagliati delle richieste (#378 — acquisisce i corpi completi della pipeline in 4 fasi: richiesta del cliente, richiesta tradotta, risposta del fornitore, risposta del cliente — attivazione/disattivazione, assetto da 64 KB, ring buffer da 500 voci) -**feat(mitm)**: profilo IDE MITM Kiro (#336 — `src/mitm/targets/kiro.ts` prende di mira api.anthropic.com, riutilizza l'infrastruttura MITM esistente)---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: miglioramenti SSE, estensioni provider_nodes locali, registro proxy, correzioni passthrough Claude.### Funzionalità\n\n-**feat(health)**: controllo dello stato in background per `provider_nodes` locali con backoff esponenziale (30s→300s) e `Promise.allSettled` per evitare blocchi (#423, @Regis-RCR) -**feat(embeddings)**: instrada `/v1/embeddings` a `provider_nodes` locale — `buildDynamicEmbeddingProvider()` con convalida del nome host (#422, @Regis-RCR) -**feat(audio)**: instrada TTS/STT a `provider_nodes` locale — `buildDynamicAudioProvider()` con protezione SSRF (#416, @Regis-RCR) -**feat(proxy)**: registro proxy, API di gestione e generalizzazione dei limiti di quota (#429, @Regis-RCR)### 🐛 Bug Fixes\n\n-**fix(sse)**: Elimina i campi specifici di Claude (`metadata`, `anthropic_version`) quando il target è OpenAI-compat (#421, @prakersh) -**fix(sse)**: estratto l'utilizzo di Claude SSE (`input_tokens`, `output_tokens`, token cache) in modalità flusso passthrough (#420, @prakersh) -**fix(sse)**: genera fallback `call_id` per chiamate a strumenti con ID mancanti/vuoti (#419, @prakersh) -**fix(sse)**: passaggio da Claude a Claude: corpo anteriore completamente intatto, nessuna ritraduzione (#418, @prakersh) -**fix(sse)**: filtra gli elementi `tool_result` orfani dopo la compattazione del contesto del codice Claude per evitare errori 400 (#417, @prakersh). -**fix(sse)**: ignora le chiamate allo strumento con nome vuoto nel traduttore dell'API Responses per impedire cicli infiniti di `placeholder_tool` (#415, @prakersh) -**fix(sse)**: rimuove i blocchi di contenuto di testo vuoti prima della traduzione (#427, @prakersh) -**fix(api)**: aggiunto `refreshable: true` alla configurazione del test Claude OAuth (#428, @prakersh)### 📦 Dependencies\n\n- Bump di `vitest`, `@vitest/*` e relative devDependencies (#414, @dependabot)---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: compatibilità Turbopack/Docker: rimozione del protocollo `node:` da tutte le importazioni `src/`.### 🐛 Bug Fixes\n\n-**fix(build)**: rimosso il prefisso del protocollo `node:` dalle istruzioni `import` in 17 file sotto `src/`. Le importazioni di `node:fs`, `node:path`, `node:url`, `node:os` ecc. causavano \"Il file Ecmascript presentava un errore\" sulle build Turbopack (Next.js 15 Docker) e sugli aggiornamenti da installazioni globali npm precedenti. File interessati: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts` e altri 12 in `src/app/api/` e `src/lib/`. -**lavoretto (flusso di lavoro)**: aggiornato `generate-release.md` per fare in modo che la sincronizzazione dell'hub Docker e la distribuzione dual-VPS siano**passaggi obbligatori**in ogni versione.---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: filtraggio dei parametri del modello di ragionamento, correzione 404 del provider locale, provider Kilo Gateway, aumenti delle dipendenze.### ✨ New Features\n\n-**feat(api)**: aggiunto**Kilo Gateway**(`api.kilo.ai`) come nuovo fornitore di chiavi API (alias `kg`) — oltre 335 modelli, 6 modelli gratuiti, 3 modelli di routing automatico (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Modelli passthrough supportati tramite endpoint \"/api/gateway/models\". (PR n. 408 di @Regis-RCR)### 🐛 Bug Fixes\n\n-**fix(sse)**: rimuove i parametri non supportati per i modelli di ragionamento (o1, o1-mini, o1-pro, o3, o3-mini). I modelli della famiglia `o1`/`o3` rifiutano `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs` e `n` con HTTP 400. I parametri vengono ora rimossi al livello `chatCore` prima dell'inoltro. Utilizza un campo dichiarativo `unsupportedParams` per modello e una mappa O(1) precalcolata per la ricerca. (PR n. 412 di @Regis-RCR) -**fix(sse)**: il provider locale 404 ora comporta un**blocco solo del modello (5 secondi)**invece di un blocco a livello di connessione (2 minuti). Quando un backend di inferenza locale (Ollama, LM Studio, oMLX) restituisce 404 per un modello sconosciuto, la connessione rimane attiva e gli altri modelli continuano a funzionare immediatamente. Risolve anche un bug preesistente in cui `model` non veniva passato a `markAccountUnavailable()`. Provider locali rilevati tramite nome host (`localhost`, `127.0.0.1`, `::1`, estensibile tramite `LOCAL_HOSTNAMES` env var). (PR n. 410 di @Regis-RCR)### 📦 Dependencies\n\n- `meglio-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- \"base-agente\" 7 → 8---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n-**fix(provider)**: rimossi nomi di modelli inesistenti su 5 provider: -**gemini / gemini-cli**: rimossi `gemini-3.1-pro/flash` e `gemini-3-*-preview` (non esistono nell'API di Google v1beta); sostituito con `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash` -**antigravity**: rimossi `gemini-3.1-pro-high/low` e `gemini-3-flash` (alias interni non validi); sostituito con modelli 2.x reali -**github (Copilot)**: rimossi `gemini-3-flash-preview` e `gemini-3-pro-preview`; sostituito con \"gemini-2.5-flash\". -**nvidia**: corretto `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM utilizza lo spazio dei nomi `meta/` per i modelli Meta); aggiunti `nvidia/llama-3.1-70b-instruct` e `nvidia/llama-3.1-405b-instruct` -**fix(db/combo)**: Aggiornata la combo `free-stack` sul DB remoto: rimosso `qw/qwen3-coder-plus` (token di aggiornamento scaduto), corretto `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corretto `gemini/gemini-3.1-flash` → \"gemini/gemini-2.5-flash\", aggiunto \"if/deepseek-v3.2\"---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: striscia hash zod/pino inserita nella pipeline di compilazione, provider sintetico aggiunto, percorso VPS PM2 corretto.### 🐛 Bug Fixes\n\n-**fix(build)**: Turbopack hash-strip ora viene eseguito in**tempo di compilazione**per TUTTI i pacchetti — non solo per `better-sqlite3`. Il passaggio 5.6 in \"prepublish.mjs\" percorre ogni \".js\" in \"app/.next/server/\" ed elimina il suffisso esadecimale di 16 caratteri da qualsiasi \"require()\" con hash. Correzioni `zod-dcb22c...`, `pino-...`, ecc. MODULE_NOT_FOUND sulle installazioni npm globali. Chiude il numero 398 -**fix(deploy)**: PM2 su entrambi i VPS puntava a directory git-clone obsolete. Riconfigurato in \"app/server.js\" nel pacchetto globale npm. Aggiornato il flusso di lavoro `/deploy-vps` per utilizzare `npm pack + scp` (il registro npm rifiuta i pacchetti da 299 MB).### Funzionalità\n\n-**feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — inferenza compatibile con OpenAI incentrata sulla privacy. \"passthroughModels: true\" per il catalogo dinamico dei modelli HuggingFace. Modelli iniziali: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR n. 404 di @Regis-RCR)### 📋 Issues Closed\n\n-**chiudi #398**: regressione dell'hash npm: risolto dall'hash-strip in fase di compilazione in fase di prepubblicazione -**triage #324**: screenshot del bug senza passaggi: dettagli di riproduzione richiesti---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: hashing del modulo completamente corretto, 2 PR accorpati (filtro strumenti antropici + percorsi endpoint personalizzati), aggiunto il provider Alibaba Cloud DashScope, 3 problemi obsoleti chiusi.### 🐛 Bug Fixes\n\n-**fix(build)**: hash strip estesa del pacchetto web \"externals\" per coprire TUTTI i \"serverExternalPackages\", non solo \"better-sqlite3\". Next.js 16 Turbopack esegue l'hashing di `zod`, `pino` e di ogni altro pacchetto esterno al server in nomi come `zod-dcb22c6336e0bc69` che non esistono in `node_modules` in fase di runtime. Una regex catch-all HASH_PATTERN ora rimuove il suffisso di 16 caratteri e ritorna al nome del pacchetto base. Aggiunto anche `NEXT_PRIVATE_BUILD_WORKER=0` in \"prepublish.mjs\" per rafforzare la modalità webpack, oltre a una scansione post-build che segnala eventuali riferimenti con hash rimanenti. (#396, #398, PR #403) -**fix(chat)**: i nomi degli strumenti in formato antropico (`tool.name` senza wrapper `.function`) venivano eliminati silenziosamente dal filtro dei nomi vuoti introdotto in #346. LiteLLM inoltra le richieste con il prefisso `antropic/` nel formato API Messaggi Anthropic, causando il filtraggio di tutti gli strumenti e la restituzione di Anthropic `400: tool_choice.any può essere specificato solo durante la fornitura degli strumenti`. Risolto il problema con il ritorno a \"tool.name\" quando \"tool.function.name\" è assente. Aggiunti 8 test unitari di regressione. (PR n. 397)### Funzionalità\n\n-**feat(api)**: percorsi endpoint personalizzati per nodi provider compatibili con OpenAI: configura `chatPath` e `modelsPath` per nodo (ad esempio `/v4/chat/completions`) nell'interfaccia utente di connessione del provider. Include una migrazione del DB (`003_provider_node_custom_paths.sql`) e la sanificazione del percorso URL (nessun attraversamento `..`, deve iniziare con `/`). (PR n. 400) -**feat(provider)**: Alibaba Cloud DashScope aggiunto come provider compatibile con OpenAI. Endpoint internazionale: `dashscope-intl.aliyuncs.com/compatibili-mode/v1`. 12 modelli: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Autenticazione: chiave API bearer.### 📋 Issues Closed\n\n-**chiudi #323**: errore di connessione Cline `[oggetto Oggetto]` — risolto nella v2.3.7; ha richiesto all'utente di aggiornare dalla versione 2.2.9 -**chiudi #337**: monitoraggio del credito Kiro — implementato nella v2.5.5 (#381); indirizzato l'utente a Dashboard → Utilizzo -**triage #402**: ARM64 macOS DMG danneggiato: richiesta versione macOS, errore esatto e soluzione alternativa consigliata `xattr -d com.apple.quarantine`---\n\n## [2.6.1] — 2026-03-15\n\n> Correzione critica all'avvio: le installazioni npm globali v2.6.0 si sono arrestate in modo anomalo con un errore 500 a causa di un bug di hashing del nome modulo Turbopack/webpack nell'hook della strumentazione Next.js 16.### 🐛 Bug Fixes\n\n-**fix(build)**: forza che `better-sqlite3` sia sempre richiesto con il nome esatto del pacchetto nel bundle del server webpack. Next.js 16 ha compilato l'hook della strumentazione in un blocco separato ed ha emesso `require('better-sqlite3-')` — un nome di modulo con hash che non esiste in `node_modules` — anche se il pacchetto era elencato in `serverExternalPackages`. Aggiunta una funzione esplicita `externals` alla configurazione del webpack del server in modo che il bundler emetta sempre `require('better-sqlite3')`, risolvendo l'avvio `500 Internal Server Error` su installazioni globali pulite. (#394, PR #395)### 🔧 CI\n\n-**ci**: aggiunto `workflow_dispatch` a `npm-publish.yml` con protezione della sincronizzazione della versione per i trigger manuali (#392). -**ci**: aggiunto `workflow_dispatch` a `docker-publish.yml`, aggiornate le azioni GitHub alle ultime versioni (#392).---\n\n## [2.6.0] - 2026-03-15\n\n> Sprint per la risoluzione dei problemi: 4 bug risolti, log UX migliorati, aggiunto il monitoraggio del credito Kiro.### 🐛 Bug Fixes\n\n-**correzione(media)**: ComfyUI e SD WebUI non vengono più visualizzati nell'elenco dei provider della pagina multimediale quando non sono configurati: recupera `/api/providers` al montaggio e nasconde i provider locali senza connessioni (#390). -**correzione(auth)**: il round robin non riseleziona più gli account con velocità limitata immediatamente dopo il raffreddamento: `backoffLevel` è ora utilizzato come chiave di ordinamento primaria nella rotazione LRU (#340) -**risolto (oauth)**: Qoder (e altri provider che reindirizzano alla propria interfaccia utente) non lasciano più la modalità OAuth bloccata su \"In attesa di autorizzazione\" - transizioni automatiche del rilevatore popup chiuso alla modalità di immissione URL manuale (#344) -**fix(logs)**: la tabella dei log delle richieste è ora leggibile in modalità light: i badge di stato, i conteggi dei token e i tag combinati utilizzano classi di colore adattive `dark:` (#378)### Funzionalità\n\n-**feat(kiro)**: monitoraggio del credito Kiro aggiunto al fetcher di utilizzo: query `getUserCredits` dall'endpoint AWS CodeWhisperer (#337)### 🛠 Chores\n\n-**chore(tests)**: Allineati `test:plan3`, `test:fixes`, `test:security` per utilizzare lo stesso caricatore `tsx/esm` di `npm test` — elimina i falsi negativi della risoluzione del modulo nelle esecuzioni mirate (PR #386)---\n\n## [2.5.9] - 2026-03-15\n\n> Correzione del passthrough nativo del Codex + rafforzamento della convalida del corpo del percorso.### 🐛 Bug Fixes\n\n-**fix(codex)**: preserva il passthrough dell'API Responses nativa per i client Codex: evita mutazioni di traduzione non necessarie (PR n. 387) -**fix(api)**: convalida i corpi delle richieste su prezzi/sincronizzazione e percorsi di routing delle attività: previene arresti anomali dovuti a input non validi (PR n. 388) -**fix(auth)**: i segreti JWT persistono dopo i riavvii tramite `src/lib/db/secrets.ts` — elimina gli errori 401 dopo il riavvio di pm2 (PR #388)---\n\n## [2.5.8] - 2026-03-15\n\n> Correzione della build: ripristino della connettività VPS interrotta dalla pubblicazione incompleta della v2.5.7.### 🐛 Bug Fixes\n\n-**fix(build)**: `scripts/prepublish.mjs` utilizzava ancora il flag deprecato `--webpack` causando il fallimento silenzioso della build standalone di Next.js: pubblicazione npm completata senza `app/server.js`, interrompendo la distribuzione VPS---\n\n## [2.5.7] - 2026-03-15\n\n> Correzioni nella gestione degli errori del parco giochi multimediale.### 🐛 Bug Fixes\n\n-**fix(media)**: trascrizione \"API Key Required\" falso positivo quando l'audio non contiene parlato (musica, silenzio) - ora mostra invece \"Nessun parlato rilevato\" -**fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` e `audioSpeech.ts` ora restituisce il JSON corretto (`{error:{message}}`), abilitando il corretto rilevamento degli errori di credenziale 401/403 in MediaPageClient -**fix(media)**: `parseApiError` ora gestisce il campo `err_msg` di Deepgram e rileva la `\"chiave API\"` nei messaggi di errore per una classificazione accurata degli errori delle credenziali---\n\n## [2.5.6] - 2026-03-15\n\n> Correzioni critiche di sicurezza/autenticazione: Antigravity OAuth interrotto + sessioni JWT perse dopo il riavvio.### 🐛 Bug Fixes\n\n-**fix(oauth) #384**: Antigravity Google OAuth ora invia correttamente `client_secret` all'endpoint del token. Il fallback per \"ANTIGRAVITY_OAUTH_CLIENT_SECRET\" era una stringa vuota, il che è falso, quindi \"client_secret\" non è mai stato incluso nella richiesta, causando errori \"client_secret mancante\" per tutti gli utenti senza una variabile env personalizzata. Chiude #383. -**fix(auth) #385**: `JWT_SECRET` è ora persistente su SQLite (`namespace='secrets'`) alla prima generazione e ricaricato agli avvii successivi. In precedenza, veniva generato un nuovo segreto casuale a ogni avvio del processo, invalidando tutti i cookie/sessioni esistenti dopo ogni riavvio o aggiornamento. Interessa sia \"JWT_SECRET\" che \"API_KEY_SECRET\". Chiude #382.---\n\n## [2.5.5] - 2026-03-15\n\n> Correzione della rimozione dell'elenco dei modelli, rafforzamento della build autonoma di Electron e monitoraggio del credito Kiro.### 🐛 Bug Fixes\n\n-**fix(models) #380**: `GET /api/models` ora include gli alias del provider durante la creazione del filtro del provider attivo: i modelli per `claude` (alias `cc`) e `github` (alias `gh`) venivano sempre mostrati indipendentemente dal fatto che fosse configurata una connessione, perché le chiavi `PROVIDER_MODELS` sono alias ma le connessioni DB vengono archiviate sotto gli ID del provider. Risolto il problema espandendo ogni ID provider attivo per includere anche il relativo alias tramite \"PROVIDER_ID_TO_ALIAS\". Chiude #353. -**fix(electron) #379**: Il nuovo `scripts/prepare-electron-standalone.mjs` mette in scena un bundle dedicato `/.next/electron-standalone` prima del packaging di Electron. Interrompe con un errore chiaro se `node_modules` è un collegamento simbolico (il costruttore di elettroni fornirebbe una dipendenza di runtime sulla macchina di compilazione). Sanificazione del percorso multipiattaforma tramite `path.basename`. Di @kfiramar.### ✨ New Features\n\n-**feat(kiro) #381**: monitoraggio del saldo del credito Kiro: l'endpoint di utilizzo ora restituisce i dati del credito per gli account Kiro chiamando `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (lo stesso endpoint Kiro IDE utilizzato internamente). Restituisce i crediti rimanenti, la franchigia totale, la data di rinnovo e il livello di abbonamento. Chiude #337.## [2.5.4] - 2026-03-15\n\n> Correzione dell'avvio del logger, correzione della sicurezza del bootstrap dell'accesso e miglioramento dell'affidabilità dell'HMR dello sviluppatore. L'infrastruttura CI è stata rafforzata.### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n-**fix(logger) #376**: ripristina il percorso del logger di trasporto pino — `formatters.level` combinato con `transport.targets` viene rifiutato da pino. Le configurazioni supportate dal trasporto ora eliminano il formattatore di livello tramite `getTransportCompatibleConfig()`. Corregge anche la mappatura del livello numerico in `/api/logs/console`: `30→info, 40→warn, 50→error` (era spostato di uno). -**fix(login) #375**: la pagina di accesso ora si avvia dall'endpoint pubblico `/api/settings/require-login` invece che da quello protetto `/api/settings`. Nelle configurazioni protette da password, la pagina di pre-autenticazione riceveva un 401 e tornava inutilmente alle impostazioni predefinite sicure. La route pubblica ora restituisce tutti i metadati di bootstrap (`requireLogin`, `hasPassword`, `setupComplete`) con un fallback conservativo di 200 in caso di errore. -**fix(dev) #374**: aggiunti `localhost` e `127.0.0.1` a `allowedDevOrigins` in `next.config.mjs` — Il websocket HMR veniva bloccato quando si accedeva all'app tramite indirizzo di loopback, producendo ripetuti avvisi multiorigine.### 🔧 CI & Infrastructure\n\n-**Correzione OOM ESLint**: `eslint.config.mjs` ora ignora `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**` e `clipr/**` — ESLint si bloccava con un OOM heap JS durante la scansione di BLOB binari VS Code e blocchi compilati. -**Correzione test unitario**: rimosso `ALTER TABLE provider_connections ADD COLUMN \"group\"` obsoleto da 2 file di test: la colonna ora fa parte dello schema di base (aggiunto in #373), causando `SQLITE_ERROR: nome colonna duplicato` su ogni esecuzione del CI. -**Hook pre-commit**: aggiunto `npm run test:unit` a `.husky/pre-commit`: i test unitari ora bloccano i commit interrotti prima che raggiungano il CI.## [2.5.3] - 2026-03-14\n\n> Correzioni di bug critici: migrazione dello schema DB, caricamento dell'ambiente di avvio, cancellazione dello stato degli errori del provider e correzione del tooltip i18n. Miglioramenti della qualità del codice su ogni PR.### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n-**fix(db) #373**: aggiunta la colonna `provider_connections.group` allo schema di base + migrazione del backfill per i database esistenti: la colonna veniva utilizzata in tutte le query ma mancava nella definizione dello schema -**correzione(i18n) #371**: sostituzione della chiave inesistente `t(\"deleteConnection\")` con la chiave `provviders.delete` esistente — correzioni dell'errore di runtime `MISSING_MESSAGE: provider.deleteConnection` nella pagina dei dettagli del provider -**fix(auth) #372**: Cancella i metadati di errore obsoleti (`errorCode`, `lastErrorType`, `lastErrorSource`) dagli account del fornitore dopo un ripristino autentico: in precedenza, gli account recuperati continuavano a apparire come non riusciti -**correzione (avvio) #369**: Unifica il caricamento di env su `npm run start`, `run-standalone.mjs` ed Electron per rispettare la priorità di `DATA_DIR/.env → ~/.omniroute/.env → ./.env`: impedisce la generazione di un nuovo `STORAGE_ENCRYPTION_KEY` su un database crittografato esistente### 🔧 Code Quality\n\n- Modelli documentati di `result.success` e `response?.ok` in \"auth.ts\" (entrambi intenzionali, ora spiegati)\n- Normalizzato `overridePath?.trim()` in `electron/main.js` per corrispondere a `bootstrap-env.mjs`\n- Aggiunto il commento sull'ordine di unione `preferredEnv` all'avvio di Electron\n\n> Politica di quota dell'account Codex con rotazione automatica, attivazione/disattivazione rapida del livello, modello gpt-5.4 e correzione dell'etichetta di analisi.### ✨ New Features (PRs #366, #367, #368)\n\n-**Politica sulle quote del Codex (PR n. 366)**: la finestra delle quote settimanali/di 5 ore per account viene attivata/disattivata nella dashboard del fornitore. Gli account vengono automaticamente saltati quando le finestre abilitate raggiungono la soglia del 90% e riammessi dopo \"resetAt\". Include \"quotaCache.ts\" con getter di stato senza effetti collaterali. -**Attivazione/disattivazione livello rapido Codex (PR n. 367)**: Dashboard → Impostazioni → Livello di servizio Codex. L'attivazione/disattivazione predefinita inserisce `service_tier: \"flex\"` solo per le richieste Codex, riducendo i costi di circa l'80%. Stack completo: scheda UI + endpoint API + esecutore + traduttore + ripristino all'avvio. -**Modello gpt-5.4 (PR #368)**: aggiunge `cx/gpt-5.4` e `codex/gpt-5.4` al registro del modello Codex. Test di regressione incluso.### 🐛 Bug Fixes\n\n-**correzione n. 356**: i grafici di analisi (fornitore principale, per account, suddivisione dei fornitori) ora mostrano nomi/etichette dei fornitori leggibili dall'uomo anziché ID interni non elaborati per i fornitori compatibili con OpenAI.\n\n> Versione principale: strategia di routing rigorosamente casuale, controlli di accesso tramite chiave API, gruppi di connessione, sincronizzazione dei prezzi esterni e correzioni di bug critici per modelli di pensiero, test combinati e convalida dei nomi degli strumenti.### ✨ New Features (PRs #363 & #365)\n\n-**Strategia di routing rigorosamente casuale**: mazzo shuffle Fisher-Yates con garanzia anti-ripetizione e serializzazione mutex per richieste simultanee. Mazzi indipendenti per combo e per provider. -**Controlli di accesso chiave API**: `allowedConnections` (limita le connessioni che una chiave può utilizzare), `is_active` (abilita/disabilita la chiave con 403), `accessSchedule` (controllo degli accessi basato sul tempo), attiva/disattiva `autoResolve`, rinomina le chiavi tramite PATCH. -**Gruppi di connessione**: connessioni del provider di gruppo per ambiente. Visualizzazione a fisarmonica nella pagina Limiti con persistenza localStorage e commutazione automatica intelligente. -**Sincronizzazione prezzi esterna (LiteLLM)**: risoluzione dei prezzi a 3 livelli (sostituzioni utente → sincronizzato → valori predefiniti). Attivazione tramite `PRICING_SYNC_ENABLED=true`. Strumento MCP `omniroute_sync_pricing`. 23 nuovi test. -**i18n**: 30 lingue aggiornate con strategia strict-random, stringhe di gestione delle chiavi API. pt-BR completamente tradotto.### 🐛 Bug Fixes\n\n-**correzione #355**: timeout di inattività del flusso aumentato da 60 a 300 secondi: impedisce l'interruzione dei modelli di pensiero esteso (claude-opus-4-6, o3, ecc.) durante le lunghe fasi di ragionamento. Configurabile tramite `STREAM_IDLE_TIMEOUT_MS`. -**correzione n. 350**: il test combinato ora ignora `REQUIRE_API_KEY=true` utilizzando l'intestazione interna e utilizza il formato compatibile con OpenAI universalmente. Timeout esteso da 15 a 20 secondi. -**correzione #346**: gli strumenti con `function.name` vuoto (inoltrato da Claude Code) vengono ora filtrati prima che i provider upstream li ricevano, prevenendo errori \"Input[N].name non valido: stringa vuota\".### 🗑️ Closed Issues\n\n-**#341**: sezione Debug rimossa: la sostituzione è `/dashboard/logs` e `/dashboard/health`.\n\n> Supporto API Key Round-Robin per configurazioni di provider multi-chiave e conferma del routing con caratteri jolly e della finestra di quota già in atto.### ✨ New Features\n\n-**Chiave API Round-Robin (T07)**: le connessioni del provider ora possono contenere più chiavi API (Modifica connessione → Chiavi API aggiuntive). Le richieste ruotano in round robin tra chiavi primarie + extra tramite `providerSpecificData.extraApiKeys[]`. Le chiavi vengono mantenute in memoria indicizzate per connessione: non sono necessarie modifiche allo schema del database.### 📝 Already Implemented (confirmed in audit)\n\n-**Wildcard Model Routing (T13)**: `wildcardRouter.ts` con corrispondenza con caratteri jolly in stile glob (`gpt*`, `claude-?-sonnet`, ecc.) è già integrato in `model.ts` con classificazione di specificità. -**Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` fa già avanzare automaticamente la finestra — se `Date.now() > entry.until`, il blocco viene eliminato immediatamente (nessun blocco obsoleto).\n\n> Miglioramento dell'interfaccia utente, aggiunte alla strategia di routing e gestione corretta degli errori per i limiti di utilizzo.### ✨ New Features\n\n-**Strategie di routing Fill-First e P2C**: aggiunti `fill-first` (drenare la quota prima di proseguire) e `p2c` (selezione a bassa latenza Power-of-Two-Choices) al selettore di strategie combinate, con pannelli di guida completi e badge codificati a colori. -**Modelli preimpostati con stack gratuito**: la creazione di una combinazione con il modello Stack gratuito ora riempie automaticamente 7 modelli di provider gratuiti migliori della categoria (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Gli utenti devono semplicemente attivare i fornitori e ottenere una combinazione di $ 0 al mese pronta all'uso. -**Modale combo più ampia**: la modalità Crea/Modifica combo ora utilizza `max-w-4xl` per modificare comodamente combo di grandi dimensioni.### 🐛 Bug Fixes\n\n-**Pagina Limiti HTTP 500 per Codex e GitHub**: `getCodexUsage()` e `getGitHubUsage()` ora restituiscono un messaggio intuitivo quando il provider restituisce 401/403 (token scaduto), invece di generare e causare un errore 500 nella pagina Limiti. -**Falsi positivi del banner di manutenzione**: il banner non mostra più \"Il server non è raggiungibile\" in modo spurio al caricamento della pagina. Risolto il problema chiamando `checkHealth()` immediatamente al montaggio e rimuovendo la chiusura obsoleta di `show`-state. -**Descrizioni comando icona provider**: i pulsanti delle icone Modifica (matita) ed Elimina nella riga di connessione del provider ora dispongono di descrizioni comandi HTML native: tutte e 6 le icone di azione sono ora auto-documentate.\n\n> Numerosi miglioramenti derivanti dall'analisi dei problemi della community, supporto di nuovi provider, correzioni di bug per il tracciamento dei token, routing dei modelli e affidabilità dello streaming.### ✨ New Features\n\n-**Task-Aware Smart Routing (T05)**: selezione automatica del modello in base al tipo di contenuto della richiesta: codifica → deepseek-chat, analisi → gemini-2.5-pro, visione → gpt-4o, riepilogo → gemini-2.5-flash. Configurabile tramite Impostazioni. Nuova API \"GET/PUT/POST /api/settings/task-routing\". -**HuggingFace Provider**: aggiunto HuggingFace Router come provider compatibile con OpenAI con Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini. -**Vertex AI Provider**: aggiunto il provider Vertex AI (Google Cloud) con Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude tramite Vertex. -**Caricamenti di file Playground**: caricamento di audio per la trascrizione, caricamento di immagini per modelli di visione (rilevamento automatico in base al nome del modello), rendering di immagini in linea per risultati di generazione di immagini. -**Feedback visivo sulla selezione del modello**: i modelli già aggiunti nel selettore combinato ora mostrano ✓ badge verde: impedisce la confusione duplicata. -**Compatibilità Qwen (PR n. 352)**: impostazioni aggiornate dell'agente utente e dell'impronta digitale CLI per la compatibilità del provider Qwen. -**Gestione dello stato Round-Robin (PR n. 349)**: logica round-robin migliorata per gestire gli account esclusi e mantenere correttamente lo stato di rotazione. -**Clipboard UX (PR #360)**: operazioni degli appunti rafforzate con fallback per contesti non sicuri; Miglioramenti alla normalizzazione dello strumento Claude.### 🐛 Bug Fixes\n\n-**Correzione n. 302 — OpenAI SDK stream=False elimina tool_calls**: T01 Accetta la negoziazione dell'intestazione non forza più lo streaming quando `body.stream` è esplicitamente \"false\". Causava l'eliminazione silenziosa delle tool_calls durante l'utilizzo di OpenAI Python SDK in modalità non streaming. -**Correzione n.73 — Claude Haiku instradato a OpenAI senza prefisso del provider**: i modelli `claude-*` inviati senza prefisso del provider ora vengono instradati correttamente al provider `antigravity` (antropico). Aggiunta anche l'euristica `gemini-*`/`gemma-*` → `gemini`. -**Correzione #74 — I token contano sempre 0 per lo streaming Antigravity/Claude**: l'evento SSE `message_start` che trasporta `input_tokens` non veniva analizzato da `extractUsage()`, causando la caduta di tutti i conteggi dei token di input. Il monitoraggio dei token di input/output ora funziona correttamente per le risposte in streaming. -**Correzione #180 — Duplicati di importazione di modelli senza feedback**: `ModelSelectModal` ora mostra ✓ un'evidenziazione verde per i modelli già nella combo, rendendo evidente che sono già aggiunti. -**Errori nella generazione di pagine multimediali**: i risultati delle immagini ora vengono visualizzati come tag \"\" invece che come JSON non elaborato. Risultati della trascrizione mostrati come testo leggibile. Gli errori di credenziale mostrano un banner color ambra invece di un errore silenzioso. -**Pulsante di aggiornamento del token sulla pagina del provider**: interfaccia utente di aggiornamento manuale del token aggiunta per i provider OAuth.### 🔧 Improvements\n\n-**Registro del provider**: HuggingFace e Vertex AI aggiunti a `providerRegistry.ts` e `provviders.ts` (frontend). -**Read Cache**: nuovo `src/lib/db/readCache.ts` per un efficiente caching di lettura DB. -**Quota Cache**: cache delle quote migliorata con eliminazione basata su TTL.### 📦 Dependencies\n\n- `dompurificare` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)### 📁 New Files\n\n| File | Scopo |\n| --------------------------------------------- | -------------------------------------------------------------- | ----------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Logica di routing sensibile alle attività (7 tipi di attività) |\n| `src/app/api/settings/task-routing/route.ts` | API di configurazione dell'instradamento delle attività |\n| `src/app/api/providers/[id]/refresh/route.ts` | Aggiornamento manuale del token OAuth |\n| `src/lib/db/readCache.ts` | Cache di lettura DB efficiente |\n| `src/shared/utils/clipboard.ts` | Appunti rinforzati con fallback | ## [2.4.1] - 2026-03-13 |\n\n### 🐛 Fix\n\n-**Modale combo: Stack gratuito visibile e prominente**: il modello Stack gratuito era nascosto (4° nella griglia a 3 colonne). Risolto: spostato nella posizione 1, passato alla griglia 2x2 in modo che tutti e 4 i modelli siano visibili, bordo verde + evidenziazione badge GRATUITO.## [2.4.0] - 2026-03-13\n\n> **Versione principale**: ecosistema Free Stack, revisione del parco giochi di trascrizione, oltre 44 provider, documentazione completa del livello gratuito e miglioramenti dell'interfaccia utente su tutta la linea.### Funzionalità\n\n-**Combo: modello Stack gratuito**— Nuovo quarto modello \"Stack gratuito ($0)\" che utilizza il round robin su Kiro + Qoder + Qwen + Gemini CLI. Suggerisce la combo precostruita a costo zero al primo utilizzo.\n-**Media/Trascrizione: Deepgram come predefinito**— Deepgram (Nova 3, $ 200 gratis) è ora il fornitore di trascrizione predefinito. AssemblyAI ($ 50 gratis) e Groq Whisper (gratuito per sempre) mostrati con badge di credito gratuiti. -**README: sezione \"Inizia gratuitamente\"**: nuova tabella in 5 passaggi README iniziale che mostra come configurare l'IA a costo zero in pochi minuti. -**README: combinazione di trascrizione gratuita**: nuova sezione con suggerimenti per la combinazione Deepgram/AssemblyAI/Groq e dettagli sul credito gratuito per fornitore. -**provviders.ts: flag hasFree**: NVIDIA NIM, Cerebras e Groq contrassegnati con il badge hasFree e freeNote per l'interfaccia utente dei provider. -**i18n: chiavi templateFreeStack**: modello combinato Stack gratuito tradotto e sincronizzato in tutte le 30 lingue.## [2.3.16] - 2026-03-13\n\n### Documentazione\n\n-**README: 44+ Provider**— Aggiornate tutte e 3 le occorrenze di \"36+ provider\" a \"44+\" riflettendo il conteggio effettivo della base di codice (44 provider in provider.ts) -**LEGGIMI: Nuova sezione \"🆓 Modelli gratuiti: cosa ottieni effettivamente\"**- Aggiunta tabella di 7 fornitori con limiti di velocità per modello per: Kiro (Claude illimitato tramite AWS Builder ID), Qoder (5 modelli illimitati), Qwen (4 modelli illimitati), Gemini CLI (180.000/mese), NVIDIA NIM (~40 RPM dev-per sempre), Cerebras (1 milione di tok/giorno / 60.000 TPM), Groq (30 giri/min/14,4K giri/min). Include la raccomandazione combinata \\/usr/bin/bash Ultimate Free Stack. -**README: tabella dei prezzi aggiornata**— Aggiunto Cerebras al livello API KEY, corretto NVIDIA da \"1000 crediti\" a \"dev-forever free\", conteggi e nomi dei modelli Qoder/Qwen aggiornati -**README: modelli Qoder 8→5**(denominati: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2) -**LEGGIMI: modelli Qwen 3→4**(denominati: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)## [2.3.15] - 2026-03-13\n\n### Funzionalità\n\n-**Dashboard Auto-Combo (priorità livello)**: aggiunto \"🏷️ Livello\" come settima etichetta del fattore di punteggio nella visualizzazione della suddivisione dei fattori \"/dashboard/auto-combo\": tutti e 7 i fattori di punteggio dell'Auto-Combo sono ora visibili. -**i18n — sezione autoCombo**: aggiunte 20 nuove chiavi di traduzione per la dashboard Auto-Combo (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, ecc.) a tutti i 30 file di lingua.## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n-**Qoder OAuth (#339)**: ripristinato il valore predefinito valido `clientSecret`: in precedenza era una stringa vuota, che causava \"Credenziali client errate\" a ogni tentativo di connessione. La credenziale pubblica è ora il fallback predefinito (sostituibile tramite `QODER_OAUTH_CLIENT_SECRET` env var). -**Server MITM non trovato (#335)**: `prepublish.mjs` ora compila `src/mitm/*.ts` in JavaScript utilizzando `tsc` prima di copiarlo nel bundle npm. In precedenza venivano copiati solo i file `.ts` grezzi, il che significa che `server.js` non esisteva mai nelle installazioni globali npm/Volta. -**GeminiCLI mancante projectId (#338)**: invece di generare un errore grave 500 quando `projectId` manca dalle credenziali archiviate (ad esempio dopo il riavvio di Docker), OmniRoute ora registra un avviso e tenta la richiesta, restituendo un errore significativo lato provider invece di un arresto anomalo di OmniRoute. -**Mancata corrispondenza della versione di Electron (#323)**: versione `electron/package.json` sincronizzata con `2.3.13` (era `2.0.13`) in modo che la versione binaria del desktop corrisponda al pacchetto npm.### ✨ New Models (#334)\n\n-**Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto` -**Codice**: `gpt5.4`### 🔧 Improvements\n\n-**Tier Scoring (API + validazione)**: aggiunto `tierPriority` (peso `0.05`) allo schema Zod `ScoringWeights` e al percorso API `combos/auto`: il settimo fattore di punteggio è ora completamente accettato dall'API REST e convalidato in input. Il peso della \"stabilità\" è stato modificato da \"0,10\" a \"0,05\" per mantenere la somma totale = \"1,0\".### ✨ New Features\n\n-**Punteggio quota a livelli (combo automatico)**: aggiunto \"tierPriority\" come settimo fattore di punteggio: gli account con livelli Ultra/Pro sono ora preferiti rispetto ai livelli gratuiti quando altri fattori sono uguali. Nuovi campi opzionali \"accountTier\" e \"quotaResetIntervalSecs\" su \"ProviderCandidate\". Aggiornati tutti e 4 i pacchetti modalità (\"spedisci velocemente\", \"risparmia costi\", \"prima la qualità\", \"offline-friendly\"). -**Fallback modello intrafamiliare (T5)**: quando un modello non è disponibile (404/400/403), OmniRoute ora ricorre automaticamente ai modelli fratelli della stessa famiglia prima di restituire un errore (`modelFamilyFallback.ts`). -**Timeout bridge API configurabile**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var consente agli operatori di ottimizzare il timeout del proxy (predefinito 30 secondi). Risolve gli errori 504 sulle risposte upstream lente. (#332) -**Star History**: sostituito il widget star-history.com con starchart.cc (`?variant=adaptive`) in tutti i 30 README: si adatta al tema chiaro/scuro, aggiornamenti in tempo reale.### 🐛 Bug Fixes\n\n-**Auth: prima password**: `INITIAL_PASSWORD` env var viene ora accettato quando si imposta la prima password del dashboard. Utilizza \"timingSafeEqual\" per il confronto in tempo costante, prevenendo attacchi temporali. (#333) -**Troncamento README**: corretto un tag di chiusura `` mancante nella sezione Risoluzione dei problemi che causava a GitHub l'interruzione del rendering di tutto ciò che si trovava sotto (stack tecnico, documenti, roadmap, contributori). -**Installazione pnpm**: rimosso l'override ridondante di `@swc/helpers` da `package.json` che era in conflitto con la dipendenza diretta, causando errori `EOVERRIDE` su pnpm. Aggiunta la configurazione `pnpm.onlyBuiltDependencies`. -**CLI Path Injection (T12)**: aggiunto il validatore `isSafePath()` in `cliRuntime.ts` per bloccare l'attraversamento del percorso e i metacaratteri della shell in `CLI_*_BIN` env vars. -**CI**: rigenerato `package-lock.json` dopo la rimozione dell'override per correggere gli errori `npm ci` sulle azioni GitHub.### 🔧 Improvements\n\n-**Formato di risposta (T1)**: `response_format` (json_schema/json_object) ora inserito come prompt di sistema per Claude, consentendo la compatibilità dell'output strutturato. -**429 tentativi (T2)**: tentativi intra-URL per 429 risposte (2× tentativi con ritardo di 2 secondi) prima di tornare all'URL successivo. -**Intestazioni CLI Gemini (T3)**: aggiunte le intestazioni delle impronte digitali `User-Agent` e `X-Goog-Api-Client` per la compatibilità della CLI Gemini. -**Catalogo prezzi (T9)**: aggiunte le voci di prezzo `deepseek-3.1`, `deepseek-3.2` e `qwen3-coder-next`.### 📁 New Files\n\n| File | Scopo |\n| ------------------------------------------ | ------------------------------------------------------------------- | --------- |\n| `open-sse/services/modelFamilyFallback.ts` | Definizioni di famiglia modello e logica di fallback intrafamiliare | ### Fixed |\n\n-**KiloCode**: timeout del controllo dello stato del kilocode già corretto nella v2.3.11 -**OpenCode**: aggiungi opencode al registro cliRuntime con timeout del controllo dello stato di 15 secondi -**OpenClaw / Cursore**: aumenta il timeout del controllo sanitario a 15 secondi per le varianti ad avvio lento -**VPS**: installa i pacchetti npm droid e openclaw; attiva CLI_EXTRA_PATHS per kiro-cli -**cliRuntime**: aggiunta la registrazione dello strumento opencode e aumento del timeout per continuare## [2.3.11] - 2026-03-12\n\n### Fixed\n\n-**KiloCode Healthcheck**: Aumenta `healthcheckTimeoutMs` da 4000ms a 15000ms — kilocode esegue il rendering di un banner con logo ASCII all'avvio causando un falso `healthcheck_failed` in ambienti lenti/con avvio a freddo## [2.3.10] - 2026-03-12\n\n### Fixed\n\n-**Lint**: risolto l'errore `check:any-budget:t11`: sostituire `as any` con `as Record` in OAuthModal.tsx (3 occorrenze)### Docs\n\n-**CLI-TOOLS.md**: guida completa per tutti gli 11 strumenti CLI (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw) -**i18n**: CLI-TOOLS.md sincronizzato in 30 lingue con titolo tradotto + introduzione## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n-**/v1/completions**: nuovo endpoint legacy di completamenti OpenAI: accetta sia la stringa `prompt` che l'array `messages`, si normalizza automaticamente nel formato chat -**EndpointPage**: ora mostra tutti e 3 i tipi di endpoint compatibili con OpenAI: Completamenti chat, API di risposta e Completamenti legacy -**i18n**: aggiunto `completionsLegacy/completionsLegacyDesc` a 30 file di lingua### Fixed\n\n-**OAuthModal**: corretto `[object Object]` visualizzato su tutti gli errori di connessione OAuth: estrai correttamente `.message` dagli oggetti di risposta all'errore in tutte e 3 le chiamate `throw new Error(data.error)` (scambio, codice dispositivo, autorizzazione)\n\n- Interessa Cline, Codex, GitHub, Qwen, Kiro e tutti gli altri provider OAuth## [2.3.7] - 2026-03-12\n\n### Fixed\n\n-**Cline OAuth**: aggiungi `decodeURIComponent` prima della decodifica base64 in modo che i codici di autenticazione codificati URL dall'URL di callback vengano analizzati correttamente, correggendo gli errori \"codice di autorizzazione non valido o scaduto\" sulle configurazioni remote (IP LAN) -**Cline OAuth**: `mapTokens` ora popola `name = firstName + lastName || email` in modo che gli account Cline mostrino nomi utente reali anziché \"ID account\" -**Nomi di account OAuth**: tutti i flussi di scambio OAuth (scambio, poll, poll-callback) ora normalizzano `name = email` quando manca il nome, quindi ogni account OAuth mostra la propria email come etichetta visualizzata nel dashboard dei provider -**Nomi account OAuth**: rimosso il fallback sequenziale \"Account N\" in `db/providers.ts`: gli account senza email/nome ora utilizzano un'etichetta stabile basata su ID tramite `getAccountDisplayName()` invece di un numero sequenziale che cambia quando gli account vengono eliminati## [2.3.6] - 2026-03-12\n\n### Fixed\n\n-**Batch di test del provider**: corretto lo schema Zod per accettare `providerId: null` (il frontend invia null per le modalità non provider); restituiva erroneamente \"Richiesta non valida\" per tutti i test batch -**Modale test del provider**: corretta la visualizzazione di \"[object Object]\" normalizzando gli oggetti di errore API in stringhe prima del rendering in \"setTestResults\" e \"ProviderTestResultsView\" -**i18n**: Aggiunte le chiavi mancanti `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` a `en.json` -**i18n**: sincronizzate 1111 chiavi mancanti in tutti i 29 file di lingua non inglese utilizzando valori inglesi come fallback## [2.3.5] - 2026-03-11\n\n### Fixed\n\n-**@swc/helpers**: aggiunta la correzione permanente di `postinstall` per copiare `@swc/helpers` nei `node_modules` dell'app standalone: ​​impedisce l'arresto anomalo di MODULE_NOT_FOUND sulle installazioni npm globali## [2.3.4] - 2026-03-10\n\n### Added\n\n- Integrazioni multiple di fornitori e miglioramenti del dashboard\n"}, "d33c0ed1b5e66c2e1d848ebf52928f520e6b3f42": {"t": 1785765404.6763835, "n": 168225, "h": "1eaae8f3e0ada81d", "c": "# Changelog (Italiano)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.5.3] - 2026-04-05\n\n### Fixed\n\n- **Middleware:** Resolved infinite redirect loop on dashboard for fresh instances when requireLogin is disabled.\n\n---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n- **Qoder API Native Integration:** Completely refactored the Qoder Executor to bypass the legacy COSY AES/RSA encryption algorithm, routing directly into the native DashScope OpenAi-compatible URL. Eliminates complex dependencies on Node `crypto` modules while improving stream fidelity.\n- **Resilience Engine Overhaul:** Integrated context overflow graceful fallbacks, proactive OAuth token detection, and empty-content emission prevention (#990).\n- **Context-Optimized Routing Strategy:** Added new intelligent routing capability to natively maximize context windows in automated combo deployments (#990).\n\n### 🐛 Bug Fixes\n\n- **Responses API Stream Corruption:** Fixed deep-cloning corruption where Anthropic/OpenAI translation boundaries stripped `response.` specific SSE prefixes from streaming boundaries (#992).\n- **Claude Cache Passthrough Alignment:** Aligned CC-Compatible cache markers consistently with upstream Client Pass-Through mode preserving prompt caching.\n- **Turbopack Memory Leak:** Pinned Next.js to strict `16.0.10` preventing memory leaks and build staleness from recent upstream Turbopack hashed module regressions (#987).\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **Models.dev Integration:** Integrated models.dev as the authoritative runtime source for model pricing, capabilities, and specifications, overriding hardcoded prices. Includes a settings UI to manage sync intervals, translation strings for all 30 languages, and robust test coverage.\n- **Provider Native Capabilities:** Added support for declaring and checking native API features (e.g. `systemInstructions_supported`) preventing failures by sanitizing invalid roles. Currently configured for Gemini Base and Antigravity OAuth providers.\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Sicurezza\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Funzionalità\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Sicurezza\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicurezza\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicurezza\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Documentazione\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Documentazione\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funzionalità\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funzionalità\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funzionalità\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicurezza\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funzionalità\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funzionalità\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funzionalità\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funzionalità\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funzionalità\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funzionalità\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funzionalità\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funzionalità\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicurezza\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\bany\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funzionalità\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funzionalità\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funzionalità\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funzionalità\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funzionalità\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funzionalità\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Documentazione\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funzionalità\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "b100325fe0e34ff2cbf20eb3e0b78929d25babbf": {"t": 1785765406.4968626, "n": 168080, "h": "08d1d2d6604b0b3d", "c": "# Changelog (Italiano)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n\n## [Unreleased]\n\n---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n- **Qoder API Native Integration:** Completely refactored the Qoder Executor to bypass the legacy COSY AES/RSA encryption algorithm, routing directly into the native DashScope OpenAi-compatible URL. Eliminates complex dependencies on Node `crypto` modules while improving stream fidelity.\n- **Resilience Engine Overhaul:** Integrated context overflow graceful fallbacks, proactive OAuth token detection, and empty-content emission prevention (#990).\n- **Context-Optimized Routing Strategy:** Added new intelligent routing capability to natively maximize context windows in automated combo deployments (#990).\n\n### 🐛 Bug Fixes\n\n- **Responses API Stream Corruption:** Fixed deep-cloning corruption where Anthropic/OpenAI translation boundaries stripped `response.` specific SSE prefixes from streaming boundaries (#992).\n- **Claude Cache Passthrough Alignment:** Aligned CC-Compatible cache markers consistently with upstream Client Pass-Through mode preserving prompt caching.\n- **Turbopack Memory Leak:** Pinned Next.js to strict `16.0.10` preventing memory leaks and build staleness from recent upstream Turbopack hashed module regressions (#987).\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **Models.dev Integration:** Integrated models.dev as the authoritative runtime source for model pricing, capabilities, and specifications, overriding hardcoded prices. Includes a settings UI to manage sync intervals, translation strings for all 30 languages, and robust test coverage.\n- **Provider Native Capabilities:** Added support for declaring and checking native API features (e.g. `systemInstructions_supported`) preventing failures by sanitizing invalid roles. Currently configured for Gemini Base and Antigravity OAuth providers.\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Sicurezza\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Funzionalità\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Sicurezza\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicurezza\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicurezza\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Documentazione\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Documentazione\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funzionalità\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funzionalità\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funzionalità\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicurezza\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funzionalità\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funzionalità\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funzionalità\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funzionalità\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funzionalità\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funzionalità\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funzionalità\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funzionalità\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicurezza\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funzionalità\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funzionalità\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funzionalità\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funzionalità\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funzionalità\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funzionalità\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Documentazione\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funzionalità\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "bd281e5753a872fcae52091f909734e96710f61e": {"t": 1785765409.2849743, "n": 166338, "h": "52c3525e0e1f64a1", "c": "# Changelog (Italiano)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Sicurezza\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Funzionalità\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Sicurezza\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicurezza\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicurezza\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Documentazione\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Documentazione\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funzionalità\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funzionalità\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funzionalità\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicurezza\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funzionalità\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funzionalità\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funzionalità\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funzionalità\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funzionalità\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funzionalità\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funzionalità\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funzionalità\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicurezza\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funzionalità\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funzionalità\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funzionalità\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funzionalità\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funzionalità\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funzionalità\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Documentazione\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funzionalità\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "19f46eb81743cf9992edc6ff7af268a1da79ffe6": {"t": 1785765411.3045745, "n": 165657, "h": "ce0bf027ee73c740", "c": "# Changelog (Italiano)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Sicurezza\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Funzionalità\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Sicurezza\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicurezza\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicurezza\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Documentazione\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Documentazione\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funzionalità\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funzionalità\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funzionalità\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicurezza\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funzionalità\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funzionalità\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funzionalità\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funzionalità\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funzionalità\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funzionalità\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funzionalità\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funzionalità\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicurezza\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funzionalità\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funzionalità\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funzionalità\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funzionalità\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funzionalità\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funzionalità\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Documentazione\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funzionalità\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "bfeb1693d691d7e3e60da1fc1c81b3ccf113c42f": {"t": 1785765413.345935, "n": 151838, "h": "889f1d091031250e", "c": "# Changelog (Italiano)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n### 🛠️ Maintenance\n\n- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.\n\n## [3.4.2] - 2026-04-01\n\n### 🐛 Bug Fixes\n\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.\n\n### 🛠️ Maintenance\n\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicurezza\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicurezza\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Documentazione\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Documentazione\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funzionalità\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funzionalità\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funzionalità\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicurezza\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funzionalità\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funzionalità\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funzionalità\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funzionalità\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funzionalità\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funzionalità\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funzionalità\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funzionalità\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicurezza\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funzionalità\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funzionalità\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funzionalità\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funzionalità\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funzionalità\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funzionalità\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Documentazione\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funzionalità\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "e071393eb5ed2de0eff9eefa7d275cd313b3b40a": {"t": 1785765415.0262241, "n": 143913, "h": "39699c9a48b985fd", "c": "# Changelog (Italiano)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)\n\n---\n\n\n## [Unreleased]\n\n---\n\n## [3.3.9] - 2026-03-31\n\n### 🐛 Bug Fixes\n\n- **Custom Provider Rotation:** Integrated `getRotatingApiKey` internally inside DefaultExecutor, ensuring `extraApiKeys` rotation triggers correctly for custom and compatible upstream providers (#815)\n\n---\n\n## [3.3.8] - 2026-03-30\n\n### Funzionalità\n\n- **Models API Filtering:** Endpoint `/v1/models` now dynamically filters its list based on the permissions tied to the `Authorization: Bearer ` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicurezza\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicurezza\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Documentazione\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Documentazione\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funzionalità\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funzionalità\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funzionalità\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicurezza\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funzionalità\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funzionalità\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funzionalità\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funzionalità\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funzionalità\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funzionalità\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funzionalità\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funzionalità\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicurezza\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funzionalità\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funzionalità\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funzionalità\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funzionalità\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funzionalità\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funzionalità\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Documentazione\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funzionalità\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}}, "docs/i18n/bg/CHANGELOG.md": {"63029ae7eb5118baa91257939233db8fb0aed60b": {"t": 1785746533.6163993, "n": 229419, "h": "bdc70d352d68f718", "c": "# Changelog (Български)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.6.8] — 2026-04-17\n\n### ✨ New Features\n\n- **feat(providers):** Support `xhigh` reasoning tier exclusively on Claude models that expose it (#1356)\n- **feat(providers):** Add CC Compatible connection-level 1M context toggle (#1357)\n- **feat(core):** Add full support for Node.js 24 LTS (Krypton) environments with continuous integration coverage (#1340)\n- **feat(dashboard):** Display Antigravity credit balance in dashboard Limits & Quotas (#1338)\n- **feat(i18n):** Add internationalization support for combo features and dashboard components; sync translations across 31 keys (#1318)\n- **feat(providers):** Add Claude Opus 4.7 to Claude Code OAuth models natively with extended context and caching (#1347)\n- **feat(core):** Add stopSequences support and expand tool definitions to include Google Search capabilities\n- **feat(auth):** Enforce dashboard session authentication on all management API routes, preventing unauthenticated access to configuration endpoints\n- **feat(runtime):** Add hot-reloadable guardrails and model diagnostics for real-time rule evaluation without restarts\n- **feat(core):** Add payload rules, tag-based routing, and scheduled budget systems for fine-grained request governance\n- **feat(providers):** Expose Antigravity preview model aliases and Gemini CLI onboarding flow for first-time setup\n- **feat(antigravity):** Add client model aliases and thoughtSignature bypass modes for Antigravity OAuth connections\n- **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations\n- **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages\n\n### Сигурност\n\n- **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns\n- **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353)\n- **fix(providers):** Resolve Codex token refresh race condition via mutex `getAccessToken` preventing `refresh_token_reused` Auth0 revocations\n\n### 🔧 Maintenance & Architecture\n\n- **refactor(core):** Split CLI runner and decouple migration engine for extensibility (#1358)\n- **refactor(audit):** Rewire audit dashboard from dead in-memory `configAudit` store to live SQLite `audit_log` table — 331+ hidden compliance entries now visible in `/dashboard/audit`\n- **build(deps):** Bump `softprops/action-gh-release` from v2 to v3\n- **ci:** Bump GitHub Actions CI node-version to Node.js 24 natively\n- **fix(types):** Resolve TypeScript compilation errors in `claudeCodeCompatible.ts` (type predicates, `cache_control` index access) and `proxyFetch.ts` (`signal` nullability)\n\n### 🐛 Bug Fixes\n\n- **fix(context):** Scale reserved context tokens dynamically using a 15% sliding window for smaller models\n- **test(core):** Replace unit test with integration test for proactive context compression to align with isolated runner rules (#1378)\n- **fix(services):** Pass origin provider to refreshWithRetry to avoid tripping the generic \"unknown\" circuit breaker (fixes Codex accounts erroneously disabling)\n- **fix(db):** Prevent native module ABI load crashes from assuming database corruption and skipping databases\n- **fix(db):** Increase mass-migration threshold from 5 to 50 pending migrations to protect legacy users upgrading node\n- **fix(db):** Prevent migration runner safety aborts from triggering on fresh `DATA_DIR` installations by detecting new databases (#1328)\n- **fix(mcp):** Checkpoint and close MCP audit SQLite database safely on process signals and shutdown (#1348)\n- **fix(mcp):** Fully decouple MCP audit SQLite connection caching via globalThis to fix unhandled teardown in standalone Next.js chunks (#1349)\n- **fix(cli):** Avoid creating app router directory during postinstall initialization on non-built source trees (#1351)\n- **fix(codex):** Correctly translate `system` role to `developer` in input array to unlock GPT-5 automatic prompt caching (#1346)\n- **fix(core):** Pass client headers to executor in chatCore (#1335)\n- **fix(providers):** Separate test batch calls and ignore unknown connections\n- **fix(providers):** Add grok-web SSO cookie validation handler (#1334)\n- **fix(db):** Preserve key_value settings (dashboard passwords, saved aliases) across DB heuristic recreation cycles (#1333)\n- **fix(routing):** Allow combo fallback to cascade context overflow 400 errors instead of immediate aborts (#1331)\n- **fix(core):** Resolve thinking leaks, consecutive roles, and missing thoughtSignatures for Antigravity translator (#1316)\n- **fix(translator):** Only apply thoughtSignature to the first `functionCall` part in Gemini parallel tool calls, preventing duplicate signatures\n- **fix(providers):** Default to batch testing execution blocks for web, search, and audio modalities to prevent connection timeouts\n- **fix(cli):** Resolve Node 22 TS entrypoint incompatibility by using esbuild compilation (#1315)\n- **fix(chat):** Preserve max_output_tokens for Responses API targets in chatCore sanitization (#1313)\n- **fix(api):** API Manager usage stats showing 0 for all registered keys (#1310)\n- **fix(api):** Support image-only models in catalog and allow authless search providers to bypass validation requirements\n- **fix(routes):** Require prompts for media generation requests (`/images`, `/videos`, `/music`), returning 400 on missing payloads\n- **fix(dashboard):** Auto-scroll ActivityHeatmap to show current date (#1309)\n- **fix(dashboard):** Restore horizontal layout with `w-max` wrapper in heatmap components\n- **fix(i18n):** Update `nodeIncompatibleHint` to recommend Node 24 LTS across all 31 languages\n- **fix(i18n):** Add Chinese i18n support to remaining dashboard components (`Loading.tsx`, `DataTable`, etc.)\n- **fix(requestLogger):** Add missing `cacheSource` and `tps` columns to i18n log detail views\n\n## [3.6.6] — 2026-04-15\n\n### ✨ New Features\n\n- **feat(storage):** Add database backup cleanup controls, UI management, and customizable retention period env vars (#1304)\n- **feat(providers):** Add Freepik Pikaso image generation provider with support for cookie/subscription-based auth modes (#1277)\n- **feat(providers): Add Perplexity Web (Session) Provider** — Routes through Perplexity's internal SSE API using a session cookie, giving native proxy access without separate API costs to GPT-5.4, Claude Opus, Gemini 3.1 Pro, and Nemotron via preferences mapping (#1289)\n- **feat(api): Sync Tokens & V1 WebSocket Bridge** — Dedicated sync token storage, issuance, revocation, and bundle download routes backed by stable config bundle versioning with ETag support. Exposes `/v1/ws` WebSocket upgrade route and a custom Next.js server bridge (`scripts/v1-ws-bridge.mjs`) so OpenAI-compatible WebSocket traffic can be proxied through the gateway. Compliance auditing expanded with structured metadata, pagination, request context, auth/provider credential events, and SSRF-blocked validation logging. New migrations: `024_create_sync_tokens.sql`. New modules: `syncTokens.ts`, `src/lib/sync/bundle.ts`, `src/lib/sync/tokens.ts`, `src/lib/ws/handshake.ts`, `src/lib/apiBridgeServer.ts`, `src/lib/compliance/providerAudit.ts`.\n- **feat(models): GLM Thinking Preset & Hybrid Token Counting** — GLM Thinking (`glmt`) registered as a first-class provider preset with shared GLM model metadata, pricing, per-connection usage sync, dashboard support, and `maxTokens: 65536 / thinkingBudgetTokens: 24576` request defaults with 900s extended timeout. Provider-side `/messages/count_tokens` endpoint used when a Claude-compatible upstream supports it; gracefully falls back to estimation on missing models, missing credentials, or upstream failures. Startup seeding of default model aliases (`src/lib/modelAliasSeed.ts`) normalizes common cross-proxy model dialects so canonical slash-based model IDs are not misrouted. New file `open-sse/config/glmProvider.ts`.\n- **feat(core): Hardened Outbound Provider Calls & Cooldown Retries** — Guarded outbound fetch helpers (`src/shared/network/safeOutboundFetch.ts`, `src/shared/network/outboundUrlGuard.ts`) blocking private/local URLs with configurable retry, timeout normalisation, and route-level status propagation for provider validation and model discovery. Cooldown-aware chat retries (`src/sse/services/cooldownAwareRetry.ts`) with configurable `requestRetry` and `maxRetryIntervalSec` settings and model-scoped cooldown responses. Improved rate-limit learning from headers and error bodies so short upstream lockouts can recover automatically. Runtime environment validation (`src/lib/env/runtimeEnv.ts`) checks env at startup. Pollinations now requires an API key. Antigravity and Codex header handling aligned via `open-sse/config/antigravityUpstream.ts` and `open-sse/config/codexClient.ts`. Gemini tool names restored in translated responses; synthetic Claude text block injected when upstream SSE completes empty.\n- **feat(logs):** Add TPS (Tokens Per Second) metric to log details modal metadata grid (#1182)\n- **feat(memory+skills):** Full-featured Memory & Skills systems with FTS5 SQLite search, dynamic UI pagination, backend observability, and extensive test coverage (#1228)\n- **feat(bailian-quota):** Add Alibaba Coding Plan quota monitoring, multi-window quota extraction, and UI credential validation (#1235)\n- **feat(storage): Call Log Storage Refactor** — Extracted heavy request/response JSON payloads from the core SQLite database (`storage.sqlite`) into filesystem artifacts stored within `DATA_DIR/call_logs`. This massively reduces WAL bloat and eliminates `SQLITE_FULL` crashes on high-traffic nodes (#1307).\n- **feat(providers): Add Grok Web (Subscription) Provider** — Routes through the xAI web interface for subscription users via cookie session mapping (#1295).\n- **feat(api): Advanced Media Support** — Extends OpenAI generic proxy layer to natively support `image`, `embeddings`, `audio-transcriptions`, and `audio-speech` workflows (#1297).\n- **feat(cli-tools): Qwen Code CLI Integration** — Full integration for Qwen Code local execution mapping, model resolution, and dynamic API key fetching (#1266, #1263).\n- **feat(oauth):** Supports `cursor-agent` CLI as a native Cursor credential source alongside the standard configuration (#1258).\n- **feat(models):** Custom and imported models now merge correctly into filter lists for all available global providers (#1191).\n\n### 🐛 Bug Fixes\n\n- **fix(providers):** match correct endpoint api.xiaomimimo.com for Xiaomi MiMo (#1303)\n- **fix(core):** strip provider alias routing prefix from payload for custom endpoints to fix Azure OpenAI 400 errors (#1261)\n- **fix(core):** ProxyFetch Undici dispatcher automatically bypasses LAN/local addresses, preventing fetch failures on internal OpenRouter requests (#1254)\n- **fix(core):** Gemini thought stream signature detection upgraded to use native part.thought boolean, preventing reasoning text leaks (#1298)\n- **deps:** bump hono from 4.12.12 to 4.12.14 to resolve CVE SSR HTML injection vulnerability (#1306, #59)\n- **deps:** update dompurify to 3.4.0 in frontend overrides mitigating XSS HTML Injection (CVE-XYZ / Dependabot #60)\n- **test:** Disable SQLite automatic backups during continuous integration (CI) tests to resolve E2E timeout issues limiting runner scaling (#24481475058)\n- **feat(core): Proactive Context Compression** — `chatCore` now proactively compresses oversized message contexts before hitting upstream providers to dramatically reduce `context_length_exceeded` errors. Employs binary-search message pruning with structural integrity guarantees tracking explicit `tool_use` boundaries ensuring truncated tool inputs drop paired outputs appropriately (#1292, #1293)\n\n- **fix(cli):** Resolve codex routing config parsing by strictly quoting section keys array, enforcing responses wire_api with fallback, and standardizing select-model button positioning mirroring Claude UI\n- **fix(providers):** Correct Lobehub provider icons rendering by removing unsupported local references ensuring local SVG/PNG fallback mechanism invokes natively\n- **fix(db):** Implement Database migration tracking safety abort safeguards (pre-migration backups via `VACUUM INTO` and mass renumbering warnings) to protect existing database structures on startup upgrades (#1281)\n- **fix(dashboard):** Cleaned up target codex `config.toml` structure preventing recursive section rendering by enforcing quotes on section dot paths and mapping correct UI `OMNIROUTE_API_KEY` names.\n- **fix(mcp):** Add dedicated explicit timeout constraint overrides for search handlers (#1280)\n- **fix(crypto):** Add validation guard to encryption layer to surface clear UI errors when cryptographic environment variables are missing, replacing raw Node.js TypeErrors. Legacy env vars `OMNIROUTE_CRYPT_KEY` and `OMNIROUTE_API_KEY_BASE64` now also accepted as fallbacks (#1165)\n- **fix(providers):** Update Pollinations provider definition to require API keys and specify their new limited pollen/hour free tier (#1177)\n- **Streaming `\\n\\n` Artifact Fix (#1211):** Changed `` tag-stripping regex from `?` to `*` quantifier across `combo.ts`, `comboAgentMiddleware.ts`, and `contextHandoff.ts` to greedily strip all accumulated JSON-escaped newline sequences surrounding the tag. This prevents literal `\\n\\n` prefix artifacts from appearing in consumer streaming responses\n- **E2E Combo Test Locator:** Fixed Playwright strict-mode violation in `combo-unification.spec.ts` by replacing ambiguous `getByRole` locator with a compound filter locator for the \"All\" strategy tab\n- **fix(cc-compatible):** Trim beta flags and preserve cache passthrough for third-party HTTP proxy compatibility (#1230)\n- **fix(providers):** Update Xiaomi MiMo endpoints to the live token-plan, migrating away from dead API URLs (#1238)\n- **fix:** Forward client `x-initiator` header to GitHub Copilot upstream to accurately distinguish agent vs user turns (#1227)\n- **fix:** Resolve backlog bugs including streaming edge cases, unhandled rejections, and quota parse failures (#1206, #1220, #1231, #1175, #1187, #1218, #1202)\n- **fix(tests):** Resolve memory migration and skills route pagination bugs arising from PR overlaps\n- **fix(i18n):** Add missing Chinese i18n support to dashboard components (`DataTable`, `EmptyState`, etc), update `en.json/zh-CN.json` routing keys, and natively resolve JSX defaults via `next-intl` (#1274)\n\n### 🔧 Internal Improvements\n\n- **Compliance Audit Expansion:** `src/lib/compliance/index.ts` expanded with structured metadata, pagination support, request context enrichment, and new `providerAudit.ts` module logging auth and provider credential events, SSRF-blocked validation attempts, and provider CRUD operations\n- **Config Sync Bundle:** `src/lib/sync/bundle.ts` exports `buildConfigBundle()` generating a versioned JSON snapshot of settings, provider connections, nodes, model aliases, combos, and API keys (passwords redacted) with ETag support for bandwidth-efficient polling\n- **Codex Client Constants:** Centralized `CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT_PLATFORM`, and pattern-validated env overrides (`CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT`) in `open-sse/config/codexClient.ts`\n- **Antigravity Upstream Constants:** `open-sse/config/antigravityUpstream.ts` consolidates all Antigravity base URLs and model/fetchAvailableModels discovery path builders\n- **Model Alias Seed:** `src/lib/modelAliasSeed.ts` seeds 30+ cross-proxy model dialect aliases (e.g. `openai/gpt-5` → `gpt-5`, `anthropic/claude-opus-4-6` → `cc/claude-opus-4-6`) at startup via idempotent `upsert`\n- **Test Coverage:** 15+ new unit test suites covering sync routes, WebSocket bridge, compliance index, GLM provider config, cooldown-aware retry, safe outbound fetch, stream utilities, Codex executor, provider validation branches, model cross-proxy compatibility, and model alias seeding\n- **TypeScript Migration:** Finalized migration of remaining JS tests (`proxy-load` and `testFromFile`) to TypeScript ES modules, ensuring a fully synchronized TS stack.\n- **Reliability & Resilience:** Added exponential backoff to `models.dev` auto-sync to combat transient network failures, raised interval floor to 1 hour, and added LKGP debug logging for enhanced observability during routing. (#1286)\n\n---\n\n## [3.6.5] — 2026-04-13\n\n### ✨ New Features\n\n- **Antigravity AI Credits Fallback:** Automatically retries with `GOOGLE_ONE_AI` credit injection when free-tier quota is exhausted. Per-account credit balance (5-hour TTL) is cached from SSE `remainingCredits` and exposed as a numeric badge in the Provider Usage dashboard (#1190 — thanks @sFaxsy)\n- **Claude Code Native Parity:** Full header/body signing parity with the Claude Code 2.1.87 OAuth client — CCH xxHash64 body signing with singleton WASM initialization promise (fixing race conditions), dynamic per-request fingerprint, bidirectional TitleCase ↔ lowercase tool name remapping (14 tools), API constraint enforcement (`temperature=1` for thinking, max 4 `cache_control` blocks, auto-inject ephemeral on last user message), and optional ZWJ obfuscation. Wired into `BaseExecutor` for automatic CCH signing on all `anthropic-compatible-cc-*` providers and into `chatCore` for synchronous parity pipeline steps (#1188 — thanks @RaviTharuma)\n- **Per-Connection Codex Defaults:** Codex Fast Service Tier and Reasoning Effort settings are now per-connection instead of a single global toggle. Existing connections are migrated automatically on startup via an idempotent backfill migration (#1176 — thanks @rdself)\n- **Cursor Usage Dashboard:** New `getCursorUsage()` fetches quotas from Cursor's `/api/usage`, `/api/auth/me`, and `/api/subscription` endpoints. Displays standard requests, on-demand usage, and per-plan limits (Free/Pro/Business/Team). Client version bumped to `3.1.0` and `x-cursor-user-agent` header added for parity\n- **Database Health Check System:** Automated periodic SQLite integrity monitoring via `runDbHealthCheck()` — detects orphan quota/domain rows, broken combo references, stale snapshots, and invalid JSON state. Runs every 6 hours (configurable via `OMNIROUTE_DB_HEALTHCHECK_INTERVAL_MS`), with auto-repair and pre-repair backup. Exposed as **MCP tool #18** (`omniroute_db_health_check`) with Zod schemas and `autoRepair` option. Dashboard panel in Health page with status card, issue count, repaired count, and one-click repair button\n- **OpenAI Responses API Store Opt-In:** Per-connection `openaiStoreEnabled` flag controls whether the `store` field is preserved or forced to `false` on Codex Responses API requests. When enabled, `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields are round-tripped through the Chat Completions → Responses translation, enabling multi-turn context caching on supported providers\n- **Email Privacy Toggle (Combos Page):** Global email visibility toggle (`EmailPrivacyToggle`) added to the Combos page header with responsive layout, tooltip guidance, and per-connection label masking via `pickDisplayValue()`. All combo builder options, provider connection lists, and quota screens now respect the global privacy state from `emailPrivacyStore`\n- **skills.sh Integration:** Added `skills.sh` as an external skill provider. Users can now search, browse, and install agent skills directly from a new \"skills.sh\" tab in the Skills dashboard. Includes backend API resolvers, frontend implementation with search/install states, and a dedicated unit test suite (#1223 — thanks @RaviTharuma)\n- **Stabilization Settings:** Added persistence support for `lkgpEnabled` and `backgroundDegradation` settings, integrated into `instrumentation-node.ts` for improved lifecycle awareness (#1212)\n- **xxhash-wasm dependency:** Added `xxhash-wasm@^1.1.0` for CCH signing (xxHash64 with seed `0x6E52736AC806831E`)\n\n### 🐛 Bug Fixes\n\n- **Codex `stream: false` via Combo (ALL_ACCOUNTS_INACTIVE):** Fixed a critical bug where Codex combos returned `ALL_ACCOUNTS_INACTIVE` or empty content when the client sent `stream: false`. Root cause was triple: (1) `CodexExecutor.transformRequest()` mutated `body.stream` in-place to `true`, contaminating the combo's quality check which skipped validation thinking it was streaming; (2) the non-stream SSE parser used the wrong format (Chat Completions instead of Responses API) for Codex SSE output; (3) combo quality validation read the mutated `body.stream` instead of the client's original intent. Fixed by: cloning the body via `structuredClone()` in CodexExecutor, detecting Codex/Responses SSE format in the non-stream fallback path (with auto-translation back to Chat Completions), and capturing `clientRequestedStream` before the combo loop\n- **Gemini CLI Tool Schema Rejection:** Fixed 400 Bad Request errors from the Google API by strictly filtering non-standard vendor extensions (starting with `x-`) and `deprecated` fields from tool parameter schemas (#1206)\n- **SOCKS5 Proxy Interop (Node.js 22):** Resolved `invalid onRequestStart method` crashes caused by `undici` version mismatches between dispatchers and the built-in fetch. Hardened `proxyFetch.ts` to strictly use the library's fetch implementation for custom dispatchers (#1219)\n- **Search Cache Coalescing with TTL=0:** Fixed a bug where providers configured with `cacheTTLMs: 0` (caching explicitly disabled) still had concurrent requests coalesced and returned `{ cached: true }`. Now each call gets its own independent upstream fetch (#1178 — thanks @sjhddh)\n- **Antigravity Credit Cache Alignment (PR #1190):** Reconciled `accountId` derivation between `AntigravityExecutor.collectStreamToResponse` and `getAntigravityUsage` to use consistent cache keys (`email || sub || \"unknown\"`). Previously, SSE-parsed credit balances could be written under a different key than the one read by the usage dashboard, causing stale/missing credit badges\n- **Non-streaming reasoning_content Duplication:** Fixed clients rendering duplicated reasoning panels when both `reasoning_content` and visible `content` were present in non-streaming responses. `responseSanitizer` now strips `reasoning_content` from messages that already have visible text content, preserving it only for reasoning-only messages\n- **Streaming Regression Fix:** Hardened the `sanitize` TransformStream in the combo engine to strip both literal and JSON-escaped newline sequences, eliminating leading `\\n\\n` prefixes in assistant responses (#1211)\n- **Gemini Empty Choice Fix:** Ensured initial assistant deltas always include an empty `content: \"\"` string to satisfy strict OpenAI client requirements and prevent empty choice responses in tools (#1209)\n- **Gemini Tools Sanitizer Deduplication:** Extracted shared tool conversion logic into `buildGeminiTools()` helper (`geminiToolsSanitizer.ts`), eliminating duplicate implementations between `openai-to-gemini.ts` and `claude-to-gemini.ts`. The new helper correctly handles `web_search` / `web_search_preview` tool types by emitting `googleSearch` tools with priority over function declarations\n- **Qwen/Qoder Thinking+Tool_Choice Conflict:** Added `sanitizeQwenThinkingToolChoice()` to both `DefaultExecutor` (for Qwen provider) and `QoderExecutor` to prevent provider-side 400 errors when clients send `tool_choice` alongside thinking/reasoning parameters that are mutually exclusive upstream\n- **API Key Deletion Orphan Cleanup:** Deleting an API key now also removes associated `domain_budgets` and `domain_cost_history` rows, preventing orphan data accumulation\n- **CC-compatible test assertion:** Fixed pre-existing test that expected no `cache_control` on system blocks — the billing header system block now carries `cache_control: { type: \"ephemeral\" }` per PR #1188 design\n- **Codex Combo Smoke Test False Positives:** Fixed combo tests incorrectly reporting `ERROR` for valid Codex streaming responses when `response.output` is empty but text deltas were emitted. The summary now falls back to accumulated delta text (#1176 — thanks @rdself)\n- **Electron Builder Version Mismatch:** Fixed Electron desktop startup failures on Windows packaged builds caused by native modules (`better-sqlite3`) being under `app.asar.unpacked` while helpers were in `app/node_modules`. `resolveServerNodePath()` now merges both locations with deduplication and existence checks (#1172 — thanks @backryun)\n\n### 🔧 Internal Improvements\n\n- **SSE Parser: Responses API Non-Stream Conversion:** Added full `parseSSEToResponsesOutput()` implementation in `sseParser.ts` (255+ lines) — reconstructs complete Responses API objects from SSE event streams, handling `response.output_text.delta/done`, `response.reasoning_summary_text.delta/done`, `response.function_call_arguments.delta/done`, and terminal events. Used by the new chatCore non-stream fallback path for Codex\n- **Cursor Executor Version Sync:** Updated Cursor client User-Agent to `3.1.0` and centralized version constants (`CURSOR_CLIENT_VERSION`, `CURSOR_USER_AGENT`) for consistent fingerprinting across executor, usage fetcher, and OAuth flows\n- **Responses API Translator Parity:** `convertResponsesApiFormat()` now accepts credentials and passes them through to the translator, enabling store-aware field propagation. Round-trip preservation of `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields\n- **Provider Schema Validation:** Added `openaiStoreEnabled` boolean validation to `providerSpecificData` Zod schema\n- **Combo Error Response Normalization:** Empty combo targets now return 404 (`comboModelNotFoundResponse`) instead of generic 503, improving client-side error differentiation\n- **Dependency Updates:** Bumps `typescript-eslint` to `8.58.2` (dev), `axios` to `1.15.0` (prod), and `next` to `16.2.2` (prod) (#1224, #1225)\n\n### ⚠️ Breaking Changes\n\n- **`DELETE /api/settings/codex-service-tier` removed:** This endpoint no longer exists. Codex Service Tier configuration has moved to per-connection `providerSpecificData.requestDefaults`. Existing connections are migrated automatically on first startup after upgrade. Any external scripts or integrations that call this endpoint should be updated — use `PUT /api/providers/:id` with `providerSpecificData.requestDefaults.serviceTier` instead (#1176).\n- **CCH signing on CC-compatible providers:** All requests to `anthropic-compatible-cc-*` providers now include an xxHash64 integrity token (`cch=...`) in the billing header. Providers that do not validate CCH will ignore it (no behavioral change), but any custom middleware inspecting the billing header should expect a 5-character hex token instead of the `00000` placeholder\n\n---\n\n## [3.6.4] — 2026-04-12\n\n### ✨ New Features\n\n- **Combo Builder v2 (Wizard UI):** Completely redesigned the combo creation/editing interface as a multi-stage wizard with stages: Basics → Steps → Strategy → Review. The builder fetches provider, model, and connection metadata via a new `GET /api/combos/builder/options` endpoint, enabling precise provider/model/account selection with duplicate detection and automatic next-connection suggestion. Heavy UI components (`ModelSelectModal`, `ProxyConfigModal`, `ModelRoutingSection`) are now lazily loaded via `next/dynamic` for faster initial page render\n- **Combo Step Architecture (Schema v2):** Introduced a structured step model (`ComboModelStep`, `ComboRefStep`) replacing the legacy flat string/object combo entries. Steps carry explicit `id`, `kind`, `providerId`, `connectionId`, `weight`, and `label` fields, enabling pinned-account routing, cross-combo references, and per-step metrics. All combo CRUD operations normalize entries through the new `src/lib/combos/steps.ts` module. Zod schemas updated with `comboModelStepInputSchema` and `comboRefStepInputSchema` unions\n- **Composite Tiers System:** Added tiered model routing via `config.compositeTiers` — each tier maps a named stage to a specific combo step with optional fallback chains. Includes comprehensive validation (`src/lib/combos/compositeTiers.ts`) ensuring step existence, preventing circular fallback, and validating default tier references. Zod schema enforcement blocks composite tiers on global defaults (concrete combos only)\n- **Model Capabilities Registry:** Created `src/lib/modelCapabilities.ts` providing `getResolvedModelCapabilities()` — a unified resolver that merges static specs, provider registry data, and live-synced capabilities into a single `ResolvedModelCapabilities` object covering tool calling, reasoning, vision, context window, thinking budget, modalities, and model lifecycle metadata\n- **Observability Module:** Extracted health and telemetry payload construction into `src/lib/monitoring/observability.ts` with `buildHealthPayload()`, `buildTelemetryPayload()`, and `buildSessionsSummary()` builders. The health endpoint now returns session activity, quota monitor status, and per-provider breakdowns alongside existing system metrics\n- **Session & Quota Monitor Dashboard:** Added live Session Activity and Quota Monitors panels to the Health dashboard, showing active session counts, sticky-bound sessions, per-API-key breakdowns, and top session details alongside quota monitor alerting/exhausted/error status with per-provider drill-down\n- **Combo Health Per-Target Analytics:** The combo-health API now resolves per-target metrics using the new `resolveNestedComboTargets()` function, providing step-level success rates, latency, and historical usage breakdowns per execution key — enabling per-account, per-connection health visibility\n- **Auto-Combo → Combos Unification:** Merged the separate `/dashboard/auto-combo` page into the main `/dashboard/combos` page. Auto/LKGP combos are now managed alongside all other combos with a new strategy filter tabs system (All / Intelligent / Deterministic). The old auto-combo route redirects to `/dashboard/combos?filter=intelligent`. Removed the `auto-combo` sidebar entry, consolidating navigation into the single `Combos` item\n- **Intelligent Routing Panel (`IntelligentComboPanel`):** New inline panel (371 lines) within the combos page that shows real-time provider scores, 6-factor scoring breakdown (quota, health, cost, latency, task fitness, stability), mode pack selector, incident mode status, and excluded providers for `auto`/`lkgp` combos — replacing the former standalone auto-combo dashboard\n- **Builder Intelligent Step (`BuilderIntelligentStep`):** New conditional wizard step (280 lines) that appears in the Builder v2 flow only when `strategy=auto` or `strategy=lkgp` is selected. Exposes candidate pool selection, mode pack presets, router sub-strategy selector, exploration rate slider, budget cap, and collapsible advanced scoring weights configuration\n- **Intelligent Routing Module (`intelligentRouting.ts`):** Extracted strategy categorization and filtering logic into a dedicated shared module (210 lines) with `getStrategyCategory()`, `isIntelligentStrategy()`, `filterCombosByStrategyCategory()`, `normalizeIntelligentRoutingFilter()`, and `normalizeIntelligentRoutingConfig()` utility functions\n- **LKGP Standalone Strategy:** Implemented `lkgp` (Last Known Good Provider) as a fully functional standalone combo strategy. Previously, `lkgp` as a combo strategy silently fell through to `priority` ordering — the LKGP lookup only ran inside the `auto` engine. Now `strategy: \"lkgp\"` correctly queries the LKGP state, moves the last successful provider to the top of the target list, and saves the LKGP state after each successful request. Falls back to priority ordering when no LKGP state exists\n- **Unified Routing Rules & Model Aliases:** Consolidated the routing rules and model alias management controls into the Settings page, reducing fragmentation across the dashboard\n\n### ⚡ Performance\n\n- **Middleware Lazy Loading:** Refactored `src/proxy.ts` to lazy-import `apiAuth`, `db/settings`, and `modelSyncScheduler` modules, reducing middleware cold-start overhead. Added inline `isPublicApiRoute()` to avoid loading the full auth module for public routes\n- **E2E Auth Bypass:** Added `NEXT_PUBLIC_OMNIROUTE_E2E_MODE` environment flag to bypass authentication gates for dashboard and management API routes during Playwright E2E test runs\n\n### 🐛 Bug Fixes\n\n- **P2C Credential Selection:** Implemented Power-of-Two-Choices (P2C) connection scoring in `src/sse/services/auth.ts` with quota headroom awareness, error/recency penalties, and forced/excluded connection support. The new `getProviderCredentialsWithQuotaPreflight()` function integrates quota preflight checks directly into credential selection, eliminating the separate Codex-only preflight path\n- **Fixed-Account Combo Steps:** Combo steps with explicit `connectionId` now correctly bypass provider-level model cooldowns and circuit breakers, preventing a single account failure from blocking pinned-connection routing for the same model\n- **Combo Metrics Per-Target Tracking:** Extended `comboMetrics.ts` to track `byTarget` metrics keyed by execution path, recording per-step `provider`, `providerId`, `connectionId`, and `label` alongside existing per-model aggregates\n- **Call Logs Schema Expansion:** Added `requested_model`, `request_type`, `tokens_cache_read`, `tokens_cache_creation`, `tokens_reasoning`, `combo_step_id`, and `combo_execution_key` columns to `call_logs` with auto-migration. Added composite index `idx_cl_combo_target` for efficient per-target historical queries\n- **Quota Monitor Enrichment:** Expanded `quotaMonitor.ts` with full lifecycle state tracking (`status`, `startedAt`, `lastPolledAt`, `consecutiveFailures`, `totalPolls`, `totalAlerts`), ISO-formatted snapshots via `getQuotaMonitorSnapshots()`, and sorted summary via `getQuotaMonitorSummary()`\n- **Codex Quota Fetcher Hardening:** Improved `codexQuotaFetcher.ts` with safer connection registration and quota fetch error handling\n- **LKGP Save Refactored to Async/Await:** Replaced fire-and-forget `.then()` chain for LKGP persistence after successful combo routing with proper `async/await` + `try/catch`, preventing unhandled promise rejections and ensuring LKGP state is reliably saved before the response is returned\n- **Duplicate `auto` in Combo Strategy Schema:** Removed duplicate `\"auto\"` entry from `comboStrategySchema` (was listed on both line 104 and 108). Harmless to Zod runtime but cleaned up to avoid confusion. Schema now has exactly 13 unique strategy values\n- **Legacy Combo Refs Normalization:** Fixed combo step normalization to preserve legacy string combo references during CRUD operations, preventing data loss when editing combos created before the v2 step architecture\n\n### Сигурност\n\n- **Auth Bypass on Backup Routes (Critical):** Added `isAuthenticated` guards to `/api/db-backups/exportAll` (full database export) and `/api/db-backups` (list, create, and restore backups) — both were previously accessible without authentication\n- **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency\n- **API Key Secret Hardening:** Removed the hardcoded `\"omniroute-default-insecure-api-key-secret\"` fallback from `apiKey.ts` — the function now fails fast if `API_KEY_SECRET` is unset, relying on the startup validator to auto-generate it\n- **NPM Tarball Leak Fix:** Added `app/.env*` to `.npmignore` to prevent the working `.env` file from being shipped inside the npm tarball distribution\n- **Electron Builder CVE Fix:** Bumped `electron-builder` to 26.8.1 to resolve `tar` CVEs in the desktop build pipeline\n\n### 🔧 Maintenance & Infrastructure\n\n- **DB Migration 021:** Added `combo_call_log_targets` migration for `combo_step_id` and `combo_execution_key` columns in call_logs\n- **Combo CRUD Normalization:** `db/combos.ts` now normalizes all stored combo entries through the step normalization pipeline on read, ensuring consistent step IDs and kind annotations regardless of when the combo was created\n- **Playwright Config:** Updated Playwright configuration and `run-next-playwright.mjs` script for improved E2E test orchestration\n- **Build Script:** Updated `build-next-isolated.mjs` with additional reliability improvements\n- **Auto-Combo UI Cleanup:** Deleted `AutoComboModal.tsx` (161 lines), replaced `auto-combo/page.tsx` (478→5 lines) with a server-side redirect to `/dashboard/combos?filter=intelligent`\n- **Sidebar Consolidation:** Removed `\"auto-combo\"` from `HIDEABLE_SIDEBAR_ITEM_IDS` and `PRIMARY_SIDEBAR_ITEMS` — `normalizeHiddenSidebarItems()` silently discards any stale `\"auto-combo\"` entries in user settings\n- **Schema Cleanup:** Removed obsolete `createAutoComboSchema` from `schemas.ts`. Exported `comboStrategySchema` for direct use in test and filter modules\n- **A2A Agent Card Update:** Renamed skill ID from `auto-combo` to `intelligent-routing` with updated description referencing the unified combos dashboard\n- **Builder Draft Refactor:** Extended `builderDraft.ts` with dynamic stage list generation via `getComboBuilderStages()` and `isIntelligentBuilderStrategy()`. Stage navigation (`getNextComboBuilderStage`, `getPreviousComboBuilderStage`, `canAccessComboBuilderStage`) now accepts options to conditionally include/skip the `intelligent` wizard step\n- **i18n Consolidation:** Removed the standalone `\"autoCombo\"` i18n block (22 keys) from all 30 language files. Migrated keys into the `\"combos\"` block with new additions for filter tabs, intelligent panel, and builder step labels\n\n### 🧪 Tests\n\n- **16 New Test Suites:** Added comprehensive test coverage including:\n - `combo-builder-draft.test.mjs` (186 lines) — Builder draft step construction and validation\n - `combo-builder-options-route.test.mjs` (228 lines) — Builder options API endpoint\n - `combo-health-route.test.mjs` (266 lines) — Combo health analytics with per-target metrics\n - `combo-routes-composite-tiers.test.mjs` (157 lines) — Composite tiers API integration\n - `composite-tiers-validation.test.mjs` (131 lines) — Composite tier validation rules\n - `db-combos-crud.test.mjs` — Combo CRUD with step normalization\n - `db-core-init.test.mjs` (129 lines) — DB initialization and column migrations\n - `model-capabilities-registry.test.mjs` (105 lines) — Model capabilities resolution\n - `observability-payloads.test.mjs` (165 lines) — Health/telemetry payload construction\n - `openapi-spec-route.test.mjs` — OpenAPI spec generation\n - `proxy-e2e-mode.test.mjs` (74 lines) — E2E mode auth bypass\n - `quota-monitor.test.mjs` — Quota monitor lifecycle state\n - `run-next-playwright.test.mjs` (119 lines) — Playwright runner script\n - `sse-auth.test.mjs` (154 lines) — P2C credential selection and quota preflight\n - `telemetry-summary-route.test.mjs` (35 lines) — Telemetry summary endpoint\n - Plus updates to 12 existing test files for compatibility with new step architecture\n- **Auto-Combo Unification Tests:**\n - `autocombo-unification.test.mjs` (156 lines) — Strategy categorization, schema deduplication, sidebar cleanup, and routing strategies metadata validation\n - `combo-unification.spec.ts` (189 lines) — Playwright E2E tests for filter tabs, intelligent panel rendering, redirect from old route, sidebar entry removal, and Builder v2 intelligent step flow\n - 3 new LKGP standalone tests in `combo-routing-engine.test.mjs` — Validates LKGP provider prioritization, fallback to priority when no state exists, and LKGP state persistence after successful requests\n - Updated `combo-builder-draft.test.mjs` with intelligent stage navigation tests\n - Updated `sidebar-visibility.test.mjs` to reflect `auto-combo` removal\n\n---\n\n## [3.6.3] — 2026-04-11\n\n### ✨ New Features\n\n- **OpenAI-Compatible Loose Validation:** Empty API keys can now be naturally submitted and saved for any `openai-compatible-*` providers (e.g. Pollinations, localized routes) directly in the UI instead of blocking save actions (#1152)\n- **Cloudflare Configuration:** Updated the provider schema and UI integration for Cloudflare AI to officially expose and support the backend `accountId` field securely without overrides (#1150)\n\n### 🐛 Bug Fixes\n\n- **Vertex JSON Validation Crash:** Prevented `invalid character in header` crashes inside the `/validate` endpoint by creating a native authentication parser that correctly handles Google Identity Service Account JSON flows prior to pinging endpoints (#1153)\n- **Extraneous Payload Rejection:** Globally prevented upstream `400 Bad Request` execution crashes by stripping the non-standard `prompt_cache_retention` attribute forcibly attached by Cursor/Cline IDE engines when targeting strict OpenAI/Anthropic routes (#1154)\n- **Reasoning Content Drop:** Prevented pure reasoning packets, common in advanced fallback models like DeepSeek, from being aborted mid-stream by explicitly adjusting the `Empty Content (502)` circuit breakers to acknowledge `reasoning_content` states as valid (#1155)\n- **Desktop Windows Build Crash:** Fixed `better_sqlite3.node is not a valid Win32 application` preventing OmniRoute Desktop from launching on Windows by properly removing the ABI-mismatched sqlite cache from Next.js standalone and falling back to the cross-compiled Electron equivalent during packager build steps (#1163)\n- **Login Visual Security:** Removed the raw fallback hash dump that artificially rendered underneath the login modal in Docker instances missing `OMNIROUTE_API_KEY_BASE64` flags (#1148)\n\n### 🔧 Maintenance & Dependencies\n\n- **Dependabot Updates:** Safely bumped GitHub Actions `docker/build-push-action` to v7 and `actions/download-artifact` to v8\n- **Electron Updates:** Upgraded desktop wrapper core to Electron `41.2.0` and `electron-builder` to `26.8.1`, incorporating essential V8/Chromium security patches\n- **NPM Package Groups:** Updated `production` and `development` NPM groups to securely handle minor audit warnings and keep toolchains modern\n- **CI/CD Reliability:** Fixed persistent `Snyk` token-absence failures on automated pull requests by appropriately bypassing on dependabot actions\n\n## [3.6.2] — 2026-04-11\n\n### ✨ New Features\n\n- **33 New API Key Providers:** Massive provider expansion adding DeepInfra, Vercel AI Gateway, Lambda AI, SambaNova, nScale, OVHcloud AI, Baseten, PublicAI, Moonshot AI, Meta Llama API, v0 (Vercel), Morph, Featherless AI, FriendliAI, LlamaGate, Galadriel, Weights & Biases Inference, Volcengine, AI21 Labs, Venice.ai, Codestral, Upstage, Maritalk, Xiaomi MiMo, Inference.net, NanoGPT, Predibase, Bytez, Heroku AI, Databricks, Snowflake Cortex, and GigaChat (Sber). OmniRoute now supports **100+ providers** (4 Free + 8 OAuth + 91 API Key + Custom compatible)\n- **Global Email Privacy Toggle:** Added a persistent eye-icon toggle button across all dashboard pages (Providers, Usage Limits, Playground) that reveals or hides masked email addresses. Toggle state is stored in localStorage and synced globally via Zustand store\n- **Documentation Refresh:** Updated README, ARCHITECTURE, FEATURES, AGENTS.md, and API_REFERENCE for v3.6.2 with accurate provider counts (100+), new executor list, and system API documentation\n- **Uninstall Guide:** Created comprehensive `docs/UNINSTALL.md` covering clean uninstallation for all deployment methods (npm, Docker, Electron, source)\n\n### 🐛 Bug Fixes\n\n- **PDF Attachments:** Unlocked deep string object parsing (`geminiHelper`) ensuring Gemini translation successfully passes complex PDF payloads from OpenAI-compatible streams without dropping them silently (#993)\n- **SkillsMP Engine:** Corrected object extraction path mappings inside the API router to fix UI marketplace rendering under Docker/Standalone Node isolated deployments (#988)\n\n---\n\n## [3.6.1] — 2026-04-10\n\n### ✨ New Features\n\n- **OAuth Env Repair Action:** Added a \"Repair env\" button to the OAuth Providers dashboard that detects and restores missing OAuth client IDs from `.env.example` — with timestamped backup and append-only safety. Includes full 33-language i18n support and sanitized API responses (#1116, by @yart)\n\n### 🐛 Bug Fixes\n\n- **i18n: Missing Provider Keys:** Added missing `filterModels`, `modelsActive`, `showModel`, `hideModel` keys across all 32 locale files, fixing runtime `MISSING_MESSAGE` errors in the providers UI. Also cleaned up duplicate keys in `en.json` (#1111, by @rilham97)\n- **GPT-5.4 Routing:** Added missing `targetFormat: \"openai-responses\"` to `gpt-5.4` and `gpt-5.4-mini` models in both the Codex and GitHub Copilot providers, fixing `[400]: model not accessible via /chat/completions` errors (#1114, by @ask33r)\n\n---\n\n## [3.6.0] — 2026-04-10\n\n### ✨ New Features & Analytics\n\n- **Combo Smoke Test:** Raised the default token budget to 2048 to prevent truncation of thinking models during preflight checks, and fully randomized the arithmetic probe prompt to bypass deterministic caching from upstream relays (#1105)\n\n### 🐛 Bug Fixes & Compliance\n\n- **DB Bloat / Row Limits:** Added `CALL_LOGS_TABLE_MAX_ROWS` and `PROXY_LOGS_TABLE_MAX_ROWS` (default: 100,000) to the backend DB compliance cleaner to prevent runaway SQLite growth. Limits are enforced automatically on the TTL cycle (#1104, fixes #1101)\n- **HTML Error Handling:** The router now correctly identifies unexpected HTML responses (e.g. ``) sent by upstream providers (like Azure/Copilot) instead of throwing obscure `Unexpected token '<'` JSON parse errors, bubbling up a clean 502 Bad Gateway (#1104, fixes #1066)\n- **Android/Termux SQLite Native Support:** `better-sqlite3` is now correctly built from source with cross-compilation flags in ARM64 local Termux deployments without failing on missing prebuilt binaries (#1107)\n\n---\n\n## [3.5.9] — 2026-04-09\n\n### ✨ New Features\n\n- **Persistent Combo Ordering:** Drag combo cards by handle to reorder them in the dashboard; order is persisted to SQLite via a new `sort_order` column and `POST /api/combos/reorder` endpoint. Includes DB migration `020_combo_sort_order.sql` and JSON import preservation (#1095)\n- **Sidebar Group Reorder:** Moved \"Logs\" before \"Health\" in the System section and \"Limits & Quotas\" after \"Cache\" in the Primary section for a more logical navigation flow (#1095)\n\n### 🐛 Bug Fixes\n\n- **Stream Failure Surfacing:** Upstream `response.failed` events (e.g. Codex rate-limit errors) are now properly surfaced as non-200 errors instead of being silently swallowed as empty 200 OK streams. Rate-limit failures return HTTP 429 (#1098, closes #1093)\n- **Upstream Model Preservation:** The Responses-to-OpenAI stream translator now preserves the actual upstream model (e.g. `gpt-5.4`) instead of hardcoding a `gpt-4` fallback (#1098, closes #1094)\n- **Docker EXDEV Fix:** `build-next-isolated.mjs` now falls back from `fs.rename()` to `cp/rm` when Docker buildx raises `EXDEV` (cross-device link), unblocking the Docker image publish workflow (#1097)\n- **macOS CLI Path Resolution:** `cliRuntime.ts` resolves symlink parents with `fs.realpath()` to handle macOS `/var` → `/private/var` chains, preventing false `symlink_escape` rejections (#1097)\n- **Request Log Token Layout:** Split token badges into separate Input (Total In, Cache Read, Cache Write) and Output (Total Out, Reasoning) groups for clearer readability; renamed \"Time\" label to \"Completed Time\" (#1096)\n\n---\n\n## [3.5.8] — 2026-04-09\n\n### ✨ New Features & Analytics\n\n- **Analytics Layout Redesign:** Replaced flat metrics with a responsive `CompactStatGrid`, grouping data visually across sections (#1089)\n\n### 🐛 Bug Fixes\n\n- **Build Core:** Force Turbopack cleanup via Prepbulish script to prevent Next.js 16 app/ routing conflicts on runtime.\n- **Provider Quarantine:** Introduces model/provider circuit-breakers with adaptive TTL exponential backoff for recurring upstream errors (#1090)\n- **Oauth Keep-Alive:** Safely protects authenticated active accounts against spontaneous dropping from router due to transient token refresh failures (#1085)\n\n### 🔒 Security & Maintenance\n\n- **Dependabot:** bumped axios from 1.14.0 to 1.15.0 addressing SSRF flags (#1088)\n\n---\n\n## [3.5.7] — 2026-04-09\n\n### 🐛 Bug Fixes & Security\n\n- **Turbopack Standalone Chunks:** Fixed a critical bug in `scripts/prepublish.mjs` where Turbopack chunks missing from the `.next/standalone` trace resulted in a `500 ChunkLoadError` (e.g., `_not-found` page crash) during production deployments via NPM or Docker. Standalone chunks are now explicitly copied and correctly stripped of Turbopack hashes.\n\n---\n\n## [3.5.6] — 2026-04-09\n\n### ✨ New Features\n\n- **Email Privacy Masking:** OAuth account emails are now masked in the provider dashboard (e.g. `di*****@g****.com`) to prevent accidental exposure when sharing screenshots. Full address visible on hover via `title` attribute (#1025).\n- **OpenRouter & GitHub in Embedding/Image Registries:** OpenRouter (3 embedding models, 4 image models) and GitHub Models (2 embedding models via Azure inference) are now first-class entries in the provider registries, enabling their use for `/v1/embeddings` and `/v1/images/generations` (#960).\n- **Model Visibility Toggle & Search Filter:** The provider page model list now includes a real-time search/filter bar and a per-model visibility toggle (👁 icon). Hidden models are grayed out and excluded from the `/v1/models` catalog. An active-count badge (`N/M active`) shows at a glance how many models are enabled (#750).\n- **Chinese Localization (zh-CN):** Added missing translations for Context Relay, Memory, LKGP, and Models.dev sync features, while standardizing terminology across the application (#1079).\n- **Environment Auto-Sync:** Added `sync-env.mjs` to auto-generate and append `.env` from `.env.example` during installation, automatically generating cryptographic secrets on first run.\n- **Source Mode Dashboard Update:** Fixed real-time Source (git-checkout) updating in the dashboard, enabling secure, real-time update pipelines for non-NPM installations.\n\n### 🐛 Bug Fixes & Security\n\n- **Hardcoded Secret Cleanup:** Removed 12 hardcoded OAuth credential fallbacks from the source code, forcing secure reliance on environment variables and resolving static analysis security alerts.\n- **Next.js Security Patch:** Bumped `next` from 16.2.2 to 16.2.3 to resolve critical RSC deserialization RCE vulnerability (SNYK-JS-NEXT-15954202).\n- **Memory/Cache UI Crash:** Added null-safety guards (`?? 0`) to `.toLocaleString()` calls in Memory and Cache dashboard pages, preventing `TypeError` crashes when database tables are empty or contain null numeric values (#1083).\n- **WebSearch tool_choice Translation:** Fixed OpenAI-to-Claude translator dropping `tool_choice` objects with `type: \"function\"` as-is, which Claude rejects. Now properly maps all OpenAI `tool_choice` variants (`function`, `required`, `none`) to Claude-compatible format (`tool`, `any`, `auto`), fixing \"Did 0 searches\" in Claude Code WebSearch (#1072).\n- **Provider Validation baseUrl Override:** Added `baseUrl` passthrough from frontend validation requests to the backend validation endpoint. Chinese-site users of Alibaba Coding Plan (bailian-coding-plan) can now validate API keys against their custom Base URL instead of always hitting the international endpoint (#1078).\n- **Minimax Auth Header:** Switched Minimax provider from `x-api-key` to `Authorization: Bearer` header format, matching the current API spec (#1076).\n- **Native Fetch Fallback:** Added graceful fallback to native `fetch` when the `undici` dispatcher fails, improving resilience in environments where undici is unavailable (#1054).\n- **EPIPE Flood Fix:** Added circuit-breaker logic to prevent EPIPE errors from creating a feedback loop that fills logs at GB/s (#1006).\n- **Qoder PAT Validation:** Improved Qoder Personal Access Token validation with actionable error messages that guide users to the correct token format (#966).\n- **CI/CD Pipeline:** Fixed `check:docs-sync` failure by syncing OpenAPI version to 3.5.6 and finalizing CHANGELOG release heading. Commented out `DATA_DIR` in `.env.example` to prevent E2E test failures in CI runners lacking root permissions.\n\n### 🌍 i18n\n\n- **Auto Language Generation (CI):** Added CI pipeline to auto-generate missing language files and strings via `feat(CI,i18n)` workflow, covering 30+ locales (#1071).\n\n---\n\n## [3.5.5] — 2026-04-08\n\n### ✨ New Features\n\n- **Node.js 24 Compatibility Warning:** Added a proactive version incompatibility warning on the login page to guide users to the stable Node.js 22 LTS, preventing native sqlite binding crashes.\n- **Context Relay Combo Strategy:** Added the new `context-relay` combo strategy with priority-style routing, structured handoff summary generation once quota usage reaches the warning threshold, and handoff injection after the next real account switch.\n- **Global Context Relay Defaults:** Added global Settings defaults plus combo-level configuration for `handoffThreshold`, `handoffModel`, and `handoffProviders`, so new or unconfigured combos can inherit the feature consistently.\n\n### 🐛 Bug Fixes\n\n- **Proxy Connection Healthchecks:** Applied proxy resolution per connection in the sweeping loop (`tokenHealthCheck.ts`) and global provider validation sweeps, resolving Node 22 bypass and improving proxy stability (#1051, #1056, #1061).\n- **Security Vulnerability Remediation:** Resolved multiple CodeQL scanning alerts including SSRF in model sync, insecure randomness in web crypto (`generateSessionId`), and incomplete URL sanitization.\n- **Context Relay Typing & Synchronization:** Reverted out-of-scope test breakages and resolved `handoffProvider` and response `input` extraction payload typing.\n- **Legacy OpenAI-Compatible Responses Routing:** Fixed legacy/imported OpenAI-compatible providers (for example `openai-compatible-sp-openai`) incorrectly routing Chat Completions traffic to `/chat/completions` when the real provider node was configured as `apiType: \"responses\"`. OmniRoute now treats `providerSpecificData.apiType` as authoritative across routing, executors, and translator tools, avoiding false empty-content failures during combo/provider smoke tests (#1069).\n- **Gemini PDF Attachment Integration:** Fixed payload generation and format for parsing `inline_data` and generic base64 sources for deep Gemini PDF routing (#993, #1021).\n- **Vercel AI SDK Fallbacks:** Mapped `max_output_tokens` to `max_tokens` for strict OpenAI-compatible providers, resolving errors from standard AI agents and frameworks (#994).\n- **External Auth & UI Reliability:** Handled null `state` failures in Cline OAuth exchange (#1016), added 3rd-party 400 error patterns to combo fallback (#1024), and resolved desktop sidebar layout and popover overflows (#1039, #1001).\n- **Context Relay In-Flight Deduplication:** Prevented duplicate handoff generation for the same session/combo while an earlier summary request is still in flight.\n- **Context Relay Provider Gating:** Aligned runtime behavior with configuration so explicit `handoffProviders` exclusions, including an empty array, now disable handoff generation as expected.\n\n### 🛠️ Maintenance & Dependabot\n\n- **Updated Sub-dependencies:** Bumped `hono` to `4.12.12` and `@hono/node-server` to `1.19.13` to patch critical security gaps (#1063, #1064, #1067, #1068).\n\n### Документация\n\n- **Documentation Synchronization:** Updated system documentation (README, Architecture, Features, Tools, Troubleshooting) and synced `i18n` configurations to match the v3.5.5 context relay patterns and proxy troubleshooting steps.\n- **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance.\n\n---\n\n## [3.5.4] — 2026-04-07\n\n### ✨ New Features\n\n- **Detailed Token Tracking:** Added granular token breakdown columns (cache read, cache write, reasoning) to call logs with proper null vs zero distinction. Includes DB migration 018 and 5-label UI display per provider capability (#1017 — thanks @rdself).\n- **Legacy JSON Config Import/Export:** Restored JSON-based settings export and import for migration from legacy 9router configurations. Security-hardened with Zero-Trust redaction of passwords and `requireLogin` fields, and automatic pre-import database backups (#1012 — thanks @luandiasrj).\n- **Non-Stream Aliases:** Added API support for explicit non-streaming aliases (`non_stream`, `disable_stream`, `disable_streaming`, `streaming=false`), normalized at the boundary before provider translation (#1036 — thanks @wlfonseca).\n- **Russian Dashboard Localization:** Comprehensive Russian translation for the dashboard UI, including fixes for 2 Ukrainian locale keys (#1003 — thanks @mercs2910).\n\n### 🐛 Bug Fixes\n\n- **Anthropic Streaming Input Undercount:** Fixed a critical bug where Anthropic streaming `prompt_tokens` only reported non-cached tokens (e.g., `in=3` when actual total was 113,616). Cache tokens are now summed into prompt_tokens during streaming (#1017).\n- **Built-in Responses API Tool Types:** Preserved built-in Responses API tools (`web_search`, `file_search`, `computer`, `code_interpreter`, `image_generation`) from being silently stripped by the empty-name tool filter — these tools carry no `.name` field (#1014 — thanks @rdself).\n- **Cursor/Codex Responses Compatibility:** Fixed empty output in Cursor when using Codex models by hoisting system input items to `instructions`, sanitizing invalid tool names, and detecting Responses-format payloads on chat/completions endpoint (#1002 — thanks @mercs2910).\n- **OAuth Token Expiry Display:** Fixed OAuth connections showing \"expired\" badge even with valid tokens by reading `tokenExpiresAt` (updated on refresh) instead of `expiresAt` (original grant timestamp) (#1032 — thanks @tombii).\n- **Codex Fast-Tier Copy:** Corrected dashboard settings copy from `service_tier=fast` to `service_tier=priority`, matching the actual Codex wire format (#1045 — thanks @kfiramar).\n- **macOS Desktop App Startup:** Stabilized packaged macOS app launch by excluding desktop artifacts from the standalone bundle and improving launch path detection (#1004 — thanks @mercs2910).\n- **macOS Sidebar Layout:** Fixed macOS traffic light overlap, sidebar spacing, and button overflow in the Electron desktop app (#1001 — thanks @mercs2910).\n\n### ⚡ Performance\n\n- **Analytics Page Load:** Dramatically reduced analytics page load times (30s→1-2s for 50K entries) via date-filtered DB queries, parallel `Promise.all()` cost calculations, and merged 6 COUNT queries into a single CASE WHEN aggregate (#1038 — thanks @oyi77).\n\n### 🔒 Security & Dependencies\n\n- **Node Base Image:** Upgraded Docker base from `22-bookworm-slim` to `22.22.2-trixie-slim` (#1011 — Snyk).\n- **Production Dependencies:** Bumped 5 production dependencies (#1044 — Dependabot).\n- **Vite:** Bumped from 8.0.3 to 8.0.5 (#1031 — Dependabot).\n- **Development Dependencies:** Bumped 4 development dependencies (#1030 — Dependabot).\n\n### 🧪 Tests\n\n- **Token Accounting Tests:** Added 18 new unit tests covering detailed token breakdown, null vs zero semantics, per-provider token extraction, and Anthropic streaming input fix (#1017).\n- **Built-in Tool Tests:** Added 3 new test cases for built-in Responses API tool type preservation (#1014).\n- **ChatCore Sanitization:** Updated sanitization tests to accommodate Responses format detection (PR #1002) and built-in tool preservation (PR #1014).\n\n### 🛠️ Maintenance\n\n- **PR Workflow:** Updated `/review-prs` workflow to merge PRs into the release branch (`release/vX.Y.Z`) instead of directly into `main`, ensuring proper pre-release staging.\n\n### Coverage\n\n- **2537 tests, 2532 passing** — Statement coverage: 91.95%, Branch coverage: 78.79%, Function coverage: 93.19%\n\n## [3.5.3] - 2026-04-07\n\n### Сигурност\n\n- **Vulnerabilities:** Fully remediated 12 High-Severity CodeQL vulnerabilities by migrating from Math.random to `crypto.randomUUID()`, wrapping SSE injection points with aggressive backslash escaping, sanitizing trailing HTTP fragments, and enforcing rigid SSRF HTTP verification schemes across internal routes.\n- **Dependencies:** Upgraded Next.js to `^16.2.2` and Vite to `>=8.0.5` resolving critical DoS, arbitrary file reads and CSRF vectors in the build/server environments.\n\n### Fixed\n\n- **E2E Stability:** Eliminated extreme CI unreliability and transient test timeouts (Playwright) by propagating internal standalone `_next/static` assets properly and refactoring deep UI interactions inside defensive `expect().toPass()` loops.\n- **Middleware:** Resolved infinite redirect loop on dashboard for fresh instances when requireLogin is disabled.\n- **Core Fallbacks:** Preserved primary failure contexts and enhanced Edge-case error handling pipelines across chat and fallback loops.\n- **Proxy/Hooks:** Optimized local git hooks, normalized token coverage endpoints into `/coverage`, and guarded GLM region lookups.\n\n### 🛠️ Maintenance\n\n- **CI/CD Stabilization:** Prevented random GitHub Runner freezes by decoupling sharded processes, adjusting test concurrencies, unref-ing active connections on server teardown, and strictly capping job timeout durations.\n\n### Документация\n\n- **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned).\n\n### Coverage\n\n- **Testing:** Consolidated the workspace test coverage framework hitting 92.1% statement line coverage, with new rigid unit-tests matching API key policies and tool scopes.\n\n---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n- **Qoder API Native Integration:** Completely refactored the Qoder Executor to bypass the legacy COSY AES/RSA encryption algorithm, routing directly into the native DashScope OpenAi-compatible URL. Eliminates complex dependencies on Node `crypto` modules while improving stream fidelity.\n- **Resilience Engine Overhaul:** Integrated context overflow graceful fallbacks, proactive OAuth token detection, and empty-content emission prevention (#990).\n- **Context-Optimized Routing Strategy:** Added new intelligent routing capability to natively maximize context windows in automated combo deployments (#990).\n\n### 🐛 Bug Fixes\n\n- **Responses API Stream Corruption:** Fixed deep-cloning corruption where Anthropic/OpenAI translation boundaries stripped `response.` specific SSE prefixes from streaming boundaries (#992).\n- **Claude Cache Passthrough Alignment:** Aligned CC-Compatible cache markers consistently with upstream Client Pass-Through mode preserving prompt caching.\n- **Turbopack Memory Leak:** Pinned Next.js to strict `16.0.10` preventing memory leaks and build staleness from recent upstream Turbopack hashed module regressions (#987).\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **Models.dev Integration:** Integrated models.dev as the authoritative runtime source for model pricing, capabilities, and specifications, overriding hardcoded prices. Includes a settings UI to manage sync intervals, translation strings for all 30 languages, and robust test coverage.\n- **Provider Native Capabilities:** Added support for declaring and checking native API features (e.g. `systemInstructions_supported`) preventing failures by sanitizing invalid roles. Currently configured for Gemini Base and Antigravity OAuth providers.\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Сигурност\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Функции\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Сигурност\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Сигурност\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Сигурност\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Документация\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Документация\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Функции\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Функции\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Функции\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Сигурност\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Функции\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Функции\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Функции\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Функции\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Функции\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Функции\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Функции\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Функции\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Сигурност\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\bany\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Функции\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Функции\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Функции\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Функции\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Функции\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Функции\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Документация\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Функции\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "e5c4e450c0cd597c2de3d9dde1d74b572c0a6bb3": {"t": 1785765398.1215875, "n": 229419, "h": "bdc70d352d68f718", "c": "# Changelog (Български)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.6.8] — 2026-04-17\n\n### ✨ New Features\n\n- **feat(providers):** Support `xhigh` reasoning tier exclusively on Claude models that expose it (#1356)\n- **feat(providers):** Add CC Compatible connection-level 1M context toggle (#1357)\n- **feat(core):** Add full support for Node.js 24 LTS (Krypton) environments with continuous integration coverage (#1340)\n- **feat(dashboard):** Display Antigravity credit balance in dashboard Limits & Quotas (#1338)\n- **feat(i18n):** Add internationalization support for combo features and dashboard components; sync translations across 31 keys (#1318)\n- **feat(providers):** Add Claude Opus 4.7 to Claude Code OAuth models natively with extended context and caching (#1347)\n- **feat(core):** Add stopSequences support and expand tool definitions to include Google Search capabilities\n- **feat(auth):** Enforce dashboard session authentication on all management API routes, preventing unauthenticated access to configuration endpoints\n- **feat(runtime):** Add hot-reloadable guardrails and model diagnostics for real-time rule evaluation without restarts\n- **feat(core):** Add payload rules, tag-based routing, and scheduled budget systems for fine-grained request governance\n- **feat(providers):** Expose Antigravity preview model aliases and Gemini CLI onboarding flow for first-time setup\n- **feat(antigravity):** Add client model aliases and thoughtSignature bypass modes for Antigravity OAuth connections\n- **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations\n- **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages\n\n### Сигурност\n\n- **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns\n- **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353)\n- **fix(providers):** Resolve Codex token refresh race condition via mutex `getAccessToken` preventing `refresh_token_reused` Auth0 revocations\n\n### 🔧 Maintenance & Architecture\n\n- **refactor(core):** Split CLI runner and decouple migration engine for extensibility (#1358)\n- **refactor(audit):** Rewire audit dashboard from dead in-memory `configAudit` store to live SQLite `audit_log` table — 331+ hidden compliance entries now visible in `/dashboard/audit`\n- **build(deps):** Bump `softprops/action-gh-release` from v2 to v3\n- **ci:** Bump GitHub Actions CI node-version to Node.js 24 natively\n- **fix(types):** Resolve TypeScript compilation errors in `claudeCodeCompatible.ts` (type predicates, `cache_control` index access) and `proxyFetch.ts` (`signal` nullability)\n\n### 🐛 Bug Fixes\n\n- **fix(context):** Scale reserved context tokens dynamically using a 15% sliding window for smaller models\n- **test(core):** Replace unit test with integration test for proactive context compression to align with isolated runner rules (#1378)\n- **fix(services):** Pass origin provider to refreshWithRetry to avoid tripping the generic \"unknown\" circuit breaker (fixes Codex accounts erroneously disabling)\n- **fix(db):** Prevent native module ABI load crashes from assuming database corruption and skipping databases\n- **fix(db):** Increase mass-migration threshold from 5 to 50 pending migrations to protect legacy users upgrading node\n- **fix(db):** Prevent migration runner safety aborts from triggering on fresh `DATA_DIR` installations by detecting new databases (#1328)\n- **fix(mcp):** Checkpoint and close MCP audit SQLite database safely on process signals and shutdown (#1348)\n- **fix(mcp):** Fully decouple MCP audit SQLite connection caching via globalThis to fix unhandled teardown in standalone Next.js chunks (#1349)\n- **fix(cli):** Avoid creating app router directory during postinstall initialization on non-built source trees (#1351)\n- **fix(codex):** Correctly translate `system` role to `developer` in input array to unlock GPT-5 automatic prompt caching (#1346)\n- **fix(core):** Pass client headers to executor in chatCore (#1335)\n- **fix(providers):** Separate test batch calls and ignore unknown connections\n- **fix(providers):** Add grok-web SSO cookie validation handler (#1334)\n- **fix(db):** Preserve key_value settings (dashboard passwords, saved aliases) across DB heuristic recreation cycles (#1333)\n- **fix(routing):** Allow combo fallback to cascade context overflow 400 errors instead of immediate aborts (#1331)\n- **fix(core):** Resolve thinking leaks, consecutive roles, and missing thoughtSignatures for Antigravity translator (#1316)\n- **fix(translator):** Only apply thoughtSignature to the first `functionCall` part in Gemini parallel tool calls, preventing duplicate signatures\n- **fix(providers):** Default to batch testing execution blocks for web, search, and audio modalities to prevent connection timeouts\n- **fix(cli):** Resolve Node 22 TS entrypoint incompatibility by using esbuild compilation (#1315)\n- **fix(chat):** Preserve max_output_tokens for Responses API targets in chatCore sanitization (#1313)\n- **fix(api):** API Manager usage stats showing 0 for all registered keys (#1310)\n- **fix(api):** Support image-only models in catalog and allow authless search providers to bypass validation requirements\n- **fix(routes):** Require prompts for media generation requests (`/images`, `/videos`, `/music`), returning 400 on missing payloads\n- **fix(dashboard):** Auto-scroll ActivityHeatmap to show current date (#1309)\n- **fix(dashboard):** Restore horizontal layout with `w-max` wrapper in heatmap components\n- **fix(i18n):** Update `nodeIncompatibleHint` to recommend Node 24 LTS across all 31 languages\n- **fix(i18n):** Add Chinese i18n support to remaining dashboard components (`Loading.tsx`, `DataTable`, etc.)\n- **fix(requestLogger):** Add missing `cacheSource` and `tps` columns to i18n log detail views\n\n## [3.6.6] — 2026-04-15\n\n### ✨ New Features\n\n- **feat(storage):** Add database backup cleanup controls, UI management, and customizable retention period env vars (#1304)\n- **feat(providers):** Add Freepik Pikaso image generation provider with support for cookie/subscription-based auth modes (#1277)\n- **feat(providers): Add Perplexity Web (Session) Provider** — Routes through Perplexity's internal SSE API using a session cookie, giving native proxy access without separate API costs to GPT-5.4, Claude Opus, Gemini 3.1 Pro, and Nemotron via preferences mapping (#1289)\n- **feat(api): Sync Tokens & V1 WebSocket Bridge** — Dedicated sync token storage, issuance, revocation, and bundle download routes backed by stable config bundle versioning with ETag support. Exposes `/v1/ws` WebSocket upgrade route and a custom Next.js server bridge (`scripts/v1-ws-bridge.mjs`) so OpenAI-compatible WebSocket traffic can be proxied through the gateway. Compliance auditing expanded with structured metadata, pagination, request context, auth/provider credential events, and SSRF-blocked validation logging. New migrations: `024_create_sync_tokens.sql`. New modules: `syncTokens.ts`, `src/lib/sync/bundle.ts`, `src/lib/sync/tokens.ts`, `src/lib/ws/handshake.ts`, `src/lib/apiBridgeServer.ts`, `src/lib/compliance/providerAudit.ts`.\n- **feat(models): GLM Thinking Preset & Hybrid Token Counting** — GLM Thinking (`glmt`) registered as a first-class provider preset with shared GLM model metadata, pricing, per-connection usage sync, dashboard support, and `maxTokens: 65536 / thinkingBudgetTokens: 24576` request defaults with 900s extended timeout. Provider-side `/messages/count_tokens` endpoint used when a Claude-compatible upstream supports it; gracefully falls back to estimation on missing models, missing credentials, or upstream failures. Startup seeding of default model aliases (`src/lib/modelAliasSeed.ts`) normalizes common cross-proxy model dialects so canonical slash-based model IDs are not misrouted. New file `open-sse/config/glmProvider.ts`.\n- **feat(core): Hardened Outbound Provider Calls & Cooldown Retries** — Guarded outbound fetch helpers (`src/shared/network/safeOutboundFetch.ts`, `src/shared/network/outboundUrlGuard.ts`) blocking private/local URLs with configurable retry, timeout normalisation, and route-level status propagation for provider validation and model discovery. Cooldown-aware chat retries (`src/sse/services/cooldownAwareRetry.ts`) with configurable `requestRetry` and `maxRetryIntervalSec` settings and model-scoped cooldown responses. Improved rate-limit learning from headers and error bodies so short upstream lockouts can recover automatically. Runtime environment validation (`src/lib/env/runtimeEnv.ts`) checks env at startup. Pollinations now requires an API key. Antigravity and Codex header handling aligned via `open-sse/config/antigravityUpstream.ts` and `open-sse/config/codexClient.ts`. Gemini tool names restored in translated responses; synthetic Claude text block injected when upstream SSE completes empty.\n- **feat(logs):** Add TPS (Tokens Per Second) metric to log details modal metadata grid (#1182)\n- **feat(memory+skills):** Full-featured Memory & Skills systems with FTS5 SQLite search, dynamic UI pagination, backend observability, and extensive test coverage (#1228)\n- **feat(bailian-quota):** Add Alibaba Coding Plan quota monitoring, multi-window quota extraction, and UI credential validation (#1235)\n- **feat(storage): Call Log Storage Refactor** — Extracted heavy request/response JSON payloads from the core SQLite database (`storage.sqlite`) into filesystem artifacts stored within `DATA_DIR/call_logs`. This massively reduces WAL bloat and eliminates `SQLITE_FULL` crashes on high-traffic nodes (#1307).\n- **feat(providers): Add Grok Web (Subscription) Provider** — Routes through the xAI web interface for subscription users via cookie session mapping (#1295).\n- **feat(api): Advanced Media Support** — Extends OpenAI generic proxy layer to natively support `image`, `embeddings`, `audio-transcriptions`, and `audio-speech` workflows (#1297).\n- **feat(cli-tools): Qwen Code CLI Integration** — Full integration for Qwen Code local execution mapping, model resolution, and dynamic API key fetching (#1266, #1263).\n- **feat(oauth):** Supports `cursor-agent` CLI as a native Cursor credential source alongside the standard configuration (#1258).\n- **feat(models):** Custom and imported models now merge correctly into filter lists for all available global providers (#1191).\n\n### 🐛 Bug Fixes\n\n- **fix(providers):** match correct endpoint api.xiaomimimo.com for Xiaomi MiMo (#1303)\n- **fix(core):** strip provider alias routing prefix from payload for custom endpoints to fix Azure OpenAI 400 errors (#1261)\n- **fix(core):** ProxyFetch Undici dispatcher automatically bypasses LAN/local addresses, preventing fetch failures on internal OpenRouter requests (#1254)\n- **fix(core):** Gemini thought stream signature detection upgraded to use native part.thought boolean, preventing reasoning text leaks (#1298)\n- **deps:** bump hono from 4.12.12 to 4.12.14 to resolve CVE SSR HTML injection vulnerability (#1306, #59)\n- **deps:** update dompurify to 3.4.0 in frontend overrides mitigating XSS HTML Injection (CVE-XYZ / Dependabot #60)\n- **test:** Disable SQLite automatic backups during continuous integration (CI) tests to resolve E2E timeout issues limiting runner scaling (#24481475058)\n- **feat(core): Proactive Context Compression** — `chatCore` now proactively compresses oversized message contexts before hitting upstream providers to dramatically reduce `context_length_exceeded` errors. Employs binary-search message pruning with structural integrity guarantees tracking explicit `tool_use` boundaries ensuring truncated tool inputs drop paired outputs appropriately (#1292, #1293)\n\n- **fix(cli):** Resolve codex routing config parsing by strictly quoting section keys array, enforcing responses wire_api with fallback, and standardizing select-model button positioning mirroring Claude UI\n- **fix(providers):** Correct Lobehub provider icons rendering by removing unsupported local references ensuring local SVG/PNG fallback mechanism invokes natively\n- **fix(db):** Implement Database migration tracking safety abort safeguards (pre-migration backups via `VACUUM INTO` and mass renumbering warnings) to protect existing database structures on startup upgrades (#1281)\n- **fix(dashboard):** Cleaned up target codex `config.toml` structure preventing recursive section rendering by enforcing quotes on section dot paths and mapping correct UI `OMNIROUTE_API_KEY` names.\n- **fix(mcp):** Add dedicated explicit timeout constraint overrides for search handlers (#1280)\n- **fix(crypto):** Add validation guard to encryption layer to surface clear UI errors when cryptographic environment variables are missing, replacing raw Node.js TypeErrors. Legacy env vars `OMNIROUTE_CRYPT_KEY` and `OMNIROUTE_API_KEY_BASE64` now also accepted as fallbacks (#1165)\n- **fix(providers):** Update Pollinations provider definition to require API keys and specify their new limited pollen/hour free tier (#1177)\n- **Streaming `\\n\\n` Artifact Fix (#1211):** Changed `` tag-stripping regex from `?` to `*` quantifier across `combo.ts`, `comboAgentMiddleware.ts`, and `contextHandoff.ts` to greedily strip all accumulated JSON-escaped newline sequences surrounding the tag. This prevents literal `\\n\\n` prefix artifacts from appearing in consumer streaming responses\n- **E2E Combo Test Locator:** Fixed Playwright strict-mode violation in `combo-unification.spec.ts` by replacing ambiguous `getByRole` locator with a compound filter locator for the \"All\" strategy tab\n- **fix(cc-compatible):** Trim beta flags and preserve cache passthrough for third-party HTTP proxy compatibility (#1230)\n- **fix(providers):** Update Xiaomi MiMo endpoints to the live token-plan, migrating away from dead API URLs (#1238)\n- **fix:** Forward client `x-initiator` header to GitHub Copilot upstream to accurately distinguish agent vs user turns (#1227)\n- **fix:** Resolve backlog bugs including streaming edge cases, unhandled rejections, and quota parse failures (#1206, #1220, #1231, #1175, #1187, #1218, #1202)\n- **fix(tests):** Resolve memory migration and skills route pagination bugs arising from PR overlaps\n- **fix(i18n):** Add missing Chinese i18n support to dashboard components (`DataTable`, `EmptyState`, etc), update `en.json/zh-CN.json` routing keys, and natively resolve JSX defaults via `next-intl` (#1274)\n\n### 🔧 Internal Improvements\n\n- **Compliance Audit Expansion:** `src/lib/compliance/index.ts` expanded with structured metadata, pagination support, request context enrichment, and new `providerAudit.ts` module logging auth and provider credential events, SSRF-blocked validation attempts, and provider CRUD operations\n- **Config Sync Bundle:** `src/lib/sync/bundle.ts` exports `buildConfigBundle()` generating a versioned JSON snapshot of settings, provider connections, nodes, model aliases, combos, and API keys (passwords redacted) with ETag support for bandwidth-efficient polling\n- **Codex Client Constants:** Centralized `CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT_PLATFORM`, and pattern-validated env overrides (`CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT`) in `open-sse/config/codexClient.ts`\n- **Antigravity Upstream Constants:** `open-sse/config/antigravityUpstream.ts` consolidates all Antigravity base URLs and model/fetchAvailableModels discovery path builders\n- **Model Alias Seed:** `src/lib/modelAliasSeed.ts` seeds 30+ cross-proxy model dialect aliases (e.g. `openai/gpt-5` → `gpt-5`, `anthropic/claude-opus-4-6` → `cc/claude-opus-4-6`) at startup via idempotent `upsert`\n- **Test Coverage:** 15+ new unit test suites covering sync routes, WebSocket bridge, compliance index, GLM provider config, cooldown-aware retry, safe outbound fetch, stream utilities, Codex executor, provider validation branches, model cross-proxy compatibility, and model alias seeding\n- **TypeScript Migration:** Finalized migration of remaining JS tests (`proxy-load` and `testFromFile`) to TypeScript ES modules, ensuring a fully synchronized TS stack.\n- **Reliability & Resilience:** Added exponential backoff to `models.dev` auto-sync to combat transient network failures, raised interval floor to 1 hour, and added LKGP debug logging for enhanced observability during routing. (#1286)\n\n---\n\n## [3.6.5] — 2026-04-13\n\n### ✨ New Features\n\n- **Antigravity AI Credits Fallback:** Automatically retries with `GOOGLE_ONE_AI` credit injection when free-tier quota is exhausted. Per-account credit balance (5-hour TTL) is cached from SSE `remainingCredits` and exposed as a numeric badge in the Provider Usage dashboard (#1190 — thanks @sFaxsy)\n- **Claude Code Native Parity:** Full header/body signing parity with the Claude Code 2.1.87 OAuth client — CCH xxHash64 body signing with singleton WASM initialization promise (fixing race conditions), dynamic per-request fingerprint, bidirectional TitleCase ↔ lowercase tool name remapping (14 tools), API constraint enforcement (`temperature=1` for thinking, max 4 `cache_control` blocks, auto-inject ephemeral on last user message), and optional ZWJ obfuscation. Wired into `BaseExecutor` for automatic CCH signing on all `anthropic-compatible-cc-*` providers and into `chatCore` for synchronous parity pipeline steps (#1188 — thanks @RaviTharuma)\n- **Per-Connection Codex Defaults:** Codex Fast Service Tier and Reasoning Effort settings are now per-connection instead of a single global toggle. Existing connections are migrated automatically on startup via an idempotent backfill migration (#1176 — thanks @rdself)\n- **Cursor Usage Dashboard:** New `getCursorUsage()` fetches quotas from Cursor's `/api/usage`, `/api/auth/me`, and `/api/subscription` endpoints. Displays standard requests, on-demand usage, and per-plan limits (Free/Pro/Business/Team). Client version bumped to `3.1.0` and `x-cursor-user-agent` header added for parity\n- **Database Health Check System:** Automated periodic SQLite integrity monitoring via `runDbHealthCheck()` — detects orphan quota/domain rows, broken combo references, stale snapshots, and invalid JSON state. Runs every 6 hours (configurable via `OMNIROUTE_DB_HEALTHCHECK_INTERVAL_MS`), with auto-repair and pre-repair backup. Exposed as **MCP tool #18** (`omniroute_db_health_check`) with Zod schemas and `autoRepair` option. Dashboard panel in Health page with status card, issue count, repaired count, and one-click repair button\n- **OpenAI Responses API Store Opt-In:** Per-connection `openaiStoreEnabled` flag controls whether the `store` field is preserved or forced to `false` on Codex Responses API requests. When enabled, `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields are round-tripped through the Chat Completions → Responses translation, enabling multi-turn context caching on supported providers\n- **Email Privacy Toggle (Combos Page):** Global email visibility toggle (`EmailPrivacyToggle`) added to the Combos page header with responsive layout, tooltip guidance, and per-connection label masking via `pickDisplayValue()`. All combo builder options, provider connection lists, and quota screens now respect the global privacy state from `emailPrivacyStore`\n- **skills.sh Integration:** Added `skills.sh` as an external skill provider. Users can now search, browse, and install agent skills directly from a new \"skills.sh\" tab in the Skills dashboard. Includes backend API resolvers, frontend implementation with search/install states, and a dedicated unit test suite (#1223 — thanks @RaviTharuma)\n- **Stabilization Settings:** Added persistence support for `lkgpEnabled` and `backgroundDegradation` settings, integrated into `instrumentation-node.ts` for improved lifecycle awareness (#1212)\n- **xxhash-wasm dependency:** Added `xxhash-wasm@^1.1.0` for CCH signing (xxHash64 with seed `0x6E52736AC806831E`)\n\n### 🐛 Bug Fixes\n\n- **Codex `stream: false` via Combo (ALL_ACCOUNTS_INACTIVE):** Fixed a critical bug where Codex combos returned `ALL_ACCOUNTS_INACTIVE` or empty content when the client sent `stream: false`. Root cause was triple: (1) `CodexExecutor.transformRequest()` mutated `body.stream` in-place to `true`, contaminating the combo's quality check which skipped validation thinking it was streaming; (2) the non-stream SSE parser used the wrong format (Chat Completions instead of Responses API) for Codex SSE output; (3) combo quality validation read the mutated `body.stream` instead of the client's original intent. Fixed by: cloning the body via `structuredClone()` in CodexExecutor, detecting Codex/Responses SSE format in the non-stream fallback path (with auto-translation back to Chat Completions), and capturing `clientRequestedStream` before the combo loop\n- **Gemini CLI Tool Schema Rejection:** Fixed 400 Bad Request errors from the Google API by strictly filtering non-standard vendor extensions (starting with `x-`) and `deprecated` fields from tool parameter schemas (#1206)\n- **SOCKS5 Proxy Interop (Node.js 22):** Resolved `invalid onRequestStart method` crashes caused by `undici` version mismatches between dispatchers and the built-in fetch. Hardened `proxyFetch.ts` to strictly use the library's fetch implementation for custom dispatchers (#1219)\n- **Search Cache Coalescing with TTL=0:** Fixed a bug where providers configured with `cacheTTLMs: 0` (caching explicitly disabled) still had concurrent requests coalesced and returned `{ cached: true }`. Now each call gets its own independent upstream fetch (#1178 — thanks @sjhddh)\n- **Antigravity Credit Cache Alignment (PR #1190):** Reconciled `accountId` derivation between `AntigravityExecutor.collectStreamToResponse` and `getAntigravityUsage` to use consistent cache keys (`email || sub || \"unknown\"`). Previously, SSE-parsed credit balances could be written under a different key than the one read by the usage dashboard, causing stale/missing credit badges\n- **Non-streaming reasoning_content Duplication:** Fixed clients rendering duplicated reasoning panels when both `reasoning_content` and visible `content` were present in non-streaming responses. `responseSanitizer` now strips `reasoning_content` from messages that already have visible text content, preserving it only for reasoning-only messages\n- **Streaming Regression Fix:** Hardened the `sanitize` TransformStream in the combo engine to strip both literal and JSON-escaped newline sequences, eliminating leading `\\n\\n` prefixes in assistant responses (#1211)\n- **Gemini Empty Choice Fix:** Ensured initial assistant deltas always include an empty `content: \"\"` string to satisfy strict OpenAI client requirements and prevent empty choice responses in tools (#1209)\n- **Gemini Tools Sanitizer Deduplication:** Extracted shared tool conversion logic into `buildGeminiTools()` helper (`geminiToolsSanitizer.ts`), eliminating duplicate implementations between `openai-to-gemini.ts` and `claude-to-gemini.ts`. The new helper correctly handles `web_search` / `web_search_preview` tool types by emitting `googleSearch` tools with priority over function declarations\n- **Qwen/Qoder Thinking+Tool_Choice Conflict:** Added `sanitizeQwenThinkingToolChoice()` to both `DefaultExecutor` (for Qwen provider) and `QoderExecutor` to prevent provider-side 400 errors when clients send `tool_choice` alongside thinking/reasoning parameters that are mutually exclusive upstream\n- **API Key Deletion Orphan Cleanup:** Deleting an API key now also removes associated `domain_budgets` and `domain_cost_history` rows, preventing orphan data accumulation\n- **CC-compatible test assertion:** Fixed pre-existing test that expected no `cache_control` on system blocks — the billing header system block now carries `cache_control: { type: \"ephemeral\" }` per PR #1188 design\n- **Codex Combo Smoke Test False Positives:** Fixed combo tests incorrectly reporting `ERROR` for valid Codex streaming responses when `response.output` is empty but text deltas were emitted. The summary now falls back to accumulated delta text (#1176 — thanks @rdself)\n- **Electron Builder Version Mismatch:** Fixed Electron desktop startup failures on Windows packaged builds caused by native modules (`better-sqlite3`) being under `app.asar.unpacked` while helpers were in `app/node_modules`. `resolveServerNodePath()` now merges both locations with deduplication and existence checks (#1172 — thanks @backryun)\n\n### 🔧 Internal Improvements\n\n- **SSE Parser: Responses API Non-Stream Conversion:** Added full `parseSSEToResponsesOutput()` implementation in `sseParser.ts` (255+ lines) — reconstructs complete Responses API objects from SSE event streams, handling `response.output_text.delta/done`, `response.reasoning_summary_text.delta/done`, `response.function_call_arguments.delta/done`, and terminal events. Used by the new chatCore non-stream fallback path for Codex\n- **Cursor Executor Version Sync:** Updated Cursor client User-Agent to `3.1.0` and centralized version constants (`CURSOR_CLIENT_VERSION`, `CURSOR_USER_AGENT`) for consistent fingerprinting across executor, usage fetcher, and OAuth flows\n- **Responses API Translator Parity:** `convertResponsesApiFormat()` now accepts credentials and passes them through to the translator, enabling store-aware field propagation. Round-trip preservation of `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields\n- **Provider Schema Validation:** Added `openaiStoreEnabled` boolean validation to `providerSpecificData` Zod schema\n- **Combo Error Response Normalization:** Empty combo targets now return 404 (`comboModelNotFoundResponse`) instead of generic 503, improving client-side error differentiation\n- **Dependency Updates:** Bumps `typescript-eslint` to `8.58.2` (dev), `axios` to `1.15.0` (prod), and `next` to `16.2.2` (prod) (#1224, #1225)\n\n### ⚠️ Breaking Changes\n\n- **`DELETE /api/settings/codex-service-tier` removed:** This endpoint no longer exists. Codex Service Tier configuration has moved to per-connection `providerSpecificData.requestDefaults`. Existing connections are migrated automatically on first startup after upgrade. Any external scripts or integrations that call this endpoint should be updated — use `PUT /api/providers/:id` with `providerSpecificData.requestDefaults.serviceTier` instead (#1176).\n- **CCH signing on CC-compatible providers:** All requests to `anthropic-compatible-cc-*` providers now include an xxHash64 integrity token (`cch=...`) in the billing header. Providers that do not validate CCH will ignore it (no behavioral change), but any custom middleware inspecting the billing header should expect a 5-character hex token instead of the `00000` placeholder\n\n---\n\n## [3.6.4] — 2026-04-12\n\n### ✨ New Features\n\n- **Combo Builder v2 (Wizard UI):** Completely redesigned the combo creation/editing interface as a multi-stage wizard with stages: Basics → Steps → Strategy → Review. The builder fetches provider, model, and connection metadata via a new `GET /api/combos/builder/options` endpoint, enabling precise provider/model/account selection with duplicate detection and automatic next-connection suggestion. Heavy UI components (`ModelSelectModal`, `ProxyConfigModal`, `ModelRoutingSection`) are now lazily loaded via `next/dynamic` for faster initial page render\n- **Combo Step Architecture (Schema v2):** Introduced a structured step model (`ComboModelStep`, `ComboRefStep`) replacing the legacy flat string/object combo entries. Steps carry explicit `id`, `kind`, `providerId`, `connectionId`, `weight`, and `label` fields, enabling pinned-account routing, cross-combo references, and per-step metrics. All combo CRUD operations normalize entries through the new `src/lib/combos/steps.ts` module. Zod schemas updated with `comboModelStepInputSchema` and `comboRefStepInputSchema` unions\n- **Composite Tiers System:** Added tiered model routing via `config.compositeTiers` — each tier maps a named stage to a specific combo step with optional fallback chains. Includes comprehensive validation (`src/lib/combos/compositeTiers.ts`) ensuring step existence, preventing circular fallback, and validating default tier references. Zod schema enforcement blocks composite tiers on global defaults (concrete combos only)\n- **Model Capabilities Registry:** Created `src/lib/modelCapabilities.ts` providing `getResolvedModelCapabilities()` — a unified resolver that merges static specs, provider registry data, and live-synced capabilities into a single `ResolvedModelCapabilities` object covering tool calling, reasoning, vision, context window, thinking budget, modalities, and model lifecycle metadata\n- **Observability Module:** Extracted health and telemetry payload construction into `src/lib/monitoring/observability.ts` with `buildHealthPayload()`, `buildTelemetryPayload()`, and `buildSessionsSummary()` builders. The health endpoint now returns session activity, quota monitor status, and per-provider breakdowns alongside existing system metrics\n- **Session & Quota Monitor Dashboard:** Added live Session Activity and Quota Monitors panels to the Health dashboard, showing active session counts, sticky-bound sessions, per-API-key breakdowns, and top session details alongside quota monitor alerting/exhausted/error status with per-provider drill-down\n- **Combo Health Per-Target Analytics:** The combo-health API now resolves per-target metrics using the new `resolveNestedComboTargets()` function, providing step-level success rates, latency, and historical usage breakdowns per execution key — enabling per-account, per-connection health visibility\n- **Auto-Combo → Combos Unification:** Merged the separate `/dashboard/auto-combo` page into the main `/dashboard/combos` page. Auto/LKGP combos are now managed alongside all other combos with a new strategy filter tabs system (All / Intelligent / Deterministic). The old auto-combo route redirects to `/dashboard/combos?filter=intelligent`. Removed the `auto-combo` sidebar entry, consolidating navigation into the single `Combos` item\n- **Intelligent Routing Panel (`IntelligentComboPanel`):** New inline panel (371 lines) within the combos page that shows real-time provider scores, 6-factor scoring breakdown (quota, health, cost, latency, task fitness, stability), mode pack selector, incident mode status, and excluded providers for `auto`/`lkgp` combos — replacing the former standalone auto-combo dashboard\n- **Builder Intelligent Step (`BuilderIntelligentStep`):** New conditional wizard step (280 lines) that appears in the Builder v2 flow only when `strategy=auto` or `strategy=lkgp` is selected. Exposes candidate pool selection, mode pack presets, router sub-strategy selector, exploration rate slider, budget cap, and collapsible advanced scoring weights configuration\n- **Intelligent Routing Module (`intelligentRouting.ts`):** Extracted strategy categorization and filtering logic into a dedicated shared module (210 lines) with `getStrategyCategory()`, `isIntelligentStrategy()`, `filterCombosByStrategyCategory()`, `normalizeIntelligentRoutingFilter()`, and `normalizeIntelligentRoutingConfig()` utility functions\n- **LKGP Standalone Strategy:** Implemented `lkgp` (Last Known Good Provider) as a fully functional standalone combo strategy. Previously, `lkgp` as a combo strategy silently fell through to `priority` ordering — the LKGP lookup only ran inside the `auto` engine. Now `strategy: \"lkgp\"` correctly queries the LKGP state, moves the last successful provider to the top of the target list, and saves the LKGP state after each successful request. Falls back to priority ordering when no LKGP state exists\n- **Unified Routing Rules & Model Aliases:** Consolidated the routing rules and model alias management controls into the Settings page, reducing fragmentation across the dashboard\n\n### ⚡ Performance\n\n- **Middleware Lazy Loading:** Refactored `src/proxy.ts` to lazy-import `apiAuth`, `db/settings`, and `modelSyncScheduler` modules, reducing middleware cold-start overhead. Added inline `isPublicApiRoute()` to avoid loading the full auth module for public routes\n- **E2E Auth Bypass:** Added `NEXT_PUBLIC_OMNIROUTE_E2E_MODE` environment flag to bypass authentication gates for dashboard and management API routes during Playwright E2E test runs\n\n### 🐛 Bug Fixes\n\n- **P2C Credential Selection:** Implemented Power-of-Two-Choices (P2C) connection scoring in `src/sse/services/auth.ts` with quota headroom awareness, error/recency penalties, and forced/excluded connection support. The new `getProviderCredentialsWithQuotaPreflight()` function integrates quota preflight checks directly into credential selection, eliminating the separate Codex-only preflight path\n- **Fixed-Account Combo Steps:** Combo steps with explicit `connectionId` now correctly bypass provider-level model cooldowns and circuit breakers, preventing a single account failure from blocking pinned-connection routing for the same model\n- **Combo Metrics Per-Target Tracking:** Extended `comboMetrics.ts` to track `byTarget` metrics keyed by execution path, recording per-step `provider`, `providerId`, `connectionId`, and `label` alongside existing per-model aggregates\n- **Call Logs Schema Expansion:** Added `requested_model`, `request_type`, `tokens_cache_read`, `tokens_cache_creation`, `tokens_reasoning`, `combo_step_id`, and `combo_execution_key` columns to `call_logs` with auto-migration. Added composite index `idx_cl_combo_target` for efficient per-target historical queries\n- **Quota Monitor Enrichment:** Expanded `quotaMonitor.ts` with full lifecycle state tracking (`status`, `startedAt`, `lastPolledAt`, `consecutiveFailures`, `totalPolls`, `totalAlerts`), ISO-formatted snapshots via `getQuotaMonitorSnapshots()`, and sorted summary via `getQuotaMonitorSummary()`\n- **Codex Quota Fetcher Hardening:** Improved `codexQuotaFetcher.ts` with safer connection registration and quota fetch error handling\n- **LKGP Save Refactored to Async/Await:** Replaced fire-and-forget `.then()` chain for LKGP persistence after successful combo routing with proper `async/await` + `try/catch`, preventing unhandled promise rejections and ensuring LKGP state is reliably saved before the response is returned\n- **Duplicate `auto` in Combo Strategy Schema:** Removed duplicate `\"auto\"` entry from `comboStrategySchema` (was listed on both line 104 and 108). Harmless to Zod runtime but cleaned up to avoid confusion. Schema now has exactly 13 unique strategy values\n- **Legacy Combo Refs Normalization:** Fixed combo step normalization to preserve legacy string combo references during CRUD operations, preventing data loss when editing combos created before the v2 step architecture\n\n### Сигурност\n\n- **Auth Bypass on Backup Routes (Critical):** Added `isAuthenticated` guards to `/api/db-backups/exportAll` (full database export) and `/api/db-backups` (list, create, and restore backups) — both were previously accessible without authentication\n- **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency\n- **API Key Secret Hardening:** Removed the hardcoded `\"omniroute-default-insecure-api-key-secret\"` fallback from `apiKey.ts` — the function now fails fast if `API_KEY_SECRET` is unset, relying on the startup validator to auto-generate it\n- **NPM Tarball Leak Fix:** Added `app/.env*` to `.npmignore` to prevent the working `.env` file from being shipped inside the npm tarball distribution\n- **Electron Builder CVE Fix:** Bumped `electron-builder` to 26.8.1 to resolve `tar` CVEs in the desktop build pipeline\n\n### 🔧 Maintenance & Infrastructure\n\n- **DB Migration 021:** Added `combo_call_log_targets` migration for `combo_step_id` and `combo_execution_key` columns in call_logs\n- **Combo CRUD Normalization:** `db/combos.ts` now normalizes all stored combo entries through the step normalization pipeline on read, ensuring consistent step IDs and kind annotations regardless of when the combo was created\n- **Playwright Config:** Updated Playwright configuration and `run-next-playwright.mjs` script for improved E2E test orchestration\n- **Build Script:** Updated `build-next-isolated.mjs` with additional reliability improvements\n- **Auto-Combo UI Cleanup:** Deleted `AutoComboModal.tsx` (161 lines), replaced `auto-combo/page.tsx` (478→5 lines) with a server-side redirect to `/dashboard/combos?filter=intelligent`\n- **Sidebar Consolidation:** Removed `\"auto-combo\"` from `HIDEABLE_SIDEBAR_ITEM_IDS` and `PRIMARY_SIDEBAR_ITEMS` — `normalizeHiddenSidebarItems()` silently discards any stale `\"auto-combo\"` entries in user settings\n- **Schema Cleanup:** Removed obsolete `createAutoComboSchema` from `schemas.ts`. Exported `comboStrategySchema` for direct use in test and filter modules\n- **A2A Agent Card Update:** Renamed skill ID from `auto-combo` to `intelligent-routing` with updated description referencing the unified combos dashboard\n- **Builder Draft Refactor:** Extended `builderDraft.ts` with dynamic stage list generation via `getComboBuilderStages()` and `isIntelligentBuilderStrategy()`. Stage navigation (`getNextComboBuilderStage`, `getPreviousComboBuilderStage`, `canAccessComboBuilderStage`) now accepts options to conditionally include/skip the `intelligent` wizard step\n- **i18n Consolidation:** Removed the standalone `\"autoCombo\"` i18n block (22 keys) from all 30 language files. Migrated keys into the `\"combos\"` block with new additions for filter tabs, intelligent panel, and builder step labels\n\n### 🧪 Tests\n\n- **16 New Test Suites:** Added comprehensive test coverage including:\n - `combo-builder-draft.test.mjs` (186 lines) — Builder draft step construction and validation\n - `combo-builder-options-route.test.mjs` (228 lines) — Builder options API endpoint\n - `combo-health-route.test.mjs` (266 lines) — Combo health analytics with per-target metrics\n - `combo-routes-composite-tiers.test.mjs` (157 lines) — Composite tiers API integration\n - `composite-tiers-validation.test.mjs` (131 lines) — Composite tier validation rules\n - `db-combos-crud.test.mjs` — Combo CRUD with step normalization\n - `db-core-init.test.mjs` (129 lines) — DB initialization and column migrations\n - `model-capabilities-registry.test.mjs` (105 lines) — Model capabilities resolution\n - `observability-payloads.test.mjs` (165 lines) — Health/telemetry payload construction\n - `openapi-spec-route.test.mjs` — OpenAPI spec generation\n - `proxy-e2e-mode.test.mjs` (74 lines) — E2E mode auth bypass\n - `quota-monitor.test.mjs` — Quota monitor lifecycle state\n - `run-next-playwright.test.mjs` (119 lines) — Playwright runner script\n - `sse-auth.test.mjs` (154 lines) — P2C credential selection and quota preflight\n - `telemetry-summary-route.test.mjs` (35 lines) — Telemetry summary endpoint\n - Plus updates to 12 existing test files for compatibility with new step architecture\n- **Auto-Combo Unification Tests:**\n - `autocombo-unification.test.mjs` (156 lines) — Strategy categorization, schema deduplication, sidebar cleanup, and routing strategies metadata validation\n - `combo-unification.spec.ts` (189 lines) — Playwright E2E tests for filter tabs, intelligent panel rendering, redirect from old route, sidebar entry removal, and Builder v2 intelligent step flow\n - 3 new LKGP standalone tests in `combo-routing-engine.test.mjs` — Validates LKGP provider prioritization, fallback to priority when no state exists, and LKGP state persistence after successful requests\n - Updated `combo-builder-draft.test.mjs` with intelligent stage navigation tests\n - Updated `sidebar-visibility.test.mjs` to reflect `auto-combo` removal\n\n---\n\n## [3.6.3] — 2026-04-11\n\n### ✨ New Features\n\n- **OpenAI-Compatible Loose Validation:** Empty API keys can now be naturally submitted and saved for any `openai-compatible-*` providers (e.g. Pollinations, localized routes) directly in the UI instead of blocking save actions (#1152)\n- **Cloudflare Configuration:** Updated the provider schema and UI integration for Cloudflare AI to officially expose and support the backend `accountId` field securely without overrides (#1150)\n\n### 🐛 Bug Fixes\n\n- **Vertex JSON Validation Crash:** Prevented `invalid character in header` crashes inside the `/validate` endpoint by creating a native authentication parser that correctly handles Google Identity Service Account JSON flows prior to pinging endpoints (#1153)\n- **Extraneous Payload Rejection:** Globally prevented upstream `400 Bad Request` execution crashes by stripping the non-standard `prompt_cache_retention` attribute forcibly attached by Cursor/Cline IDE engines when targeting strict OpenAI/Anthropic routes (#1154)\n- **Reasoning Content Drop:** Prevented pure reasoning packets, common in advanced fallback models like DeepSeek, from being aborted mid-stream by explicitly adjusting the `Empty Content (502)` circuit breakers to acknowledge `reasoning_content` states as valid (#1155)\n- **Desktop Windows Build Crash:** Fixed `better_sqlite3.node is not a valid Win32 application` preventing OmniRoute Desktop from launching on Windows by properly removing the ABI-mismatched sqlite cache from Next.js standalone and falling back to the cross-compiled Electron equivalent during packager build steps (#1163)\n- **Login Visual Security:** Removed the raw fallback hash dump that artificially rendered underneath the login modal in Docker instances missing `OMNIROUTE_API_KEY_BASE64` flags (#1148)\n\n### 🔧 Maintenance & Dependencies\n\n- **Dependabot Updates:** Safely bumped GitHub Actions `docker/build-push-action` to v7 and `actions/download-artifact` to v8\n- **Electron Updates:** Upgraded desktop wrapper core to Electron `41.2.0` and `electron-builder` to `26.8.1`, incorporating essential V8/Chromium security patches\n- **NPM Package Groups:** Updated `production` and `development` NPM groups to securely handle minor audit warnings and keep toolchains modern\n- **CI/CD Reliability:** Fixed persistent `Snyk` token-absence failures on automated pull requests by appropriately bypassing on dependabot actions\n\n## [3.6.2] — 2026-04-11\n\n### ✨ New Features\n\n- **33 New API Key Providers:** Massive provider expansion adding DeepInfra, Vercel AI Gateway, Lambda AI, SambaNova, nScale, OVHcloud AI, Baseten, PublicAI, Moonshot AI, Meta Llama API, v0 (Vercel), Morph, Featherless AI, FriendliAI, LlamaGate, Galadriel, Weights & Biases Inference, Volcengine, AI21 Labs, Venice.ai, Codestral, Upstage, Maritalk, Xiaomi MiMo, Inference.net, NanoGPT, Predibase, Bytez, Heroku AI, Databricks, Snowflake Cortex, and GigaChat (Sber). OmniRoute now supports **100+ providers** (4 Free + 8 OAuth + 91 API Key + Custom compatible)\n- **Global Email Privacy Toggle:** Added a persistent eye-icon toggle button across all dashboard pages (Providers, Usage Limits, Playground) that reveals or hides masked email addresses. Toggle state is stored in localStorage and synced globally via Zustand store\n- **Documentation Refresh:** Updated README, ARCHITECTURE, FEATURES, AGENTS.md, and API_REFERENCE for v3.6.2 with accurate provider counts (100+), new executor list, and system API documentation\n- **Uninstall Guide:** Created comprehensive `docs/UNINSTALL.md` covering clean uninstallation for all deployment methods (npm, Docker, Electron, source)\n\n### 🐛 Bug Fixes\n\n- **PDF Attachments:** Unlocked deep string object parsing (`geminiHelper`) ensuring Gemini translation successfully passes complex PDF payloads from OpenAI-compatible streams without dropping them silently (#993)\n- **SkillsMP Engine:** Corrected object extraction path mappings inside the API router to fix UI marketplace rendering under Docker/Standalone Node isolated deployments (#988)\n\n---\n\n## [3.6.1] — 2026-04-10\n\n### ✨ New Features\n\n- **OAuth Env Repair Action:** Added a \"Repair env\" button to the OAuth Providers dashboard that detects and restores missing OAuth client IDs from `.env.example` — with timestamped backup and append-only safety. Includes full 33-language i18n support and sanitized API responses (#1116, by @yart)\n\n### 🐛 Bug Fixes\n\n- **i18n: Missing Provider Keys:** Added missing `filterModels`, `modelsActive`, `showModel`, `hideModel` keys across all 32 locale files, fixing runtime `MISSING_MESSAGE` errors in the providers UI. Also cleaned up duplicate keys in `en.json` (#1111, by @rilham97)\n- **GPT-5.4 Routing:** Added missing `targetFormat: \"openai-responses\"` to `gpt-5.4` and `gpt-5.4-mini` models in both the Codex and GitHub Copilot providers, fixing `[400]: model not accessible via /chat/completions` errors (#1114, by @ask33r)\n\n---\n\n## [3.6.0] — 2026-04-10\n\n### ✨ New Features & Analytics\n\n- **Combo Smoke Test:** Raised the default token budget to 2048 to prevent truncation of thinking models during preflight checks, and fully randomized the arithmetic probe prompt to bypass deterministic caching from upstream relays (#1105)\n\n### 🐛 Bug Fixes & Compliance\n\n- **DB Bloat / Row Limits:** Added `CALL_LOGS_TABLE_MAX_ROWS` and `PROXY_LOGS_TABLE_MAX_ROWS` (default: 100,000) to the backend DB compliance cleaner to prevent runaway SQLite growth. Limits are enforced automatically on the TTL cycle (#1104, fixes #1101)\n- **HTML Error Handling:** The router now correctly identifies unexpected HTML responses (e.g. ``) sent by upstream providers (like Azure/Copilot) instead of throwing obscure `Unexpected token '<'` JSON parse errors, bubbling up a clean 502 Bad Gateway (#1104, fixes #1066)\n- **Android/Termux SQLite Native Support:** `better-sqlite3` is now correctly built from source with cross-compilation flags in ARM64 local Termux deployments without failing on missing prebuilt binaries (#1107)\n\n---\n\n## [3.5.9] — 2026-04-09\n\n### ✨ New Features\n\n- **Persistent Combo Ordering:** Drag combo cards by handle to reorder them in the dashboard; order is persisted to SQLite via a new `sort_order` column and `POST /api/combos/reorder` endpoint. Includes DB migration `020_combo_sort_order.sql` and JSON import preservation (#1095)\n- **Sidebar Group Reorder:** Moved \"Logs\" before \"Health\" in the System section and \"Limits & Quotas\" after \"Cache\" in the Primary section for a more logical navigation flow (#1095)\n\n### 🐛 Bug Fixes\n\n- **Stream Failure Surfacing:** Upstream `response.failed` events (e.g. Codex rate-limit errors) are now properly surfaced as non-200 errors instead of being silently swallowed as empty 200 OK streams. Rate-limit failures return HTTP 429 (#1098, closes #1093)\n- **Upstream Model Preservation:** The Responses-to-OpenAI stream translator now preserves the actual upstream model (e.g. `gpt-5.4`) instead of hardcoding a `gpt-4` fallback (#1098, closes #1094)\n- **Docker EXDEV Fix:** `build-next-isolated.mjs` now falls back from `fs.rename()` to `cp/rm` when Docker buildx raises `EXDEV` (cross-device link), unblocking the Docker image publish workflow (#1097)\n- **macOS CLI Path Resolution:** `cliRuntime.ts` resolves symlink parents with `fs.realpath()` to handle macOS `/var` → `/private/var` chains, preventing false `symlink_escape` rejections (#1097)\n- **Request Log Token Layout:** Split token badges into separate Input (Total In, Cache Read, Cache Write) and Output (Total Out, Reasoning) groups for clearer readability; renamed \"Time\" label to \"Completed Time\" (#1096)\n\n---\n\n## [3.5.8] — 2026-04-09\n\n### ✨ New Features & Analytics\n\n- **Analytics Layout Redesign:** Replaced flat metrics with a responsive `CompactStatGrid`, grouping data visually across sections (#1089)\n\n### 🐛 Bug Fixes\n\n- **Build Core:** Force Turbopack cleanup via Prepbulish script to prevent Next.js 16 app/ routing conflicts on runtime.\n- **Provider Quarantine:** Introduces model/provider circuit-breakers with adaptive TTL exponential backoff for recurring upstream errors (#1090)\n- **Oauth Keep-Alive:** Safely protects authenticated active accounts against spontaneous dropping from router due to transient token refresh failures (#1085)\n\n### 🔒 Security & Maintenance\n\n- **Dependabot:** bumped axios from 1.14.0 to 1.15.0 addressing SSRF flags (#1088)\n\n---\n\n## [3.5.7] — 2026-04-09\n\n### 🐛 Bug Fixes & Security\n\n- **Turbopack Standalone Chunks:** Fixed a critical bug in `scripts/prepublish.mjs` where Turbopack chunks missing from the `.next/standalone` trace resulted in a `500 ChunkLoadError` (e.g., `_not-found` page crash) during production deployments via NPM or Docker. Standalone chunks are now explicitly copied and correctly stripped of Turbopack hashes.\n\n---\n\n## [3.5.6] — 2026-04-09\n\n### ✨ New Features\n\n- **Email Privacy Masking:** OAuth account emails are now masked in the provider dashboard (e.g. `di*****@g****.com`) to prevent accidental exposure when sharing screenshots. Full address visible on hover via `title` attribute (#1025).\n- **OpenRouter & GitHub in Embedding/Image Registries:** OpenRouter (3 embedding models, 4 image models) and GitHub Models (2 embedding models via Azure inference) are now first-class entries in the provider registries, enabling their use for `/v1/embeddings` and `/v1/images/generations` (#960).\n- **Model Visibility Toggle & Search Filter:** The provider page model list now includes a real-time search/filter bar and a per-model visibility toggle (👁 icon). Hidden models are grayed out and excluded from the `/v1/models` catalog. An active-count badge (`N/M active`) shows at a glance how many models are enabled (#750).\n- **Chinese Localization (zh-CN):** Added missing translations for Context Relay, Memory, LKGP, and Models.dev sync features, while standardizing terminology across the application (#1079).\n- **Environment Auto-Sync:** Added `sync-env.mjs` to auto-generate and append `.env` from `.env.example` during installation, automatically generating cryptographic secrets on first run.\n- **Source Mode Dashboard Update:** Fixed real-time Source (git-checkout) updating in the dashboard, enabling secure, real-time update pipelines for non-NPM installations.\n\n### 🐛 Bug Fixes & Security\n\n- **Hardcoded Secret Cleanup:** Removed 12 hardcoded OAuth credential fallbacks from the source code, forcing secure reliance on environment variables and resolving static analysis security alerts.\n- **Next.js Security Patch:** Bumped `next` from 16.2.2 to 16.2.3 to resolve critical RSC deserialization RCE vulnerability (SNYK-JS-NEXT-15954202).\n- **Memory/Cache UI Crash:** Added null-safety guards (`?? 0`) to `.toLocaleString()` calls in Memory and Cache dashboard pages, preventing `TypeError` crashes when database tables are empty or contain null numeric values (#1083).\n- **WebSearch tool_choice Translation:** Fixed OpenAI-to-Claude translator dropping `tool_choice` objects with `type: \"function\"` as-is, which Claude rejects. Now properly maps all OpenAI `tool_choice` variants (`function`, `required`, `none`) to Claude-compatible format (`tool`, `any`, `auto`), fixing \"Did 0 searches\" in Claude Code WebSearch (#1072).\n- **Provider Validation baseUrl Override:** Added `baseUrl` passthrough from frontend validation requests to the backend validation endpoint. Chinese-site users of Alibaba Coding Plan (bailian-coding-plan) can now validate API keys against their custom Base URL instead of always hitting the international endpoint (#1078).\n- **Minimax Auth Header:** Switched Minimax provider from `x-api-key` to `Authorization: Bearer` header format, matching the current API spec (#1076).\n- **Native Fetch Fallback:** Added graceful fallback to native `fetch` when the `undici` dispatcher fails, improving resilience in environments where undici is unavailable (#1054).\n- **EPIPE Flood Fix:** Added circuit-breaker logic to prevent EPIPE errors from creating a feedback loop that fills logs at GB/s (#1006).\n- **Qoder PAT Validation:** Improved Qoder Personal Access Token validation with actionable error messages that guide users to the correct token format (#966).\n- **CI/CD Pipeline:** Fixed `check:docs-sync` failure by syncing OpenAPI version to 3.5.6 and finalizing CHANGELOG release heading. Commented out `DATA_DIR` in `.env.example` to prevent E2E test failures in CI runners lacking root permissions.\n\n### 🌍 i18n\n\n- **Auto Language Generation (CI):** Added CI pipeline to auto-generate missing language files and strings via `feat(CI,i18n)` workflow, covering 30+ locales (#1071).\n\n---\n\n## [3.5.5] — 2026-04-08\n\n### ✨ New Features\n\n- **Node.js 24 Compatibility Warning:** Added a proactive version incompatibility warning on the login page to guide users to the stable Node.js 22 LTS, preventing native sqlite binding crashes.\n- **Context Relay Combo Strategy:** Added the new `context-relay` combo strategy with priority-style routing, structured handoff summary generation once quota usage reaches the warning threshold, and handoff injection after the next real account switch.\n- **Global Context Relay Defaults:** Added global Settings defaults plus combo-level configuration for `handoffThreshold`, `handoffModel`, and `handoffProviders`, so new or unconfigured combos can inherit the feature consistently.\n\n### 🐛 Bug Fixes\n\n- **Proxy Connection Healthchecks:** Applied proxy resolution per connection in the sweeping loop (`tokenHealthCheck.ts`) and global provider validation sweeps, resolving Node 22 bypass and improving proxy stability (#1051, #1056, #1061).\n- **Security Vulnerability Remediation:** Resolved multiple CodeQL scanning alerts including SSRF in model sync, insecure randomness in web crypto (`generateSessionId`), and incomplete URL sanitization.\n- **Context Relay Typing & Synchronization:** Reverted out-of-scope test breakages and resolved `handoffProvider` and response `input` extraction payload typing.\n- **Legacy OpenAI-Compatible Responses Routing:** Fixed legacy/imported OpenAI-compatible providers (for example `openai-compatible-sp-openai`) incorrectly routing Chat Completions traffic to `/chat/completions` when the real provider node was configured as `apiType: \"responses\"`. OmniRoute now treats `providerSpecificData.apiType` as authoritative across routing, executors, and translator tools, avoiding false empty-content failures during combo/provider smoke tests (#1069).\n- **Gemini PDF Attachment Integration:** Fixed payload generation and format for parsing `inline_data` and generic base64 sources for deep Gemini PDF routing (#993, #1021).\n- **Vercel AI SDK Fallbacks:** Mapped `max_output_tokens` to `max_tokens` for strict OpenAI-compatible providers, resolving errors from standard AI agents and frameworks (#994).\n- **External Auth & UI Reliability:** Handled null `state` failures in Cline OAuth exchange (#1016), added 3rd-party 400 error patterns to combo fallback (#1024), and resolved desktop sidebar layout and popover overflows (#1039, #1001).\n- **Context Relay In-Flight Deduplication:** Prevented duplicate handoff generation for the same session/combo while an earlier summary request is still in flight.\n- **Context Relay Provider Gating:** Aligned runtime behavior with configuration so explicit `handoffProviders` exclusions, including an empty array, now disable handoff generation as expected.\n\n### 🛠️ Maintenance & Dependabot\n\n- **Updated Sub-dependencies:** Bumped `hono` to `4.12.12` and `@hono/node-server` to `1.19.13` to patch critical security gaps (#1063, #1064, #1067, #1068).\n\n### Документация\n\n- **Documentation Synchronization:** Updated system documentation (README, Architecture, Features, Tools, Troubleshooting) and synced `i18n` configurations to match the v3.5.5 context relay patterns and proxy troubleshooting steps.\n- **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance.\n\n---\n\n## [3.5.4] — 2026-04-07\n\n### ✨ New Features\n\n- **Detailed Token Tracking:** Added granular token breakdown columns (cache read, cache write, reasoning) to call logs with proper null vs zero distinction. Includes DB migration 018 and 5-label UI display per provider capability (#1017 — thanks @rdself).\n- **Legacy JSON Config Import/Export:** Restored JSON-based settings export and import for migration from legacy 9router configurations. Security-hardened with Zero-Trust redaction of passwords and `requireLogin` fields, and automatic pre-import database backups (#1012 — thanks @luandiasrj).\n- **Non-Stream Aliases:** Added API support for explicit non-streaming aliases (`non_stream`, `disable_stream`, `disable_streaming`, `streaming=false`), normalized at the boundary before provider translation (#1036 — thanks @wlfonseca).\n- **Russian Dashboard Localization:** Comprehensive Russian translation for the dashboard UI, including fixes for 2 Ukrainian locale keys (#1003 — thanks @mercs2910).\n\n### 🐛 Bug Fixes\n\n- **Anthropic Streaming Input Undercount:** Fixed a critical bug where Anthropic streaming `prompt_tokens` only reported non-cached tokens (e.g., `in=3` when actual total was 113,616). Cache tokens are now summed into prompt_tokens during streaming (#1017).\n- **Built-in Responses API Tool Types:** Preserved built-in Responses API tools (`web_search`, `file_search`, `computer`, `code_interpreter`, `image_generation`) from being silently stripped by the empty-name tool filter — these tools carry no `.name` field (#1014 — thanks @rdself).\n- **Cursor/Codex Responses Compatibility:** Fixed empty output in Cursor when using Codex models by hoisting system input items to `instructions`, sanitizing invalid tool names, and detecting Responses-format payloads on chat/completions endpoint (#1002 — thanks @mercs2910).\n- **OAuth Token Expiry Display:** Fixed OAuth connections showing \"expired\" badge even with valid tokens by reading `tokenExpiresAt` (updated on refresh) instead of `expiresAt` (original grant timestamp) (#1032 — thanks @tombii).\n- **Codex Fast-Tier Copy:** Corrected dashboard settings copy from `service_tier=fast` to `service_tier=priority`, matching the actual Codex wire format (#1045 — thanks @kfiramar).\n- **macOS Desktop App Startup:** Stabilized packaged macOS app launch by excluding desktop artifacts from the standalone bundle and improving launch path detection (#1004 — thanks @mercs2910).\n- **macOS Sidebar Layout:** Fixed macOS traffic light overlap, sidebar spacing, and button overflow in the Electron desktop app (#1001 — thanks @mercs2910).\n\n### ⚡ Performance\n\n- **Analytics Page Load:** Dramatically reduced analytics page load times (30s→1-2s for 50K entries) via date-filtered DB queries, parallel `Promise.all()` cost calculations, and merged 6 COUNT queries into a single CASE WHEN aggregate (#1038 — thanks @oyi77).\n\n### 🔒 Security & Dependencies\n\n- **Node Base Image:** Upgraded Docker base from `22-bookworm-slim` to `22.22.2-trixie-slim` (#1011 — Snyk).\n- **Production Dependencies:** Bumped 5 production dependencies (#1044 — Dependabot).\n- **Vite:** Bumped from 8.0.3 to 8.0.5 (#1031 — Dependabot).\n- **Development Dependencies:** Bumped 4 development dependencies (#1030 — Dependabot).\n\n### 🧪 Tests\n\n- **Token Accounting Tests:** Added 18 new unit tests covering detailed token breakdown, null vs zero semantics, per-provider token extraction, and Anthropic streaming input fix (#1017).\n- **Built-in Tool Tests:** Added 3 new test cases for built-in Responses API tool type preservation (#1014).\n- **ChatCore Sanitization:** Updated sanitization tests to accommodate Responses format detection (PR #1002) and built-in tool preservation (PR #1014).\n\n### 🛠️ Maintenance\n\n- **PR Workflow:** Updated `/review-prs` workflow to merge PRs into the release branch (`release/vX.Y.Z`) instead of directly into `main`, ensuring proper pre-release staging.\n\n### Coverage\n\n- **2537 tests, 2532 passing** — Statement coverage: 91.95%, Branch coverage: 78.79%, Function coverage: 93.19%\n\n## [3.5.3] - 2026-04-07\n\n### Сигурност\n\n- **Vulnerabilities:** Fully remediated 12 High-Severity CodeQL vulnerabilities by migrating from Math.random to `crypto.randomUUID()`, wrapping SSE injection points with aggressive backslash escaping, sanitizing trailing HTTP fragments, and enforcing rigid SSRF HTTP verification schemes across internal routes.\n- **Dependencies:** Upgraded Next.js to `^16.2.2` and Vite to `>=8.0.5` resolving critical DoS, arbitrary file reads and CSRF vectors in the build/server environments.\n\n### Fixed\n\n- **E2E Stability:** Eliminated extreme CI unreliability and transient test timeouts (Playwright) by propagating internal standalone `_next/static` assets properly and refactoring deep UI interactions inside defensive `expect().toPass()` loops.\n- **Middleware:** Resolved infinite redirect loop on dashboard for fresh instances when requireLogin is disabled.\n- **Core Fallbacks:** Preserved primary failure contexts and enhanced Edge-case error handling pipelines across chat and fallback loops.\n- **Proxy/Hooks:** Optimized local git hooks, normalized token coverage endpoints into `/coverage`, and guarded GLM region lookups.\n\n### 🛠️ Maintenance\n\n- **CI/CD Stabilization:** Prevented random GitHub Runner freezes by decoupling sharded processes, adjusting test concurrencies, unref-ing active connections on server teardown, and strictly capping job timeout durations.\n\n### Документация\n\n- **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned).\n\n### Coverage\n\n- **Testing:** Consolidated the workspace test coverage framework hitting 92.1% statement line coverage, with new rigid unit-tests matching API key policies and tool scopes.\n\n---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n- **Qoder API Native Integration:** Completely refactored the Qoder Executor to bypass the legacy COSY AES/RSA encryption algorithm, routing directly into the native DashScope OpenAi-compatible URL. Eliminates complex dependencies on Node `crypto` modules while improving stream fidelity.\n- **Resilience Engine Overhaul:** Integrated context overflow graceful fallbacks, proactive OAuth token detection, and empty-content emission prevention (#990).\n- **Context-Optimized Routing Strategy:** Added new intelligent routing capability to natively maximize context windows in automated combo deployments (#990).\n\n### 🐛 Bug Fixes\n\n- **Responses API Stream Corruption:** Fixed deep-cloning corruption where Anthropic/OpenAI translation boundaries stripped `response.` specific SSE prefixes from streaming boundaries (#992).\n- **Claude Cache Passthrough Alignment:** Aligned CC-Compatible cache markers consistently with upstream Client Pass-Through mode preserving prompt caching.\n- **Turbopack Memory Leak:** Pinned Next.js to strict `16.0.10` preventing memory leaks and build staleness from recent upstream Turbopack hashed module regressions (#987).\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **Models.dev Integration:** Integrated models.dev as the authoritative runtime source for model pricing, capabilities, and specifications, overriding hardcoded prices. Includes a settings UI to manage sync intervals, translation strings for all 30 languages, and robust test coverage.\n- **Provider Native Capabilities:** Added support for declaring and checking native API features (e.g. `systemInstructions_supported`) preventing failures by sanitizing invalid roles. Currently configured for Gemini Base and Antigravity OAuth providers.\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Сигурност\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Функции\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Сигурност\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Сигурност\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Сигурност\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Документация\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Документация\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Функции\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Функции\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Функции\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Сигурност\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Функции\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Функции\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Функции\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Функции\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Функции\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Функции\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Функции\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Функции\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Сигурност\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\bany\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Функции\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Функции\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Функции\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Функции\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Функции\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Функции\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Документация\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Функции\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "5085dcf96f72bc3ddaf7ac4473bbf9dba31e340b": {"t": 1785765400.284787, "n": 194359, "h": "617572c4bf6a457f", "c": "# Changelog (Български)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.5.3] - 2026-04-05\n\n### Fixed\n\n-**Middleware:**Разрешен безкраен цикъл на пренасочване на таблото за нови екземпляри, когато requireLogin е деактивиран.---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n-**Qoder API Native Integration:**Напълно преработи Qoder Executor, за да заобиколи наследения COZY AES/RSA алгоритъм за криптиране, насочвайки директно към родния DashScope OpenAi-съвместим URL. Елиминира сложните зависимости от `крипто` модулите на Node, като същевременно подобрява прецизността на потока. -**Основен ремонт на Resilience Engine:**Интегрирани грациозни резервни преливания на контекста, проактивно откриване на OAuth токен и предотвратяване на излъчване на празно съдържание (#990). -**Контекстно-оптимизирана стратегия за маршрутизиране:**Добавена е нова възможност за интелигентно маршрутизиране за естествено увеличаване на контекстните прозорци при автоматизирани комбинирани внедрявания (#990).### 🐛 Bug Fixes\n\n-**Повреда на потока на API за отговори:**Коригирана повреда при дълбоко клониране, при която границите на превода на Anthropic/OpenAI лишаваха специфични SSE префикси за `response.` от границите на поточно предаване (#992). -**Claude Cache Passthrough Alignment:**Подравнени CC-съвместими кеш маркери последователно с режим на преминаване на клиента нагоре по веригата, запазвайки бързото кеширане. -**Изтичане на памет на Turbopack:**Прикачен Next.js към стриктно `16.0.10`, предотвратявайки изтичане на памет и неработоспособност на компилация от скорошни регресии на хеширани модули на Turbopack (#987).---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n-**Интегриране на Models.dev:**Интегриран models.dev като авторитетен източник на време за изпълнение за ценообразуване, възможности и спецификации на модела, заменящ твърдо кодирани цени. Включва потребителски интерфейс с настройки за управление на интервали на синхронизиране, низове за превод за всичките 30 езика и надеждно тестово покритие. -**Собствени възможности на доставчика:**Добавена е поддръжка за деклариране и проверка на естествени функции на API (напр. `systemInstructions_supported`), предотвратяващи грешки чрез дезинфекция на невалидни роли. В момента е конфигуриран за Gemini Base и Antigravity OAuth доставчици. -**Разширени настройки на доставчика на API:**Добавени са персонализирани заменки на `User-Agent` за всяка връзка за връзки с доставчик на API ключ. Замяната се съхранява в `providerSpecificData.customUserAgent` и сега се прилага за проверки за валидиране и заявки за изпълнение нагоре.### 🐛 Bug Fixes\n\n-**Надеждност на Qwen OAuth:**Решени са поредица от проблеми с интегрирането на OAuth, включително блокер за 400 лоши заявки за изтекли токени, резервно генериране за анализиране на свойствата на OIDC `access_token`, когато `id_token` е пропуснато, грешки при откриване на каталог на модели и стриктно филтриране на заглавки `X-Dashscope-*`, за да се избегне 400 отхвърляне от OpenAI-съвместими крайни точки.## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n-**Auto-Combo & Routing:**Завършена собствена интеграция на жизнения цикъл на CRUD за усъвършенствания Auto-Combo двигател (#955). -**Основни операции:**Коригирани липсващи преводи за нови собствени опции за автоматични комбинации (#955). -**Проверка на сигурността:**Деактивирани задачи за автоматично архивиране на SQLite по време на изпълнение на CI на модулен тест, за изрично разрешаване на висящи течове на памет на Node 22 Event Loop (#956). -**Екосистемни проксита:**Завършени планировчици за синхронизиране на модели за изрично картографиране на интеграция, OAuth цикли и Token Check се опресняват безопасно чрез собствените проксита на системата нагоре по веригата на OmniRoute (#953). -**MCP Extensibility:**Добавен и успешно регистриран новият инструмент за MCP рамка `omniroute_web_search` извън бета версия в производствени схеми (#951). -**Tokens Buffer Logic:**Добавени лимити за конфигурация по време на изпълнение, разширяващи конфигурируемите входно/изходни буфери за токени за прецизни показатели за проследяване на използването (#959).### 🐛 Bug Fixes\n\n-**CodeQL Remediation:**Напълно разрешени и защитени критични операции за индексиране на низове, предотвратяващи евристични индексиращи масиви от фалшифициране на заявки от страна на сървъра (SSRF), заедно с полиномиално алгоритмично проследяване (ReDoS) в модулите за дълбок диспечер на прокси. -**Крипто хешове:**Заменени са слабите непроверени наследени хешове на OAuth 1.0 със стабилни стандартни примитиви за валидиране HMAC-SHA-256, осигуряващи строг контрол на достъпа. -**API Boundary Protection:**Правилно проверени и картографирани структурни защити на маршрута, налагащи стриктна `isAuthenticated()` логика на междинния софтуер, покриваща по-нови динамични крайни точки, насочени към манипулиране на настройките и зареждане на собствени умения. -**CLI Ecosystem Compat:**Разрешени повредени нативни обвързвания на парсера по време на изпълнение, сриващи детекторите за среда `where` стриктно над крайните случаи `.cmd/.exe` грациозно за външни плъгини (#969). -**Архитектура на кеша:**Рефакторинг на точните параметри на таблото за управление на анализите и системните настройки, кеширане на структурата на оформлението, за да се поддържат стабилни цикли на устойчивост на повторна хидратация, разрешаващи мигания на визуално неподравнено състояние (#952). -**Стандарти за кеширане на Claude:**Нормализирани и точно запазени критични ефимерни блокови маркери „ефимерни“ кеширащи TTL поръчки за възли надолу по веригата, налагащи стандартно съвместими CC заявки, картографирани чисто без изпуснати показатели (#948). -**Вътрешни псевдоними Auth:**Опростени вътрешни съпоставяния по време на изпълнение, нормализиране на търсенето на полезни данни за идентификационни данни на Codex в глобалните параметри за превод, разрешаващи 401 неудостоверени изпускания (#958).### 🛠️ Maintenance\n\n-**Откриваемост на потребителския интерфейс:**Правилно коригирани категоризации на оформлението, изрично разделящи логиката на доставчиците на безплатни нива, подобряващи потоците за UX сортиране в общите страници на регистъра на API (#950). -**Топология на внедряване:**Унифицирани артефакти за внедряване на Docker, гарантиращи, че основният `fly.toml` съвпада с очакваните параметри на екземпляра на облака извън кутията, като нативно управлява автоматично мащабиране на автоматизираните внедрявания. -**Инструменти за разработка:**Отделени параметри за изпълнение на `LKGP` в експлицитни помощни програми за кеширане на абстракция на DB слой, осигуряващи безопасно покритие на стриктна изолация на теста за основните кеширащи слоеве.---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n-**Панел за автоматично комбиниране на таблото:**Напълно преработен потребителският интерфейс на `/dashboard/auto-combo`, за да се интегрира безпроблемно с оригиналните карти на таблото и стандартизираните визуални подложки/заглавки. Добавени динамични визуални ленти за напредък, картографиращи механизми за тегло на избора на модел. -**Синхронизиране на маршрутизирането на настройките:**Напълно разкрити `приоритетни` и `претеглени` цели на схемата за разширено маршрутизиране вътрешно в резервните списъци с глобални настройки.### Bug Fixes\n\n-**Locale Nodes за памет и умения:**Разрешени празни тагове за изобразяване за опциите за памет и умения директно в изгледите на глобалните настройки чрез свързване на всички стойности на `settings.*` вътрешно картографиране в `en.json` (също картографирано имплицитно за инструменти за кръстосано превеждане).### Internal Integrations\n\n- Интегриран PR #946 — поправка: запазване на съвместимостта на Claude Code при преобразуването на отговорите\n- Интегриран PR #944 — fix(gemini): запазване на сигнатури на мисли при извиквания на антигравитационни инструменти\n- Интегриран PR #943 — поправка: възстановяване на тялото на GitHub Copilot\n- Интегриран PR #942 - Коригиране на cc-съвместими кеш маркери\n- Интегриран PR #941 — refactor(auth): подобряване на търсенето на псевдоним на NVIDIA + добавяне на LKGP регистриране на грешки\n- Интегриран PR #939 — Възстановяване на Claude OAuth обработка на обратно извикване на локален хост\n- _(Забележка: PR #934 беше пропуснат от цикъла 3.4.9, за да се предотвратят основни конфликтни регресии)_---\n\n## [3.4.8] — 2026-04-03\n\n### Сигурност\n\n- Напълно коригирани всички неизпълнени констатации на Github Advanced Security (CodeQL) и предупреждения на Dependabot.\n- Коригирани несигурни уязвимости на случаен принцип чрез мигриране от `Math.random` към `crypto.randomUUID()`.\n- Защитени команди на обвивката в автоматизирани скриптове от инжектиране на низове.\n- Мигрирани уязвими катастрофални обратно проследяване на RegEx модели за анализиране в канали за чат/превод.\n- Подобрени контроли за дезинфекция на изхода в компонентите на потребителския интерфейс на React и инжектиране на тагове за изпратени от сървъра събития (SSE).---\n\n## [3.4.7] — 2026-04-03\n\n### Функции\n\n- Добавен възел `Криптография` към проверките на състоянието за наблюдение и MCP (#798)\n- Подсилено съпоставяне на разрешения за маршрут на модел-каталог (`/models`) (#781)### Bug Fixes\n\n- Коригирани опреснявания на токени на Claude OAuth, които не успяват да запазят контекстите на кеша (#937)\n- Коригирани грешки на CC-съвместим доставчик, които правят кешираните модели недостъпни (#937)\n- Коригирани грешки на GitHub Executor, свързани с невалидни контекстни масиви (#937)\n- Коригирани грешки при проверка на изправността на CLI инструменти, инсталирани на NPM в Windows (#935)\n- Коригиран превод на полезен товар, изпускащ валидно съдържание поради невалидни API полета (#927)\n- Коригиран срив по време на изпълнение във възел 25 по отношение на изпълнението на API ключ (#867)\n- Коригирано разрешаване на самостоятелен модул на MCP (`ERR_MODULE_NOT_FOUND`) чрез `esbuild` (#936)\n- Коригирано несъответствие на псевдоним на разрешаване на идентификационни данни за NVIDIA NIM (#931)### Сигурност\n\n- Добавена безопасна стриктна защита на входните граници срещу необработени инжекции за изпълнение на дистанционен код `shell: true`.---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n-**Доставчици:**Регистрирани нови доставчици за генериране на изображения, видео и аудио от списъка, поискан от общността (#926). -**Потребителски интерфейс на таблото:**Добавена е самостоятелна навигация в страничната лента за новите модули памет и умения (#926). -**i18n:**Добавени низове за превод и съпоставяне на оформлението на 30 езика за пространствата от имена на паметта и уменията.### 🐛 Bug Fixes\n\n-**Устойчивост:**Предотвратено засядане на прокси прекъсвача в ОТВОРЕНО състояние за неопределено време чрез обработка на директни преходи към ЗАТВОРЕНО състояние в резервни комбинирани пътища (#930). -**Превод на протоколи:**Извършен е корекция на трансформатора за поточно предаване, за да дезинфекцира блоковете за отговор въз основа на очаквания _source_ протокол, а не на _target_ протокола на доставчика, коригирайки модели на Anthropics, обвити в полезни натоварвания на OpenAI, сриващи Claude Code (#929). -**API спецификации и Gemini:**Коригирано анализиране на `thought_signature` в преводачите `openai-to-gemini` и `claude-to-gemini`, предотвратявайки HTTP 400 грешки във всички Gemini 3 API извиквания на инструменти. -**Доставчици:**Изчистени крайни точки, които не са съвместими с OpenAI, предотвратявайки валидни връзки нагоре (#926). -**Тенденции в кеша:**Поправено е несъответствие на данни за картографиране на невалидни свойства, причиняващо срив на диаграмите на потребителския интерфейс на тенденциите в кеша, и извлечени излишни джунджурии за показатели на кеша (#926).---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n-**CLIProxyAPI екосистемна интеграция:**Добавен е изпълнителят `cliproxyapi` с вградено кеширане на ниво модул и прокси маршрутизиране. Въведена е цялостна услуга за управление на версиите за автоматично тестване на изправността, изтегляне на двоични файлове от GitHub, създаване на изолирани фонови процеси и чисто управление на жизнения цикъл на външни CLI инструменти директно през потребителския интерфейс. Включва DB таблици за прокси конфигурация, за да се даде възможност за автоматично SSRF-зависимо кръстосано маршрутизиране на външни OpenAI заявки чрез локалния CLI инструмент слой (#914, #915, #916). -**Поддръжка на Qoder PAT:**Поддръжка на интегрирани токени за персонален достъп (PAT) директно чрез локалния транспорт `qodercli` вместо наследените отдалечени `.cn` конфигурации на браузъра (#913). -**Gemini 3.1 Pro Preview (GitHub):**Добавена е `gemini-3.1-pro-preview` канонична изрична поддръжка на модел в GitHub Copilot доставчик, като същевременно се запазват по-стари псевдоними за маршрутизиране (#924).### 🐛 Bug Fixes\n\n-**Стабилност на GitHub Copilot Token:**Поправен е цикълът за опресняване на Copilot token, където остарелите токени не са били дълбоко обединени в DB, ​​и премахнати полета `reasoning_text`, които фатално нарушаваха блоковите преобразувания на Anthropic надолу по веригата за многооборотни чатове (#923). -**Глобална матрица на изчакване:**Централизирани и параметризирани изчаквания на заявка изрично от `REQUEST_TIMEOUT_MS` за предотвратяване на скрити (~300 s) буфери за извличане по подразбиране, които преждевременно прекъсват дълготрайните SSE поточни отговори от тежки модели на разсъждение (#918). -**Cloudflare Quick Tunnels State:**Поправено е сериозно несъответствие на състоянието, при което рестартирани екземпляри на OmniRoute погрешно показват унищожени тунели като активни и тунелиране по подразбиране на cloudflared към `HTTP/2`, за да елиминира нежелана поща в буфера за получаване на UDP (#925). -**i18n Преработка на превода (чешки и хинди):**Фиксиран код на хинди от ОТСТАРЯЛ `in.json` към каноничен `hi.json`, преработени съпоставяния на чешки текст, извлечен `untranslatable-keys.json` за коригиране на фалшиво положителни валидации на CI/CD и генерирани изчерпателни `I18N.md` документи за насочване на преводачите (#912). -**Възстановяване на доставчик на токени:**Поправено е Qwen, губейки специфични крайни точки на `resourceUrl` след автоматично опресняване на маркера за проверка на състоянието поради липсващи дълбоки сливания на DB (#917). -**CC Съвместим UX & Streaming:**Унифицира Добавяне на CC/OpenAI/Anthropic съвместими действия около обработката на Anthropic UI, принудени CC-съвместими заявки нагоре да използват SSE, като същевременно връщат стрийминг или не-стрийминг отговори въз основа на клиентската заявка, премахна CC конфигурация на списък с модели/поддръжка за импортиране в полза на изрична грешка в списъка с неподдържани модели и направи CC-съвместим Наличните модели отразяват списъка на регистъра на OAuth Claude Code (#921).---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n-**Responses API Token Reporting:**Излъчва `response.completed` с правилни полета `input_tokens`/`output_tokens` за клиенти на Codex CLI, коригирайки показването на използването на токени (#909 — благодаря @christopher-s). -**Проверка на SQLite WAL при изключване:**Промиване на WAL промените в основния файл на базата данни по време на грациозно изключване/рестартиране, предотвратявайки загуба на данни при спиране на Docker контейнер (#905 — благодаря @rdself). -**Изящен сигнал за изключване:**Променени са маршрутите `/api/restart` и `/api/shutdown` от `process.exit(0)` на `process.kill(SIGTERM)`, като се гарантира, че манипулаторът за изключване работи преди изход. -**Гратисен период на спиране на Docker:**Добавен е `stop_grace_period: 40s` към файловете за съставяне на Docker и `--stop-timeout 40` към примерите за изпълнение на Docker.### 🛠️ Maintenance\n\n- Затворени 5 решени/не-бъг проблема (#872, #814, #816, #890, #877).\n- Разпределени 6 проблема с искания за информация за нуждите (#892, #887, #886, #865, #895, #870).\n- Отговор на проблем с проследяване на откриване на CLI (#863) с насоки на сътрудници.---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n-**Памет и умения за Antigravity:**Завършено дистанционно инжектиране на памет и умения за доставчика на Antigravity на ниво прокси мрежа. -**Съвместимост с Claude Code:**Създаден естествен скрит мост за съвместимост за Claude Code, като прехвърля инструменти и форматиране чисто. -**MCP за търсене в мрежата:**Добавен е инструментът `omniroute_web_search` с обхвата `execute:search`. -**Кеш компоненти:**Внедрени динамични кеш компоненти, използващи TDD. -**Потребителски интерфейс и персонализиране:**Добавена персонализирана поддръжка на favicon, раздели за външен вид, бели етикети с кабел към страничната лента и добавени стъпки за ръководство за Windsurf на всички 33 езика. -**Запазване на регистрационни файлове:**Унифицирано запазване на регистрационни файлове на заявки и първоначално артефакти. -**Подобрения на модела:**Добавено е изрично `contextLength` за всички opencode-zen модели. -**i18n & преводи:**Интегрирани нативни преводи на 33 езика, включително CI валидации на контейнер и актуализации на документация на китайски (#873, #869).### 🐛 Bug Fixes\n\n-**Qwen OAuth Mapping:**Възстановена зависимостта на `id_token` към `access_token` и активирано динамично инжектиране на крайна точка на API `resource_url` за правилно регионално маршрутизиране (#900). -**Model Sync Engine:**Съхранява стриктния вътрешен идентификатор на доставчика в рутинните процедури за синхронизиране на `getCustomModels()` вместо във формата на псевдонима на UI канал, предотвратявайки грешки при вмъкване на SQLite каталог (#903). -**Claude Code & Codex:**Стандартизирани непоточно предавани празни отговори на Anthropic-форматиран `(празен отговор)` за предотвратяване на сривове на CLI прокси (#866). -**CC Съвместимо маршрутизиране:**Разрешен дублиран сблъсък на крайни точки `/v1` по време на конкатенация на пътя за генерични шлюзове на Claude Code (#904). -**Антигравитационни табла за управление:**Блокирани модели с неограничена квота от фалшиво регистриране като изчерпани гранични състояния на `100% използване` в потребителския интерфейс за използване на доставчика (#857). -**Claude Image Passthrough:**Коригирани модели на Claude с липсващи пропуски на блокове на изображения (#898). -**Gemini CLI Routing:**Разрешени са 403 блокировки на авторизация и проблеми с натрупването на съдържание чрез опресняване на ID на проекта чрез `loadCodeAssist` (#868). -**Стабилност на антигравитацията:**Коригирани списъци за достъп на модела, наложени 404 блокирания, поправени 429 каскади, блокиращи стандартни връзки, и ограничени изходни токени `gemini-3.1-pro` (#885). -**Каданс на синхронизиране на доставчика:**Поправен е ритъмът на синхронизиране на ограниченията на доставчика чрез вътрешния планировчик (#888). -**Оптимизация на таблото за управление:**Решено замразяване на потребителския интерфейс на `/dashboard/limits` при обработка на 70+ акаунта чрез паралелизиране на парчета (#784). -**SSRF Hardening:**Наложи стриктно филтриране на SSRF IP обхвата и блокира `::1` loopback интерфейса. -**MIME типове:**Стандартизиран `mime_type` към snake_case, за да съответства на спецификациите на Gemini API. -**CI стабилизиране:**Коригирани неуспешни анализи/настройки Playwright селектори и твърдения за заявки, така че GitHub Actions E2E изпълнява надеждно през локализирани потребителски интерфейси и базирани на превключватели контроли. -**Детерминистични тестове:**Премахнати чувствителни към датата квоти от тестовете за използване на Copilot и съгласувани тестове за идемпотентност/моделен каталог с обединеното поведение по време на изпълнение. -**MCP Type Hardening:**Премахнати явни регресии с нулев бюджет от „никакви“ регресии от регистрационния път на MCP сървърния инструмент. -**Model Sync Engine:**Прескочени разрушителни `replace` замени, когато автоматичното синхронизиране на доставчика дава празен списък с модели, поддържайки стабилност за динамични каталози (#899).### 🛠️ Maintenance\n\n-**Регистриране на тръбопроводи:**Подобрени артефакти за регистриране на тръбопроводи и налагане на ограничения за задържане (#880). -**AGENTS.md Основен ремонт:**Съкратено от 297→153 реда. Добавени са насоки за изграждане/тест/стил, работни потоци на код (Prettier, TypeScript, ESLint) и изрязани подробни таблици (#882). -**Интегриране на клонове на изданието:**Консолидира клоновете на активните функции в `release/v3.4.2` върху текущото `main` и валидира клона с изпълнения на lint, unit, coverage, build и CI-mode E2E. -**Тестване:**Добавена конфигурация на vitest за тестване на компоненти и спецификации на Playwright за превключвания на настройките. -**Актуализации на документи:**Разширено root readme, преведени оригинални китайски документи и изчистени остарели файлове.## [3.4.1] - 2026-03-31\n\n> [!ПРЕДУПРЕЖДЕНИЕ]\n> **ВЪЗЛОЖНА ПРОМЯНА: променливите на средата за регистриране на заявки, задържане и регистриране са преработени.**\n> При първото стартиране след надграждане OmniRoute архивира наследени журнали на заявки от `DATA_DIR/logs/`, наследени `DATA_DIR/call_logs/` и `DATA_DIR/log.txt` в `DATA_DIR/log_archives/*.zip`, след което премахва остарялото оформление и превключва към новия обединен артефакт формат под `DATA_DIR/call_logs/`.### ✨ New Features\n\n-**.ENV Migration Utility:**Включен `scripts/migrate-env.mjs` за безпроблемно мигриране на ``, когато е включен ограничен достъп (#781) -**Интеграция на Qoder:**Вградена интеграция за Qoder AI, която естествено заменя картите на наследената платформа iFlow (#660) -**Проследяване на бърз кеш:**Добавени възможности за проследяване и визуализация на интерфейса (карта със статистика) за семантично и бързо кеширане в потребителския интерфейс на таблото### 🐛 Bug Fixes\n\n-**Оразмеряване на таблото за управление на кеша:**Подобрени са размерите на оформлението на потребителския интерфейс и контекстните заглавки за разширените страници на кеша (#835) -**Видимост на страничната лента за отстраняване на грешки:**Коригиран проблем, при който превключвателят за отстраняване на грешки не показваше/скрива правилно детайлите за отстраняване на грешки в страничната лента (#834) -**Префикс на Gemini Model:**Променено резервното пространство на имената, за да се маршрутизира правилно чрез `gemini-cli/` вместо `gc/`, за да се спазват спецификациите нагоре (#831) -**OpenRouter Sync:**Подобрена синхронизация на съвместимостта за автоматично приемане на каталога с налични модели правилно от OpenRouter (#830) -**Картографиране на полезни натоварвания за поточно предаване:**Ресериализацията на полетата за разсъждение естествено разрешава конфликтни пътища на псевдоними, когато изходът се предава към крайни устройства---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n-**OpenCode Config:**Преструктуриран генериран `opencode.json`, за да използва схемата, базирана на записи `@ai-sdk/openai-compatible` с `options` и `models` като карти на обекти вместо плоски масиви, поправяйки грешки при валидиране на конфигурацията (#816) -**i18n Missing Keys:**Добавен липсващ ключ за превод `cloudflaredUrlNotice` във всичките 30 езикови файла, за да се предотвратят грешки в конзолата `MISSING_MESSAGE` в страницата Endpoint (#823)---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n-**Отчитане на токени:**Включени токени за бързо кеширане безопасно в изчисленията на входните данни за историческо използване за правилни удръжки от квоти (PR #822) -**Комбинирани тестови сонди:**Коригирани фалшиви негативи на логиката на комбо тестване чрез разрешаване на синтактичния анализ за отговори само с разсъждения и активиране на масивна паралелизация чрез Promise.all (PR #828) -**Docker Quick Tunnels:**Вградени задължителни ca-сертификати в основния контейнер за изпълнение за разрешаване на грешки при стартиране на Cloudflared TLS и открити stdout мрежови грешки, заместващи общи кодове за изход (PR #829)---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n-**Проследяване на квота на Gemini:**Добавено проследяване на квота на Gemini CLI в реално време чрез API `retrieveUserQuota` (PR #825) -**Табло за управление на кеша:**Подобрено таблото за управление на кеша, за да показва бързи показатели на кеша, 24-часови тенденции и очаквани икономии на разходи (PR #824)### 🐛 Bug Fixes\n\n-**Потребителско изживяване:**Премахнати инвазивни автоматично отварящи се OAuth модални цикли на безплодни страници с подробни данни за доставчик (PR #820) -**Актуализации на зависимостите:**Подобрени и заключени зависимости за разработка и производствени дървета, включително Next.js 16.2.1, Recharts и TailwindCSS 4.2.2 (PR #826, #827)---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n-**A2A работни потоци:**Добавен детерминистичен FSM оркестратор за многоетапни работни потоци на агенти. -**Изящна деградация:**Добавена е нова многослойна резервна рамка за запазване на основната функционалност по време на частични прекъсвания на системата. -**Одит на конфигурация:**Добавена е одитна пътека с откриване на разлика за проследяване на промените и активиране на връщане назад на конфигурацията. -**Здраве на доставчика:**Добавено проследяване на срока на валидност на доставчика с проактивни известия за потребителския интерфейс за изтичащи API ключове. -**Адаптивно маршрутизиране:**Добавен е адаптивен детектор за обем и сложност, за да замени стратегиите за маршрутизиране динамично въз основа на натоварването. -**Разнообразие на доставчиците:**Внедрено оценяване на разнообразието на доставчиците чрез ентропията на Шанън за подобряване на разпределението на натоварването. -**Граници за автоматично деактивиране:**Добавено е превключване на настройка за автоматично деактивиране на забранени акаунти към таблото за управление на устойчивостта.### 🐛 Bug Fixes\n\n-**Съвместимост с Codex & Claude:**Фиксирани резервни потребителски интерфейси, коригирани проблеми с интегрирането на Codex без поточно предаване и разрешено откриване на време за изпълнение на CLI в Windows. -**Автоматизация на пускането:**Изискват се разширени разрешения за изграждането на приложението Electron в GitHub Actions. -**Cloudflare Runtime:**Обърнато е внимание на правилните изходни кодове за изолация по време на изпълнение за тунелни компоненти на Cloudflared.### 🧪 Tests\n\n-**Актуализации на пакета за тестване:**Разширено тестово покритие за детектори за обем, разнообразие на доставчици, одит на конфигурация и FSM.---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n-**CI/CD Надеждност:**Пачирани действия на GitHub към стабилни версии на зависимости (`actions/checkout@v4`, `actions/upload-artifact@v4`) за смекчаване на необявени отписвания на среда за изграждане. -**Резервни изображения:**Заменени произволни резервни вериги в `ProviderIcon.tsx` с изрично валидиране на активи, за да се предотврати зареждането на UI компоненти `` компоненти за файлове, които не съществуват, елиминирайки `404` грешки в регистрационните файлове на конзолата на таблото (#745). -**Програма за актуализация на администратора:**Динамично откриване на инсталация на източник за програмата за актуализация на таблото. Безопасно деактивира бутона „Актуализиране сега“, когато OmniRoute е изграден локално, а не чрез npm, подканвайки за „git pull“ (#743). -**Грешка при актуализиране на ERESOLVE:**Инжектира `package.json` замени за `react`/`react-dom` и активира `--legacy-peer-deps` във вътрешните скриптове за автоматична актуализация за разрешаване на нарушаващи конфликти на дървото на зависимости с `@lobehub/ui`.---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n-**Cloudflare Tunnels:**Cloudflare Quick Tunnel интеграция с контроли на таблото (PR #772). -**Диагностика:**Семантичен байпас на кеша за комбо тестове на живо (PR #773).### 🐛 Bug Fixes\n\n-**Стабилност на поточно предаване:**Приложете `FETCH_TIMEOUT_MS` към първоначалното извикване `fetch()` на исканията за поточно предаване, за да предотвратите 300s Node.js TCP таймаут, причиняващ неуспешни неуспешни задачи (#769). -**i18n:**Добавяне на липсващи записи `windsurf` и `copilot` към `toolDescriptions` във всичките 33 локални файла (#748). -**Одит на GLM кодиране:**Пълен одит на доставчика, коригиращ ReDoS уязвимости, оразмеряване на контекстния прозорец (128k/16k) и синхронизиране на системния регистър на модела (PR #778).---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n-**OpenAI Codex:**Корекция на резервна обработка за елементи `type: \"text\"`, носещи нулеви или празни набори от данни, които причиняват отхвърляне 400 (#742). -**Отворен код:**Актуализирайте подравняването на схемата към единствения „доставчик“, за да съответства на официалната спецификация (#774). -**Gemini CLI:**Инжектиране на липсващи заглавки на квоти за крайни потребители, предотвратяващи блокиране на авторизация 403 (#775). -**Възстановяване на DB:**Рефакторинг импортиране на полезен товар от много части в необработени двоични буферирани масиви, за да се заобиколят ограниченията за максимален обем на обратния прокси (#770).---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Стабилизиране на изданието**— Финализирано издание v3.2.9 (комбинирана диагностика, порти за качество, корекция на инструмента Gemini) и създаден липсващ git таг. Консолидирани всички поетапни промени в едно атомарно освобождаване.### 🐛 Bug Fixes\n\n-**Auto-Update Test**— Коригирано `buildDockerComposeUpdateScript` тестово твърдение, за да съответства на неразширени препратки към променливи на обвивката (`$TARGET_TAG`, `${TARGET_TAG#v}`) в генерирания скрипт за внедряване, подравнявайки се с преработения шаблон от v3.2.8. -**Circuit Breaker Test**— Укрепен `combo-circuit-breaker.test.mjs` чрез инжектиране на `maxRetries: 0`, за да се предотврати увеличаването на повторния опит от изкривяване на твърденията за броя на неизправностите по време на преходите на състоянието на прекъсвача.---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Комбинирана диагностика**— Въведен е флаг за байпас на теста на живо (`forceLiveComboTest`), позволяващ на администраторите да изпълняват реални проверки на здравето нагоре, които байпасират всички локални механизми за прекъсване на веригата и състояние на охлаждане, което позволява прецизна диагностика по време на прекъсвания (PR #759) -**Quality Gates**— Добавено автоматизирано валидиране на качеството на отговора за комбинации и официално интегрирана поддръжка на модела `claude-4.6` в основните схеми за маршрутизиране (PR #762)### 🐛 Bug Fixes\n\n-**Проверка на дефиницията на инструмента**— Поправена интеграция на API на Gemini чрез нормализиране на типовете enum в дефинициите на инструмента, предотвратявайки грешки на HTTP 400 параметри нагоре (PR #760)---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Docker Auto-Update UI**— Интегриран отделен процес на фоново актуализиране за разполагания на Docker Compose. Потребителският интерфейс на таблото за управление вече безпроблемно проследява събития от жизнения цикъл на актуализацията, комбинирайки JSON REST отговори с наслагвания за напредък на SSE поточно предаване за стабилна надеждност в различни среди. -**Cache Analytics**— Поправено картографиране на визуализация с нулеви показатели чрез мигриране на телеметрични регистрационни файлове на Semantic Cache директно в модула за централизирано проследяване SQLite.### 🐛 Bug Fixes\n\n-**Authentication Logic**— Коригирана грешка, при която запазването на настройките на таблото за управление или добавянето на модели се провали с грешка 401 Unauthorized, когато `requireLogin` беше деактивирано. Крайните точки на API вече оценяват правилно превключвателя за глобално удостоверяване. Разрешено е глобалното пренасочване чрез повторно активиране на `src/middleware.ts`. -**CLI Tool Detection (Windows)**— Предотвратени са фатални изключения при инициализация по време на откриване на среда на CLI чрез правилно улавяне на ENOENT грешки `cross-spawn`. Добавя изрични пътища за откриване за `\\AppData\\Local\\droid\\droid.exe`. -**Codex Native Passthrough**— Нормализирани параметри за превод на модела, предотвратяващи отравяне на контекста в прокси режим на преминаване, налагайки общи ограничения `store: false` изрично за всички заявки, създадени от Codex. -**SSE Token Reporting**— Нормализирано откриване на `finish_reason` на част от извикването на инструмента на доставчика, коригиране на 0% Анализ на използването за отговори само за поток, при които липсват стриктни индикатори ``. -**DeepSeek тагове**— Внедрено е изрично картографиране на извличане на `` вътре в `responsesHandler.ts`, като се гарантира, че потоците от разсъждения на DeepSeek се картографират еквивалентно на собствените антропни `` структури.---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n-**Безпроблемни актуализации на потребителския интерфейс**: Функцията „Актуализиране сега“ на таблото за управление вече осигурява жива, прозрачна обратна връзка с помощта на изпратени от сървъра събития (SSE). Той извършва инсталиране на пакети, преустройване на родния модул (better-sqlite3) и PM2 се рестартира надеждно, докато показва зареждащи програми в реално време, вместо безшумно да виси.---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**API Key Reveal (#740)**— Добавен поток на копиране на API ключ с обхват в API Manager, защитен от променливата на средата `ALLOW_API_KEY_REVEAL`. -**Контроли за видимост на страничната лента (#739)**— Администраторите вече могат да скриват всяка навигационна връзка в страничната лента чрез настройките за външен вид, за да намалят визуалния безпорядък. -**Строго комбо тестване (#735)**— Втвърди крайната точка за проверка на изправността на комбо, за да изисква текстови отговори на живо от моделите вместо само меки сигнали за достижимост. -**Поточно предавани подробни регистрационни файлове (#734)**— Превключено регистриране на подробни заявки за SSE потоци, за да се реконструира крайният полезен товар, спестявайки огромни количества от размера на базата данни на SQLite и значително почиствайки потребителския интерфейс.### 🐛 Bug Fixes\n\n-**OpenCode Go MiniMax Auth (#733)**— Коригирана е логиката на хедъра за удостоверяване за моделите `minimax` на OpenCode Go, за да се използва `x-api-key` вместо стандартни токени за носител през протокола `/messages`.---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Void Linux Deployment Support (#732)**— Интегриран `xbps-src` шаблон за опаковане и инструкции за естествено компилиране и инсталиране на OmniRoute с `better-sqlite3` свързвания чрез цел за кръстосано компилиране.## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Qoder AI Migration (#660)**— Напълно мигрира наследения основен доставчик на `iFlow` към `Qoder AI`, поддържайки стабилни възможности за маршрутизиране на API.### 🐛 Bug Fixes\n\n-**Gemini Tools HTTP 400 Payload Invalid Argument (#731)**— Предотвратени инжекции на масиви `thoughtSignature` в стандартните последователности Gemini `functionCall`, блокиращи потоците на агентно маршрутизиране.---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Потребителски интерфейс на квоти за граници на доставчика (#728)**— Нормализирана логика за ограничаване на квоти и етикетиране на данни в интерфейса за ограничения.### 🐛 Bug Fixes\n\n-**Core Routing Schemas & Leaks**— Разширена `comboStrategySchema` за естествена поддръжка на `fill-first` и `p2c` стратегии за деблокиране на сложни комбо редактиране нативно. -**Извличане на мислещи етикети (CLI)**— Преструктуриран инструмент за дезинфекция на отговорите на токени на CLI RegEx, улавящ структурите на разсъжденията на модела вътре в потоците, избягвайки повредени извличания на `<мислене>`, нарушаващи изходния формат на текста на отговора. -**Налагане на строги формати**— Засилено изпълнение на дезинфекция на тръбопровода, което го прави универсално приложим към цели в режим на превод.---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n-**Тръбопровод на регистрационен файл с четири етапа на заявка (#705)**— Рефакторинг на постоянството на регистрационния файл, за да се запазят изчерпателни полезни натоварвания на четири отделни етапа на тръбопровода: заявка на клиент, заявка на преведен доставчик, отговор на доставчик и преведен отговор на клиент. Въведен е `streamPayloadCollector` за стабилно съкращаване на SSE поток и сериализация на полезния товар.### 🐛 Bug Fixes\n\n-**Поправки на потребителския интерфейс за мобилни устройства (#659)**— Предотвратява компонентите на таблицата на таблото за управление да нарушават оформлението на тесни прозорци за изглед чрез добавяне на правилно хоризонтално превъртане и ограничаване на препълването към `DashboardLayout`. -**Claude Prompt Cache Fixes (#708)**— Гарантирани блокове `cache_control` в резервните вериги Claude-to-Claude са вярно запазени и предадени безопасно обратно към моделите на Anthropic. -**Дефиниции на инструмента Gemini (#725)**— Коригирани грешки при превод на схема при деклариране на прости типове параметри „обект“ за извикване на функция Gemini.## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n-**Глобален резервен доставчик (#689)**— Когато всички комбинирани модели са изчерпани (502/503), OmniRoute сега опитва конфигурируем глобален резервен модел, преди да върне грешката. Задайте `globalFallbackModel` в настройките, за да активирате.### 🐛 Bug Fixes\n\n-**Коригиране #721**— Коригирано заобикаляне на закрепването на контекста по време на отговорите на извикване на инструмент. Маркирането без поточно предаване използва грешен JSON път (`json.messages` → `json.choices[0].message`). Инжектирането на поточно предаване вече се задейства на парчета `finish_reason` за потоци само за извикване на инструменти. `injectModelTag()` вече добавя синтетични пин съобщения за съдържание, което не е низ. -**Коригиране #709**— Потвърдено, че вече е коригирано (v3.1.9) — `system-info.mjs` създава директории рекурсивно. Затворено. -**Коригиране #707**— Потвърдено, че вече е коригирано (v3.1.9) — празно дезинфекция на името на инструмента в `chatCore.ts`. Затворено.### 🧪 Tests\n\n- Добавени са 6 модулни теста за закрепване на контекста с отговори на извикване на инструмент (нулево съдържание, съдържание на масив, двупосочно пътуване, повторно инжектиране)## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n-**Потребителски интерфейс за управление на кеша**— Добавено е специално табло за управление на семантичното кеширане в \\`/dashboard/cache\\` с целенасочено обезсилване на API и поддръжка на i18n на 31 езика (PR #701 от @oyi77) -**Проследяване на GLM квота**— Добавено е проследяване на използването в реално време и квотата на сесиите за доставчика на GLM кодиране (Z.AI) (PR #698 от @christopher-s) -**Подробни полезни натоварвания в регистрационния файл**— Кабелно пълно улавяне на полезния товар в четири етапа на тръбопровода (оригинал, превод, отговор на доставчика, поточно предавани делта) директно в потребителския интерфейс (PR #705 от @rdself)### 🐛 Bug Fixes\n\n-**Коригиране #708**— Предотвратено изтичане на токени за потребители на Claude Code, маршрутизиращи през OmniRoute чрез правилно запазване на родните заглавки \\`cache_control\\` по време на преминаване от Claude към Claude (PR #708 от @tombii) -**Коригиране #719**— Настройте вътрешни граници за удостоверяване за \\`ModelSyncScheduler\\`, за да предотвратите грешки на неудостоверен демон при стартиране (PR #719 от @rdself) -**Коригиране #718**— Възстановено изобразяване на значки в потребителския интерфейс на ограниченията на доставчика, предотвратяващо припокриване на лоши граници на квотите (PR #718 от @rdself) -**Коригиране #704**— Коригирани Combo Fallbacks, нарушаващи HTTP 400 грешки в правилата за съдържание, предотвратяващи мъртвото маршрутизиране на ротацията на модела (PR #704 от @rdself)### 🔒 Security & Dependencies\n\n- Ударен \\`path-to-regexp\\` към \\`8.4.0\\`, разрешаващ dependabot уязвимости (PR #715)## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n-**Коригиране #706**— Коригирано резервно изобразяване на икони, причинено от замяна на `font-sans` на Tailwind V4 чрез прилагане на `!important` към `.material-symbols-outlined`. -**Коригиране #703**— Коригирани повредени потоци на GitHub Copilot чрез активиране на `responses` за превод на формат `openai` за всякакви персонализирани модели, използващи `apiFormat: \"responses\"`. -**Коригиране #702**— Заменено проследяване на използването на фиксирана ставка с точни изчисления на ценообразуването на DB както за поточни, така и за непоточно предавани отговори. -**Коригиране #716**— Почистено състояние на транслация на Claude tool-call, правилно анализиране на поточни аргументи и предотвратяване на OpenAI `tool_calls` части от повтаряне на полето `id`.## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n-**Schema Coercion**— Автоматично принуждаване на низово кодирани цифрови ограничения на JSON схема (напр. `\"минимум\": \"1\"`) към правилните типове, предотвратявайки 400 грешки от Cursor, Cline и други клиенти, изпращащи неправилно формирани схеми на инструменти. -**Дезинизиране на описанието на инструмента**— Уверете се, че описанията на инструментите винаги са низове; преобразува `null`, `undefined` или цифрови описания в празни низове, преди да ги изпрати до доставчиците. -**Бутон за изчистване на всички модели**— Добавени преводи на i18n за действието на доставчика „Изчистване на всички модели“ във всички 30 езика. -**Codex Auth Export**— Добавени са бутони за експортиране на Codex `auth.json` и локално прилагане за безпроблемна CLI интеграция. -**Бележки за Windsurf BYOK**— Добавени са официални предупреждения за ограничения към картата с инструменти на Windsurf CLI, документиращи ограниченията на BYOK.### 🐛 Bug Fixes\n\n-**Коригиране #709**— `system-info.mjs` вече не се срива, когато изходната директория не съществува (добавен `mkdirSync` с рекурсивен флаг). -**Коригиране #710**— A2A `TaskManager` singleton вече използва `globalThis`, за да предотврати изтичане на състояние през повторно компилиране на маршрута на Next.js API в режим за разработка. Пакетът от тестове E2E е актуализиран, за да се справя елегантно с 401. -**Коригиране #711**— Добавено е специфично за доставчика ограничение на `max_tokens` за заявки нагоре. -**Коригиране #605 / #592**— Премахване на префикса `proxy_` от имената на инструменти в не-стрийминг отговори на Claude; фиксиран URL за валидиране на LongCat. -**Call Logs Max Cap**— Надстроен `getMaxCallLogs()` с кеширащ слой, поддръжка на env var (`CALL_LOGS_MAX`) и интегриране на настройките на DB.### 🧪 Tests\n\n- Наборът от тестове е разширен от 964 → 1027 теста (63 нови теста)\n- Добавен `schema-coercion.test.mjs` — 9 теста за принуда на цифрово поле и саниране на описанието на инструмента\n- Добавен `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI интеграционни тестове\n- Подобрен клон за тестове на функции с цялостен инструментариум за покритие### 📁 New Files\n\n| Файл | Цел |\n| -------------------------------------------------------- | ------------------------------------------------------------------------------- | ---------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Принуждаване на схема и помощни програми за саниране на описание на инструмента |\n| `tests/unit/schema-coercion.test.mjs` | Единични тестове за принуда на схема |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | Тестове за интегриране на CLI инструменти |\n| `COVERAGE_PLAN.md` | Документ за планиране на тестовото покритие | ### 🐛 Bug Fixes |\n\n-**Claude Prompt Caching Passthrough**— Коригирани маркери за cache_control, които се премахват в режим на преминаване на Claude (Claude → OmniRoute → Claude), което накара потребителите на Claude Code да изчерпят своята квота за Anthropic API 5-10 пъти по-бързо от директните връзки. OmniRoute вече запазва маркерите cache_control на клиента, когато sourceFormat и targetFormat са Claude, гарантирайки, че бързото кеширане работи правилно и драстично намалява потреблението на токени.## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n-**Ядро на платформата:**Внедрено глобално управление на състоянието за скрити модели и комбинации, което им предотвратява претрупването на каталога или изтичане в свързани MCP агенти (#681). -**Стабилност:**Коригирани сривове на поточно предаване, свързани с неуспешна интеграция на доставчика на Antigravity поради необработени масиви с недефинирани състояния (#684). -**Синхронизиране на локализацията:**Внедрено е напълно обновен синхронизатор `i18n`, откриващ липсващи вложени JSON свойства и пренастройване на 30 локализации последователно (#685).## [3.1.7] - 2026-03-27### 🐛 Bug Fixes\n\n-**Стабилност на поточно предаване:**Коригирано `hasValuableContent`, връщащо `undefined` за празни парчета в SSE потоци (#676). -**Извикване на инструмент:**Коригиран проблем в `sseParser.ts`, при който непоточно предаваните отговори на Claude с множество извиквания на инструмента отпадаха `id` на последващите извиквания на инструмента поради неправилно дедупликиране, базирано на индекс (#671).---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n-**Възстановяване на името на родния инструмент на Claude**— Имената на инструменти като `TodoWrite` вече не са с префикс `proxy_` в отговорите за предаване на Claude (както стрийминг, така и без стрийминг). Включва покритие на единичен тест (PR #663 от @coobabm) -**Clear All Models Alias Cleanup**— Бутонът \"Clear All Models\" вече премахва и свързаните псевдоними на моделите, предотвратявайки призрачни модели в потребителския интерфейс (PR #664 от @rdself)---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n-**Backoff Auto-Decay**— Акаунтите с ограничена скорост вече се възстановяват автоматично, когато изтече прозорецът им за охлаждане, коригирайки блокиране, при което високото `backoffLevel` трайно деприоритизира акаунти (PR #657 от @brendandebeasi)### 🌍 i18n\n\n-**Ревизия на превода на китайски**— Изчерпателно пренаписване на `zh-CN.json` с подобрена точност (PR #658 от @only4copilot)---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n-**Коригиране на поточно предаване**— Явният `stream: true` в тялото на заявката вече има приоритет пред `Accept: application/json` заглавка. Клиентите, изпращащи и двете, ще получат коректно SSE поточно предаване (#656)### 🌍 i18n\n\n-**Подобрения на чешки низове**— Усъвършенствана терминология в `cs.json` (PR #655 от @zen0bit)---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n-**~70 липсващи ключа за превод**добавени към `en.json` и 12 езика (PR #652 от @zen0bit) -**Актуализирана чешка документация**— ръководства за CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT (PR #652) -**Скриптове за проверка на превода**— `check_translations.py` и `validate_translation.py` за CI/QA (PR #651 от @zen0bit)---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n-**Критично: Регресия при извикване на инструмент**— Коригирани грешки `proxy_Bash` чрез деактивиране на префикса на името на инструмента `proxy_` в пътя за преминаване на Claude. Инструменти като `Bash`, `Read`, `Write` бяха преименувани на `proxy_Bash`, `proxy_Read` и т.н., което накара Клод да ги отхвърли (#618) -**Документация за забрана на акаунт в Kiro**— Документирано като фалшиво положително действие срещу AWS срещу измами, а не проблем с OmniRoute (#649)### 🧪 Tests\n\n-**936 теста, 0 неуспеха**---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n-**Метаданни за зрителни възможности**: Добавени са `capabilities.vision`, `input_modalities` и `output_modalities` към записи в `/v1/models` за модели с възможност за зрение (PR #646) -**Модели Gemini 3.1**: Добавени са `gemini-3.1-pro-preview` и `gemini-3.1-flash-lite-preview` към доставчика на Antigravity (#645)### 🐛 Bug Fixes\n\n-**Ollama Cloud 401 Error**: Фиксиран неправилен базов URL адрес на API — променен от `api.ollama.com` на официален `ollama.com/v1/chat/completions` (#643) -**Повторен опит с изтекъл токен**: Добавен ограничен повторен опит с експоненциално забавяне (5→10→20 минути) за изтекли OAuth връзки, вместо постоянното им пропускане (PR #647)### 🧪 Tests\n\n-**936 теста, 0 неуспеха**---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n-**Шаблони за проблеми с GitHub**: Добавен стандартизиран доклад за грешка, заявка за функция и шаблони за проблеми с конфигурация/прокси (#641) -**Изчистване на всички модели**: Добавен е бутон \"Изчистване на всички модели\" към страницата с подробности за доставчика с поддръжка на i18n на 29 езика (#634)### 🐛 Bug Fixes\n\n-**Конфликт на локализация (`in.json`)**: Преименува файла с локализация на хинди от `in.json` (индонезийски ISO код) на `hi.json`, за да коригира конфликтите при превод в Weblate (#642) -**Празни имена на инструменти на Codex**: Преместена дезинфекция на името на инструмента преди естественото преминаване на Codex, коригиране на 400 грешки от доставчици нагоре по веригата, когато инструментите са имали празни имена (#637) -**Поточно предаване на нови редове**: Добавено е `collapseExcessiveNewlines` към дезинфекциращото средство за отговор, свиване на серии от 3+ последователни нови реда от мислещи модели в стандартен двоен нов ред (#638) -**Claude Reasoning Effort**: Преобразуван параметър OpenAI `reasoning_effort` в собствения бюджетен блок `thinking` на Клод във всички пътища на заявка, включително автоматично регулиране на `max_tokens` (#627) -**Qwen Token Refresh**: Внедрено проактивно опресняване на OAuth токена преди изтичане (5-минутен буфер), за да се предотврати неуспех на заявки при използване на краткотрайни токени (#631)### 🧪 Tests\n\n-**936 теста, 0 неуспеха**(+10 теста от 3.0.9)---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n-**NaN токени в Claude Code/клиентски отговори (#617):**\n\n- `sanitizeUsage()` вече кръстосва `input_tokens`→`prompt_tokens` и `output_tokens`→`completion_tokens` преди филтъра за белия списък, коригирайки отговорите, показващи броя на токените NaN/0, когато доставчиците връщат имена на полета за използване в стил Claude### Сигурност\n\n- Актуализиран пакет `yaml` за коригиране на уязвимостта при препълване на стека (GHSA-48c2-rrv3-qjmp)### 📋 Issue Triage\n\n- Затворен #613 (Кодестрално — решено със заобиколно решение на персонализирания доставчик)\n- Коментирано на #615 (OpenCode двойна крайна точка — предоставено заобиколно решение, проследено като заявка за функция)\n- Коментирано на #618 (видимост на извикването на инструмента — искане на тест v3.0.9)\n- Коментирано на #627 (ниво на усилие — вече се поддържа)---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n-**Неуспешни преводи за доставчици на OpenAI-формат в Claude CLI (#632):**\n\n- Обработка на формата на масива `reasoning_details[]` от StepFun/OpenRouter — преобразува се в `reasoning_content`\n- Обработване на псевдоним на полето `reasoning` от някои доставчици → нормализирано до `reasoning_content`\n- Имена на полета за използване на различни карти: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` във `filterUsageForFormat`\n- Коригирайте `extractUsage`, за да приемете както `input_tokens`/`output_tokens`, така и `prompt_tokens`/`completion_tokens` като валидни полета за използване\n- Прилага се както към стрийминг (`sanitizeStreamingChunk`, `openai-to-clau.ts` translator), така и към не-стрийминг (`sanitizeMessage`) пътища---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n-**Antigravity Token Refresh:**Коригирана грешка `client_secret is missing` за потребители с инсталиран npm — `clientSecretDefault` беше празен в providerRegistry, карайки Google да отхвърля заявките за опресняване на токена (#588) -**OpenCode Zen Models:**Добавен е `modelsUrl` към записа в системния регистър на OpenCode Zen, така че \"Импортиране от /models\" работи правилно (#612) -**Артефакти на поточно предаване:**Поправени са прекомерните нови редове, оставени в отговорите след премахване на подписа на мислещ етикет (#626) -**Резервен прокси:**Добавен е автоматичен повторен опит без прокси, когато релето SOCKS5 не успее -**Прокси тест:**Крайната точка на теста вече разрешава реални идентификационни данни от DB чрез proxyId### ✨ New Features\n\n-**Playground Account/Key Selector:**Постоянно, винаги видимо падащо меню за избор на конкретни акаунти/ключове на доставчик за тестване — извлича всички връзки при стартиране и филтрира по избран доставчик -**CLI Tools Dynamic Models:**Изборът на модел вече се извлича динамично от `/v1/models` API — доставчици като Kiro вече показват пълния си каталог с модели -**Списък с антигравитационни модели:**Актуализиран с Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; активиран `passthroughModels` за динамичен достъп до модела (#628)### 🔧 Maintenance\n\n- Обединен PR #625 — Корекция на фона на светъл режим на доставчика---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n-**Ограничения/Прокси:**Коригирано извличане на ограничения на Codex за акаунти зад SOCKS5 прокси сървъри — опресняването на токена вече се изпълнява в контекста на прокси сървъра -**CI:**Фиксиран интеграционен тест `v1/models` неуспешно твърдение в CI среди без връзки с доставчик -**Настройки:**Бутонът за тест на прокси сървъра вече показва незабавно резултати за успех/неуспех (преди скрит зад здравни данни)### ✨ New Features\n\n-**Playground:**Добавено падащо меню за избор на акаунти — тествайте конкретни връзки поотделно, когато доставчикът има множество акаунти### 🔧 Maintenance\n\n- Обединен PR #623 — Корекция на основния URL път на LongCat API---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n-**Потребителски интерфейс с ограничения:**Добавена функция за групиране на тагове към таблото за управление на връзките, за да се подобри визуалната организация за акаунти с персонализирани тагове.---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n-**Поточно предаване:**Коригирано повреда в състоянието на `TextDecoder` вътре в комбо `sanitize` TransformStream, което причиняваше SSE деформиран изход, съответстващ на многобайтови знаци (PR #614) -**Потребителски интерфейс на доставчиците:**Безопасно изобразяване на HTML тагове в подсказките за грешка при свързване на доставчика с помощта на `dangerouslySetInnerHTML` -**Настройки на прокси сървъра:**Добавени са липсващи свойства на полезен товар `потребителско име` и `парола`, позволяващи удостоверените прокси сървъри да бъдат успешно потвърдени от таблото за управление. -**API на доставчика:**Обвързаното меко изключение се връща към `getCodexUsage`, предотвратявайки грешки на API HTTP 500, когато извличането на токена е неуспешно---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n-**Автоматично синхронизиране на модели:**Добавен е превключвател на потребителския интерфейс и крайна точка на `sync-models` за автоматично синхронизиране на списъците с модели за всеки доставчик с помощта на планировчик на планирани интервали (PR #597)### 🐛 Bug Fixes\n\n-**Изчаквания:**Повишени проксита по подразбиране `FETCH_TIMEOUT_MS` и `STREAM_IDLE_TIMEOUT_MS` до 10 минути, за да поддържат правилно модели за дълбоко разсъждение (като o1) без прекъсване на заявки (Поправки #609) -**CLI Tool Detection:**Подобрено междуплатформено откриване, обработващо NVM пътеки, Windows `PATHEXT` (предотвратяване на проблем с `.cmd` обвивки) и персонализирани NPM префикси (PR #598) -**Регистрационни файлове за поточно предаване:**Внедрено натрупване на делта `tool_calls` в регистрационните файлове за отговор на поточно предаване, така че извикванията на функции се проследяват и поддържат точно в DB (PR #603) -**Каталог на модели:**Премахнато изключение за удостоверяване, правилно скриване на моделите `comfyui` и `sdwebui`, когато няма изрично конфигуриран доставчик (PR #599)### 🌐 Translations\n\n-**cs:**Подобрени низове за превод на чешки в приложението (PR #601)## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Добавено е поле за етикет/група към `EditConnectionModal` (съхранено в `providerSpecificData.tag`) без да се изискват миграции на DB схема.\n- Връзките в изгледа на доставчика вече се групират динамично по етикет с визуални разделители.\n- Немаркираните връзки се появяват първо без заглавка, последвани от маркирани групи по азбучен ред.\n- Групирането на тагове автоматично се прилага към секцията Codex/Copilot/Antigravity Limits, тъй като превключвателите съществуват в редовете за връзка.### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n-**Липсващи значки на картите за връзка:**Коригирано чрез използване на `resolveProxyForConnection()` вместо статично картографиране. -**Тестовата връзка е деактивирана в запазен режим:**Бутонът Тест е активиран чрез разрешаване на прокси конфигурация от запазения списък. -**Модално замразяване на конфигурацията:**Добавени са `onClose()` извиквания след запазване/изчистване, за да се предотврати замразяването на потребителския интерфейс. -**Двойно отчитане на употребата:**`ProxyRegistryManager` сега зарежда употребата нетърпеливо при монтиране с дедупликация чрез `scope` + `scopeId`. Броят на употребата беше заменен с тестов бутон, показващ IP/закъснение в линия.#### fix(translator): `function_call` prefix stripping\n\n- Поправена е непълна корекция от PR #607, където само блоковете `tool_use` премахват префикса на инструмента `proxy_` на Claude. Сега клиентите, използващи формата на OpenAI Responses API, също така правилно ще получават инструменти за инструменти без префикса `proxy_`.---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nТри критични регресии, докладвани от потребители след стартирането на v3.0.0, са разрешени.#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nПрефиксът „proxy\\_“, добавен от Claude OAuth, беше премахнат само от отговорите за**поточно предаване**. В режим**non-streaming**, `translateNonStreamingResponse` нямаше достъп до `toolNameMap`, карайки клиентите да получават деформирани имена на инструменти като `proxy_read_file` вместо `read_file`.\n\n**Коригиране:**Добавен незадължителен параметър `toolNameMap` към `translateNonStreamingResponse` и приложено отстраняване на префикса в манипулатора на блок Claude `tool_use`. `chatCore.ts` сега преминава през картата.#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI не излага `GET /v1/models`. Генеричният валидатор `validateOpenAICompatibleProvider` преминава към резервен вариант за завършване на чат само ако е зададен `validationModelId`, който LongCat не конфигурира. Това доведе до неуспешно валидиране на доставчика с подвеждаща грешка при добавяне/запазване.\n\n**Коригиране:**Добавен е `longcat` към картата на специалните валидатори, като проучва директно `/chat/completions` и третира всеки неупълномощен отговор като пропуск.#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP инструменти (напр. `молив`, `компютър_употреба`) препращат дефиниции на инструменти с `{type:\"object\"}`, но без поле `свойства`. API на Anthropic ги отхвърля с: „липсващи свойства на схемата на обекта“.\n\n**Коригиране:**В `openai-to-claude.ts` инжектирайте `properties: {}` като безопасна настройка по подразбиране, когато `type` е `\"object\"` и `properties` отсъства.---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Автор | Резюме |\n| -------- | ------- | ---------------------------------------------------------------------------------------------------- | --- |\n| **#589** | @flobo3 | docs(i18n): коригиране на руския превод за Playground и Testbed |\n| **#591** | @rdself | fix(ui): подобряване на контраста на светлинния режим на доставчика и планиране на ниво на показване | --- |\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`---\n\n### 🧪 Tests\n\n-**926 теста, 0 грешки**(непроменено от v3.0.0)---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **Най-голямото издание досега.**От 36 доставчици във v2.9.5 до**67+ доставчици**във v3.0.0 — с MCP сървър, A2A протокол, машина за автоматично комбиниране, икони на доставчици, API за регистрирани ключове, 926 теста и принос от**12 членове на общността**в**10 обединени PRs**.\n>\n> Консолидиран от v3.0.0-rc.1 до rc.17 (17 кандидати за издание за 3 дни интензивно развитие).---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Доставчик | Псевдоним | Ниво | Бележки |\n| ------------------------------- | ---------------- | --------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Безплатно | 3 модела чрез `opencode.ai/zen/v1` (PR #530 от @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Платено | 4 модела чрез `opencode.ai/zen/go/v1` (PR #530 от @kang-heewon) |\n| **LongCat AI** | `lc` | Безплатно | 50 милиона токена/ден (Flash-Lite) + 500K/ден (чат/мислене) по време на публична бета версия |\n| **Опрашвания AI** | `pol` | Безплатно | Не е необходим API ключ — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Безплатно | 10K неврони/ден — ~150 LLM отговора или 500 s Whisper аудио, извод по ръба |\n| **Scaleway AI** | `scw` | Безплатно | 1 милион безплатни токени за нови акаунти — съвместими с ЕС/GDPR (Париж) |\n| **AI/ML API** | `aiml` | Безплатно | $0,025/ден безплатни кредити — 200+ модела чрез една крайна точка |\n| **Puter AI** | `pu` | Безплатно | 500+ модела (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `али` | Платено | Международни + китайски крайни точки чрез `alicode`/`alicode-intl` |\n| **План за кодиране на Alibaba** | `bcp` | Платено | Alibaba Model Studio с API, съвместим с Anthropic |\n| **Kimi кодиране (API ключ)** | `kmca` | Платено | Специализиран Kimi достъп, базиран на API ключ (отделно от OAuth) |\n| **MiniMax кодиране** | `минимакс` | Платено | Международна крайна точка |\n| **MiniMax (Китай)** | `минимакс-cn` | Платено | Специфична за Китай крайна точка |\n| **Z.AI (GLM-5)** | `зай` | Платено | Zhipu AI следващо поколение GLM модели |\n| **Vertex AI** | `връх` | Платено | Google Cloud — акаунт за услуга JSON или OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Платено | Хоствана API услуга на Ollama |\n| **Синтетичен** | `синтетичен` | Платено | Шлюз за преминаващи модели |\n| **Kilo Gateway** | `кг` | Платено | Шлюз за преминаващи модели |\n| **Търсене на объркване** | `pplx-търсене` | Платено | Специализирана крайна точка, базирана на търсене |\n| **Serper Search** | `serper-търсене` | Платено | Интегриране на API за уеб търсене |\n| **Смело търсене** | `смело търсене` | Платено | Интегриране на API на Brave Search |\n| **Exa Търсене** | `exa-търсене` | Платено | Интеграция на API за невронно търсене |\n| **Търсене на Tavily** | `tavily-търсене` | Платено | Интегриране на API за AI търсене |\n| **Нанобанан** | `nb` | Платено | API за генериране на изображения |\n| **ElevenLabs** | `el` | Платено | Гласов синтез от текст към говор |\n| **Картезия** | `картезия` | Платено | Изключително бърз TTS гласов синтез |\n| **PlayHT** | `playht` | Платено | Гласово клониране и TTS |\n| **Вътрешен свят** | `вътрешен свят` | Платено | AI герой гласов чат |\n| **SD WebUI** | `sdwebui` | Самостоятелен хостинг | Генериране на стабилно дифузионно локално изображение |\n| **ComfyUI** | `comfyui` | Самостоятелен хостинг | ComfyUI базирано на възел локално генериране на работен поток |\n| **GLM кодиране** | `glm` | Платено | Крайна точка, специфична за кодиране на BigModel/Zhipu | **Общо: 67+ доставчици**(4 безплатни, 8 OAuth, 55 API ключа) + неограничен брой потребителски доставчици, съвместими с OpenAI/Anthropic.--- |\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nАвтоматично генериране и издаване на OmniRoute API ключове програмно с налагане на квоти за всеки доставчик и всеки акаунт.\n\n| Крайна точка | Метод | Описание |\n| ------------------------------- | ------------- | -------------------------------------------------------------- |\n| `/api/v1/registered-keys` | `ПУБЛИКУВАНЕ` | Издайте нов ключ — необработеният ключ се връща**само веднъж** |\n| `/api/v1/registered-keys` | `ВЗЕМЕТЕ` | Списък на регистрирани ключове (маскирани) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Получаване на метаданни / Отмяна |\n| `/api/v1/квоти/проверка` | `ВЗЕМЕТЕ` | Предварително потвърдете квотата преди издаване |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Конфигуриране на лимити за издаване за всеки доставчик |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Конфигуриране на лимити за издаване за всеки акаунт |\n| `/api/v1/issues/report` | `ПУБЛИКУВАНЕ` | Докладвайте събития с квота на GitHub Issues |\n\n**Сигурност:**Ключовете се съхраняват като SHA-256 хешове. Необработеният ключ се показва веднъж при създаване, никога не може да се извлече отново.#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ лога на доставчици, използващи `@lobehub/icons` React компоненти (SVG). Резервна верига:**Lobehub SVG → съществуващ PNG → обща икона**. Прилага се върху страниците Табло за управление, Доставчици и Агенти със стандартизиран компонент „Икона на доставчик“.#### 🔄 Model Auto-Sync Scheduler (#488)\n\nАвтоматично опреснява списъците с модели за свързани доставчици на всеки**24 часа**. Работи при стартиране на сървъра. Може да се конфигурира чрез `MODEL_SYNC_INTERVAL_HOURS`.#### 🔀 Per-Model Combo Routing (#563)\n\nКартирайте моделите на името на модела (glob) към конкретни комбинации за автоматично маршрутизиране:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- Нова таблица `model_combo_mappings` със съвпадение на glob-to-regex\n- Секция на потребителския интерфейс на таблото: „Правила за маршрутизиране на модели“ с вградено добавяне/редактиране/превключване/изтриване#### 🧭 API Endpoints Dashboard\n\nИнтерактивен каталог, управление на уеб кукички, преглед на OpenAPI — всичко това в една страница с раздели на `/dashboard/endpoint`.#### 🔍 Web Search Providers\n\n5 нови интеграции на доставчик на търсене:**Perplexity Search**,**Serper**,**Brave Search**,**Exa**,**Tavily**— позволяващи базирани AI отговори с уеб данни в реално време.#### 📊 Search Analytics\n\nНов раздел в `/dashboard/analytics` — разбивка на доставчика, честота на попадение в кеша, проследяване на разходите. API: `GET /api/v1/search/analytics`.#### 🛡️ Per-API-Key Rate Limits (#452)\n\nКолони `max_requests_per_day` и `max_requests_per_minute` с прилагане на плъзгащ се прозорец в паметта, връщащо HTTP 429.#### 🎵 Media Playground\n\nПълна площадка за генериране на мултимедия в `/dashboard/media`: Генериране на изображения, видео, музика, транскрипция на аудио (ограничение за качване от 2 GB) и текст-към-говор.---\n\n### 🔒 Security & CI/CD\n\n-**Коригиране на CodeQL**— Коригирани 10+ предупреждения: 6 повторения на полином, 1 несигурна произволност (`Math.random()` → `crypto.randomUUID()`), 1 инжектиране на shell-command -**Проверка на маршрута**— Zod схеми + `validateBody()` на**176/176 API маршрути**— Наложен CI -**CVE fix**— dompurify XSS уязвимост (GHSA-v2wj-7wpq-c8vv) разрешена чрез npm overrides -**Плосък**— Ударен 3.3.3 → 3.4.2 (CWE-1321 прототипно замърсяване) -**Docker**— Надстроено `docker/setup-buildx-action` v3 → v4---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n-**#537**— Gemini CLI OAuth: изчистване на възможна грешка, когато `GEMINI_OAUTH_CLIENT_SECRET` липсва в Docker -**#549**— Маршрутите за настройки на CLI вече разрешават реален API ключ от `keyId` (не маскирани низове) -**#574**— Входът вече не замръзва след пропускане на настройката на паролата на съветника -**#506**— `machineId` за различни платформи е пренаписан (Windows REG.exe → macOS ioreg → Linux → резервно име на хост)#### Providers & Routing\n\n-**#536**— LongCat AI: коригирани `baseUrl` и `authHeader` -**#535**— Замяна на фиксиран модел: `body.model` е правилно зададен на `pinnedModel` -**#570**— Моделите Claude без префикс вече се преобразуват в Anthropic доставчик -**#585**— Вътрешните маркери `` вече не изтичат към клиентите в SSE поточно предаване -**#493**— Наименуването на потребителски модел на доставчик вече не се нарушава от премахването на префикса -**#490**— Поточно предаване + защита на контекстния кеш чрез инжектиране на `TransformStream` -**#511**— таг ``, инжектиран в първата част от съдържанието (не след `[DONE]`)#### CLI & Tools\n\n-**#527**— Claude Code + Codex цикъл: блоковете `tool_result` вече се преобразуват в текст -**#524**— Конфигурацията на OpenCode е запазена правилно (XDG_CONFIG_HOME, TOML формат) -**#522**— API Manager: премахнат подвеждащия бутон „Копиране на маскиран ключ“. -**#546**— `--version` връща `unknown` на Windows (PR от @k0valik) -**#544**— Сигурно откриване на CLI инструмент чрез известни инсталационни пътища (PR от @k0valik) -**#510**— Windows MSYS2/Git-Bash пътища се нормализират автоматично -**#492**— CLI открива `mise`/`nvm`-managed Node, когато `app/server.js` липсва#### Streaming & SSE\n\n-**PR #587**— Възстановяване на импортирането на `resolveDataDir` в responsesTransformer за Cloudflare Workers compat (@k0valik) -**PR #495**— Тясно място 429 безкрайно изчакване: премахване на чакащи задания при ограничение на скоростта (@xandr0s) -**#483**— Спиране на завършването на `data: null` след сигнала `[DONE]` -**#473**— Zombie SSE потоци: времето за изчакване е намалено с 300s → 120s за по-бързо възстановяване#### Media & Transcription\n\n-**Транскрипция**— Deepgram `video/mp4` → `audio/mp4` MIME картографиране, автоматично откриване на език, пунктуация -**TTS**— показване на грешка `[object Object]` коригирано за вложени грешки в стил ElevenLabs -**Ограничения за качване**— Медийната транскрипция е увеличена до 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n-**T01**— колона `requested_model` в дневниците на повикванията (миграция 009) -**T02**— Премахване на празни текстови блокове от вложен `tool_result.content` -**T03**— Разбор на `x-codex-5h-*` / `x-codex-7d-*` заглавки на квоти -**T04**— `X-Session-Id` хедър за външно лепкаво маршрутизиране -**T05**— Устойчивост на DB с ограничение на скоростта със специален API -**T06**— Деактивиран акаунт → постоянен блок (1 година изчакване) -**T07**— X-Forwarded-For IP валидиране (`extractClientIp()`) -**T08**— Ограничения на сесията на API ключ с налагане на плъзгащ се прозорец -**T09**— Codex vs Spark обхвати на ограничение на скоростта (отделни пулове) -**T10**— Кредитите са изчерпани → отделно 1 час възстановяване на времето за изчакване -**T11**— `max` усилие за разсъждение → 131072 бюджетни токена -**T12**— Ценообразуване на MiniMax M2.7 -**T13**— Корекция на показване на остаряла квота (нулиране на осведомеността за прозореца) -**T14**— TCP проверка за бърз отказ на прокси (≤2s, кеширани 30s) -**T15**— Нормализация на съдържанието на масива за Anthropic -**T23**— Интелигентно резервно нулиране на квота (извличане на заглавка) -**T24**— `503` изчакване + `406` картографиране -**T25**— Резервно валидиране на доставчик -**T29**— Vertex AI Service Account JWT auth -**T33**— Ниво на мислене към преобразуване на бюджета -**T36**— Класификация на грешките `403` срещу `429` -**T38**— Централизирани спецификации на модела (`modelSpecs.ts`) -**T39**— Резервна крайна точка за `fetchAvailableModels` -**T41**— Автоматично пренасочване на фонови задачи към флаш модели -**T42**— Картографиране на пропорциите на генериране на изображение#### Other Improvements\n\n-**Персонализирани заглавки нагоре за всеки модел**— чрез потребителски интерфейс за конфигурация (PR #575 от @zhangqiang8vip) -**Дължина на контекста на модела**— конфигурируема в метаданните на модела (PR #578 от @hijak) -**Отстраняване на префикса на модела**— опция за премахване на префикса на доставчика от имената на моделите (PR #582 от @jay77721) -**Отказ от Gemini CLI**— маркиран като остарял с предупреждение за ограничение на Google OAuth -**YAML анализатор**— заменен персонализиран анализатор с `js-yaml` за правилно анализиране на спецификациите на OpenAPI -**ZWS v5**— корекция на изтичане на HMR (485 DB връзки → 1, памет 2,4 GB → 195 MB) -**Експортиране на регистрационни файлове**— Нов бутон за експортиране на JSON на таблото за управление с падащо меню за диапазон от време -**Банер за известия за актуализиране**— началната страница на таблото за управление показва кога са налични нови версии---\n\n### 🌐 i18n & Documentation\n\n-**30 езика**при 100% паритет — синхронизирани 2788 липсващи ключа -**Чешки**— Пълен превод: 22 документа, 2606 UI низа (PR от @zen0bit) -**китайски (zh-CN)**— пълен превод (PR от @only4copilot) -**Ръководство за разполагане на VM**— Преведено на английски като изходен документ -**API Reference**— Добавени крайни точки `/v1/embeddings` и `/v1/audio/speech` -**Брой доставчици**— Актуализиран от 36+/40+/44+ на**67+**в README и всички 30 i18n README---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Автор | Резюме |\n| -------- | --------------- | ---------------------------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): възстановяване на импортирането на resolveDataDir за Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(прокси): опция за премахване на префикс за име на модел |\n| **#581** | @jay77721 | fix(npm): свързване на освобождаването на електрони към работния процес на npm-publish |\n| **#578** | @hijak | feat: конфигурируема дължина на контекста в метаданните на модела |\n| **#575** | @zhangqiang8vip | feat: заглавки нагоре по модел, съвместим PATCH, чат подравняване |\n| **#562** | @coobabm | поправка: управление на MCP сесии, преминаване на Claude, detectFormat |\n| **#561** | @zen0bit | fix(i18n): корекции на превод на чешки |\n| **#555** | @k0valik | fix(sse): централизиран `resolveDataDir()` за разрешаване на пътя |\n| **#546** | @k0valik | fix(cli): `--version` връща `unknown` на Windows |\n| **#544** | @k0valik | fix(cli): сигурно откриване на CLI инструмент чрез инсталационни пътища |\n| **#542** | @rdself | fix(ui): светъл режим контраст CSS тема променливи |\n| **#530** | @kang-heewon | feat: доставчици на OpenCode Zen + Go с `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: съвместимост на модела на протокол (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | поправка: течове на HMR ресурси в режим на разработка (ZWS v5) |\n| **#495** | @xandr0s | поправка: Bottleneck 429 безкрайно чакане (отпадане на чакащи задания) |\n| **#494** | @zhangqiang8vip | feat: MiniMax разработчик→корекция на системна роля |\n| **#480** | @prakersh | поправка: извличане на използването на потока |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 и записи за ценообразуване на Anthropic |\n| **#475** | @only4copilot | feat(i18n): подобрен китайски превод |\n\n**Благодарим на всички сътрудници!**🙏---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`---\n\n### 🧪 Tests\n\n-**926 теста, 0 грешки**(от 821 във v2.9.5)\n\n- +105 нови теста, обхващащи: съпоставяне на модел-комбо, регистрирани ключове, OpencodeExecutor, доставчик на Bailian, валидиране на маршрут, класификация на грешки, картографиране на съотношение на страните и др.---\n\n### 📦 Database Migrations\n\n| Миграция | Описание |\n| -------- | ---------------------------------------------------------------------- | --- |\n| **008** | таблици `registered_keys`, `provider_key_limits`, `account_key_limits` |\n| **009** | колона `requested_model` в `call_logs` |\n| **010** | Таблица `model_combo_mappings` за комбо маршрутизиране по модел | --- |\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Взломни промени:**Няма. Всички съществуващи конфигурации, комбинации и API ключове се запазват.\n> Миграциите на бази данни 008-010 се изпълняват автоматично при стартиране.---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n-**Коригиране на CodeQL**— Коригирани 10+ предупреждения:\n\n- 6 повторения на полином в `provider.ts` / `chatCore.ts` (заменени модели за редуване на `(?:^|/)` с базирано на сегмент съвпадение)\n- 1 несигурна случайност в `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n- 1 инжектиране на командна обвивка в `prepublish.mjs` (`JSON.stringify()` екраниране на пътя) -**Валидиране на маршрута**— Добавени Zod схеми + `validateBody()` към 5 маршрута без валидиране:\n- `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n- CI `check:route-validation:t06` вече преминава:**176/176 валидирани маршрута**### 🐛 Bug Fixes\n\n-**#585**— Вътрешните етикети `` вече не изтичат към клиентите в отговорите на SSE. Добавена е изходяща дезинфекция „TransformStream“ в „combo.ts“.### ⚙️ Infrastructure\n\n-**Docker**— Надстроено `docker/setup-buildx-action` от v3 → v4 (Node.js 20 корекция за оттегляне) -**CI cleanup**— Изтрити 150+ неуспешни/анулирани изпълнения на работен поток### 🧪 Tests\n\n- Тестов пакет:**926 теста, 0 неуспеха**(+3 нови)---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Повишени лимити за транскрипция на медии\n- Добавена дължина на контекста на модела към метаданните на регистъра\n- Добавени персонализирани заглавки за модел нагоре по веригата чрез потребителски интерфейс за конфигурация\n- Поправени са множество грешки, проверка на Zod за корекции и разрешени различни проблеми на общността.## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n-**#563**— Комбинирано маршрутизиране за модел: картографирайте моделите на името на модела (glob) към конкретни комбинации за автоматично маршрутизиране\n\n- Нова таблица `model_combo_mappings` (миграция 010) с модел, combo_id, приоритет, активиран\n- `resolveComboForModel()` DB функция със съвпадение на glob-to-regex (нечувствителен към регистър, `*` и `?` заместващи знаци)\n- `getComboForModel()` в `model.ts`: допълва `getCombo()` с резервен модел на модел\n- `chat.ts`: решението за маршрутизиране вече проверява съпоставянията на модел-комбо преди обработка на единичен модел\n- API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n- Табло за управление: разделът „Правила за маршрутизиране на модела“ е добавен към страницата с комбинации с вградено добавяне/редактиране/превключване/изтриване\n- Примери: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo### 🌐 i18n\n\n-**Пълна i18n синхронизация**: 2788 липсващи ключа, добавени в 30 езикови файла — всички езици вече са на 100% равенство с `en.json` -**Страница на агенти i18n**: Разделът за интегриране на OpenCode е напълно интернационализиран (заглавие, описание, сканиране, етикети за изтегляне) -**6 нови ключа**добавени към пространството на имената на `агентите` за секцията OpenCode### 🎨 UI/UX\n\n-**Икони на доставчик**: добавени са 16 липсващи икони на доставчик (3 копирани, 2 изтеглени, 11 създадени SVG) -**Резервен SVG**: Компонентът `ProviderIcon` актуализиран с 4-степенна стратегия: Lobehub → PNG → SVG → Обща икона -**Агентни пръстови отпечатъци**: Синхронизирано с CLI инструменти — добавен дроид, отворен нокът, втори пилот, отворен код към списък с пръстови отпечатъци (общо 14)### Сигурност\n\n-**CVE fix**: Разрешена XSS уязвимост на dompurify (GHSA-v2wj-7wpq-c8vv) чрез npm замени, принуждавайки `dompurify@^3.3.2`\n\n- `npm audit` вече отчита**0 уязвимости**### 🧪 Tests\n\n- Пакет от тестове:**923 теста, 0 неуспеха**(+15 нови теста за картографиране на комбинация от модели)---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Автор | Резюме |\n| -------- | -------- | ------------------------------------------------------------------------------------------------- | ------------ |\n| **#562** | @coobabm | fix(ux): управление на MCP сесии, нормализация на Claude passthrough, модален OAuth, detectFormat |\n| **#561** | @zen0bit | fix(i18n): корекции на чешки превод — имена на HTTP методи и актуализации на документацията | ### 🧪 Tests |\n\n- Тестов пакет:**908 теста, 0 неуспеха**---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n-**config:**разрешава реален API ключ от `keyId` в маршрути за настройки на CLI (`codex-settings`, `droid-settings`, `kilo-settings`), за да се предотврати писането на маскирани низове (#549)---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Автор | Резюме |\n| -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |\n| **#546** | @k0valik | fix(cli): `--version` връща `unknown` в Windows — използвайте `JSON.parse(readFileSync)` вместо импортиране на ESM |\n| **#555** | @k0valik | fix(sse): централизиран `resolveDataDir()` за разрешаване на пътя в идентификационни данни, autoCombo, регистратор на отговори и регистратор на заявки |\n| **#544** | @k0valik | fix(cli): сигурно откриване на CLI инструмент чрез известни инсталационни пътища (8 инструмента) с валидиране на символна връзка, проверки на типа на файла, граници на размера, минимално env в проверката на състоянието |\n| **#542** | @rdself | fix(ui): подобряване на контраста на светлия режим — добавяне на липсващи променливи на CSS тема (`bg-primary`, `bg-subtle`, `text-primary`) и коригиране на тъмните само цветове в детайлите на регистрационния файл | ### 🔧 Bug Fixes |\n\n-**TDZ корекция в `cliRuntime.ts`**— `validateEnvPath` беше използван преди инициализацията при стартиране на модула от `getExpectedParentPaths()`. Пренаредени декларации за коригиране на „ReferenceError“. -**Поправки на компилация**— Добавени са `pino` и `pino-pretty` към `serverExternalPackages`, за да се предотврати Turbopack да наруши вътрешното работно зареждане на Pino.### 🧪 Tests\n\n- Тестов пакет:**905 теста, 0 неуспеха**---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n-**#509 / #508**— Регресия на изграждането на Electron: Next.js е понижен от `16.1.x` до `16.0.10`, за да се елиминира нестабилността на хеширането на модула Turbopack, която причинява празни екрани в пакета за настолен компютър Electron. -**Поправки на модулни тестове**— Коригирани са две остарели тестови твърдения (`nanobanana-image-handler` съотношение/резолюция, `thinking-budget` Gemini `thinkingConfig` картографиране на полето), които са се отклонили след скорошни промени в изпълнението. -**#541**— Отговорено на отзивите на потребителите относно сложността на инсталацията; не са необходими промени в кода.---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n-**T29**— Vertex AI SA JSON Executor: внедрява се с помощта на библиотеката `jose` за обработка на удостоверяване на JWT/Service Account, заедно с конфигурируеми региони в потребителския интерфейс и автоматично изграждане на URL модел на партньор. -**T42**— Картографиране на аспектното съотношение на генериране на изображение: създаде логика `sizeMapper` за общи OpenAI формати (`size`), добавено естествено управление на `imagen3` и актуализирани крайни точки на NanoBanana, за да се използват автоматично картографираните аспектни съотношения. -**T38**— Централизирани спецификации на модела: `modelSpecs.ts`, създаден за ограничения и параметри на модел.### 🔧 Improvements\n\n-**T40**— Интеграция на OpenCode CLI инструменти: собствена интеграция `opencode-zen` и `opencode-go`, завършена в по-ранен PR.---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n-**T24**— `503` изчакване за изчакване на корекция + `406` съпоставяне: съпоставено `406 Неприемливо` към `503 Услугата е недостъпна` с подходящи интервали за изчакване. -**T25**— Резервно валидиране на доставчик: грациозно резервно връщане към стандартни модели за валидиране, когато конкретен `validationModelId` не присъства. -**T36**— `403` срещу `429` усъвършенстване на обработката на доставчика: извлечено в `errorClassifier.ts`, за да се разделят правилно неуспешните твърди разрешения (`403`) от ограниченията на скоростта (`429`). -**T39**— Резервна крайна точка за `fetchAvailableModels`: имплементиран механизъм от три нива (`/models` -> `/v1/models` -> локален общ каталог) + `list_models_catalog` актуализации на MCP инструмента, за да отрази `source` и `warning`. -**T33**— Ниво на мислене към преобразуване на бюджета: превръща нивата на качествено мислене в точни бюджетни разпределения. -**T41**— Автоматично пренасочване на фонови задачи: насочва автоматично тежките задачи за оценка на фона към флаш/ефективни модели. -**T23**— Резервен вариант за интелигентно нулиране на квота: точно извлича стойностите на заглавката `x-ratelimit-reset` / `retry-after` или картографира статични времена за охлаждане.---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Надстройка от v2.9.5:**16 решени проблема · 2 PR-а на общността са обединени · 2 нови доставчика · 7 нови крайни точки на API · 3 нови функции · Миграция на DB 008+009 · 832 преминали теста · 15 подобрения на пропуски в sub2api (T01–T15 завършени).### 🆕 New Providers\n\n| Доставчик | Псевдоним | Ниво | Бележки |\n| ---------------- | -------------- | --------- | --------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Безплатно | 3 модела чрез `opencode.ai/zen/v1` (PR #530 от @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Платено | 4 модела чрез `opencode.ai/zen/go/v1` (PR #530 от @kang-heewon) |\n\nИ двата доставчика използват новия `OpencodeExecutor` с многоформатно маршрутизиране (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nАвтоматично генериране и издаване на OmniRoute API ключове програмно с налагане на квоти за всеки доставчик и всеки акаунт.\n\n| Крайна точка | Метод | Описание |\n| ------------------------------------- | ------------- | -------------------------------------------------------------- |\n| `/api/v1/registered-keys` | `ПУБЛИКУВАНЕ` | Издайте нов ключ — необработеният ключ се връща**само веднъж** |\n| `/api/v1/registered-keys` | `ВЗЕМЕТЕ` | Списък на регистрирани ключове (маскирани) |\n| `/api/v1/registered-keys/{id}` | `ВЗЕМЕТЕ` | Вземете ключови метаданни |\n| `/api/v1/registered-keys/{id}` | `ИЗТРИВАНЕ` | Отмяна на ключ |\n| `/api/v1/registered-keys/{id}/revoke` | `ПУБЛИКУВАНЕ` | Отмяна (за клиенти без поддръжка на DELETE) |\n| `/api/v1/квоти/проверка` | `ВЗЕМЕТЕ` | Предварително потвърдете квотата преди издаване |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Конфигуриране на лимити за издаване за всеки доставчик |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Конфигуриране на лимити за издаване за всеки акаунт |\n| `/api/v1/issues/report` | `ПУБЛИКУВАНЕ` | Докладвайте събития с квота на GitHub Issues |\n\n**DB — Миграция 008:**Три нови таблици: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Сигурност:**Ключовете се съхраняват като SHA-256 хешове. Необработеният ключ се показва веднъж при създаване, никога не може да се извлече отново.\n**Типове квоти:**`maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` за доставчик и за акаунт.\n**Idempotency:**полето `idempotency_key` предотвратява дублиране на издаване. Връща „409 IDEMPOTENCY_CONFLICT“, ако ключът вече е бил използван.\n**Бюджет на ключ:**`dailyBudget` / `hourlyBudget` — ограничава колко заявки ключът може да насочи на прозорец.\n**Отчитане на GitHub:**По избор. Задайте `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` за автоматично създаване на проблеми с GitHub при превишена квота или неуспешно издаване.#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nВсички икони на доставчици в таблото за управление вече използват `@lobehub/icons` React компоненти (130+ доставчици със SVG).\nРезервна верига:**Lobehub SVG → съществуващ `/providers/{id}.png` → обща икона**. Използва подходящ модел на React `ErrorBoundary`.#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute вече автоматично опреснява списъците с модели за свързани доставчици на всеки**24 часа**.\n\n- Работи при стартиране на сървъра чрез съществуващата кука `/api/sync/initialize`\n- Може да се конфигурира чрез променливата на средата `MODEL_SYNC_INTERVAL_HOURS`\n- Обхваща 16 основни доставчици\n- Записва времето за последно синхронизиране в базата данни с настройки---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n-**#537 — Gemini CLI OAuth:**Изчистване на възможна грешка, когато `GEMINI_OAUTH_CLIENT_SECRET` липсва в Docker/самостоятелно хоствани внедрявания. По-рано показваше загадъчно „client_secret is missing“ от Google. Вече предоставя конкретни инструкции за `docker-compose.yml` и `~/.omniroute/.env`.#### Providers & Routing\n\n-**#536 — LongCat AI:**Фиксиран `baseUrl` (`api.longcat.chat/openai`) и `authHeader` (`Authorization: Bearer`). -**#535 — Отмяна на фиксиран модел:**`body.model` вече е правилно настроен на `pinnedModel`, когато защитата на контекстния кеш е активна. -**#532 — Проверка на ключа на OpenCode Go:**Сега използва крайната точка на теста `zen/v1` (`testKeyBaseUrl`) — един и същ ключ работи и за двете нива.#### CLI & Tools\n\n-**#527 — Claude Code + Codex цикъл:**блоковете `tool_result` вече се преобразуват в текст, вместо да се изпускат, спирайки безкрайните цикли на резултата от инструмента. -**#524 — Запазване на OpenCode config:**Добавен манипулатор `saveOpenCodeConfig()` (съзнава XDG_CONFIG_HOME, пише TOML). -**#521 — Входът блокира:**Входът вече не замръзва след пропускане на настройката на паролата — пренасочва правилно към onboarding. -**#522 — API Manager:**Премахнат подвеждащ бутон „Копиране на маскиран ключ“ (заменен с подсказка за икона на заключване). -**#532 — Конфигурация на OpenCode Go:**Манипулаторът на настройките на ръководството вече обработва `opencode` toolId.#### Developer Experience\n\n-**#489 — Antigravity:**Липсващият `googleProjectId` връща структурирана грешка 422 с указания за повторно свързване вместо загадъчен срив. -**#510 — Пътища на Windows:**Пътищата на MSYS2/Git-Bash (`/c/Program Files/...`) вече се нормализират автоматично до `C:\\Program Files\\...`. -**#492 — CLI стартиране:**`omniroute` CLI вече открива `mise`/`nvm`-managed Node, когато `app/server.js` липсва и показва насочени инструкции за корекция.---\n\n### 📖 Documentation Updates\n\n-**#513**— Нулиране на парола за Docker: документирано заобиколно решение на `INITIAL_PASSWORD` env var -**#520**— pnpm: стъпката `pnpm approve-builds better-sqlite3` е документирана---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`---\n\n### 🔀 Community PRs Merged\n\n| PR | Автор | Резюме |\n| -------- | ------------ | ------------------------------------------------------------------------ | --- |\n| **#530** | @kang-heewon | Доставчици на OpenCode Zen + Go с `OpencodeExecutor` и подобрени тестове | --- |\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n-**T05**— Устойчивост на база данни с ограничение на скоростта: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` в `providers.ts`. Съществуващата колона „rate_limited_until“ вече е изложена като специален API — опресняването на токена на OAuth НЕ трябва да докосва това поле, за да се предотвратят цикли на ограничаване на скоростта. -**T08**— Ограничение за сесията на API ключ: `max_sessions INTEGER DEFAULT 0`, добавено към `api_keys` чрез автоматична миграция. `sessionManager.ts` печели `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()` и `getActiveSessionCountForKey()`. Обаждащите се в `chatCore.js` могат да наложат ограничението и да намалят `req.close`. -**T09**— Обхвати на ограничение на скоростта на Codex срещу Spark: `getCodexModelScope()` и `getCodexRateLimitKey()` в `codex.ts`. Стандартните модели (`gpt-5.x-codex`, `codex-mini`) получават обхват `\"codex\"`; искровите модели (`codex-spark*`) получават обхват `\"искра\"`. Ключовете за ограничаване на скоростта трябва да бъдат `${accountId}:${scope}`, така че изчерпването на единия пул да не блокира другия. -**T13**— Корекция на показване на остаряла квота: `getEffectiveQuotaUsage(used, resetAt)` връща `0`, когато прозорецът за нулиране е преминал; `formatResetCountdown(resetAt)` връща четим от човека низ за обратно отброяване (напр. `\"2h 35m\"`). И двете са експортирани от `providers.ts` + `localDb.ts` за потребление на таблото за управление. -**T14**— Прокси бърз отказ: нов `src/lib/proxyHealth.ts` с `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP проверка, ≤2s вместо 30s изчакване), `getCachedProxyHealth()`, `invalidateProxyHealth()` и `getAllProxyHealthStatuses()`. Резултатите се кешират 30s по подразбиране; може да се конфигурира чрез `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.### 🧪 Tests\n\n- Тестов пакет:**832 теста, 0 неуспеха**---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n-**T01**— колона `requested_model` в `call_logs` (миграция 009): проследяване на модела, който клиентът първоначално е поискал спрямо действително маршрутизирания модел. Позволява анализ на резервния процент. -**T02**— Премахване на празни текстови блокове от вложен `tool_result.content`: предотвратява грешки на Anthropic 400 (`блоковете с текстово съдържание не трябва да са празни`), когато резултатите от инструмента на Claude Code са вериги. -**T03**— Разбор на `x-codex-5h-*` / `x-codex-7d-*` заглавки: `parseCodexQuotaHeaders()` + `getCodexResetTime()` извличане на прозорци на квоти на Codex за прецизно планиране на изчакване вместо общ 5-минутен резерв. -**T04**— Заглавка `X-Session-Id` за външно лепкаво маршрутизиране: `extractExternalSessionId()` в `sessionManager.ts` чете `x-session-id` / `x-omniroute-session` заглавки с префикс `ext:`, за да се избегне сблъсък с вътрешни идентификатори на SHA-256 сесии. Съвместим с Nginx (заглавка с тире). -**T06**— Акаунтът е деактивиран → постоянно блокиране: `isAccountDeactivated()` в `accountFallback.ts` открива 401 сигнала за деактивиране и прилага 1-годишно изчакване, за да предотврати повторни опити за постоянно мъртви акаунти. -**T07**— X-Forwarded-For IP валидиране: нов `src/lib/ipUtils.ts` с `extractClientIp()` и `getClientIpFromRequest()` — пропуска `unknown`/non-IP записи във веригите `X-Forwarded-For` (Nginx/прокси-препратени заявки). -**T10**— Изчерпани кредити → различен резервен вариант: `isCreditsExhausted()` в `accountFallback.ts` връща 1 час изчакване с флаг `creditsExhausted`, различен от общото ограничаване на скоростта 429. -**T11**— `max` усилие за разсъждение → 131072 бюджетни токена: `EFFORT_BUDGETS` и `THINKING_LEVEL_MAP` актуализирани; обратното картографиране вече връща „max“ за отговори с пълен бюджет. Единичният тест е актуализиран. -**T12**— Добавени са цени за MiniMax M2.7: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` добавени към таблицата с цените (sub2api PR #1120). Цените на M2.5/GLM-4.7/GLM-5/Kimi вече съществуват. -**T15**— Нормализиране на съдържанието на масива: помощникът `normalizeContentToString()` в `openai-to-claude.ts` правилно свива форматираните в масив съобщения от системата/инструмента към низ преди изпращане до Anthropic.### 🧪 Tests\n\n- Тестов пакет:**832 теста, 0 неуспеха**(непроменен от rc.5)---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n-**#464**— API за предоставяне на регистрирани ключове: автоматично издаване на API ключове с налагане на квота за всеки доставчик и за всеки акаунт\n\n- `POST /api/v1/registered-keys` — издаване на ключове с поддръжка на идемпотентност\n- `GET /api/v1/registered-keys` — списък (маскирани) регистрирани ключове\n- `GET /api/v1/registered-keys/{id}` — вземете ключови метаданни\n- `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — отмяна на ключове\n- `GET /api/v1/quotas/check` — предварителна проверка преди издаване\n- `PUT /api/v1/providers/{id}/limits` — задаване на лимити за издаване на доставчик\n- `PUT /api/v1/accounts/{id}/limits` — задайте лимити за издаване на акаунт\n- `POST /api/v1/issues/report` — незадължително отчитане на проблеми с GitHub\n- DB миграция 008: таблици `registered_keys`, `provider_key_limits`, `account_key_limits`---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n-**#530 (PR)**— Добавени доставчици на OpenCode Zen и OpenCode Go (от @kang-heewon)\n\n- Нов `OpencodeExecutor` с многоформатно маршрутизиране (`/chat/completions`, `/messages`, `/responses`)\n- 7 модела в двете нива---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n-**#529**— Иконите на доставчиците вече използват [@lobehub/icons](https://github.com/lobehub/lobe-icons) с елегантен резервен PNG и компонент `ProviderIcon` (поддържат се 130+ доставчици) -**#488**— Автоматично актуализиране на списъците с модели на всеки 24 часа чрез `modelSyncScheduler` (може да се конфигурира чрез `MODEL_SYNC_INTERVAL_HOURS`)### 🔧 Bug Fixes\n\n-**#537**— Gemini CLI OAuth: вече показва ясна грешка, която може да се предприеме, когато `GEMINI_OAUTH_CLIENT_SECRET` липсва в Docker/самостоятелно хоствани внедрявания---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n-**#536**— Проверка на ключа на LongCat AI: фиксиран baseUrl (`api.longcat.chat/openai`) и authHeader (`Authorization: Bearer`) -**#535**— Замяна на фиксиран модел: `body.model` вече е настроен на `pinnedModel`, когато защитата на контекстния кеш открие фиксиран модел -**#524**— Конфигурацията на OpenCode вече е запазена правилно: добавен манипулатор `saveOpenCodeConfig()` (съзнава XDG_CONFIG_HOME, пише TOML)---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n-**#521**— Влизането вече не се блокира след пропускане на настройката на парола (пренасочва към onboarding) -**#522**— API Manager: Премахнат подвеждащ бутон „Копиране на маскиран ключ“ (заменен с подсказка за икона на заключване) -**#527**— Цикъл със суперсили на Claude Code + Codex: блоковете `tool_result` вече се преобразуват в текст, вместо да бъдат премахнати -**#532**— Проверката на OpenCode GO API ключ вече използва правилната крайна точка `zen/v1` (`testKeyBaseUrl`) -**#489**— Антигравитация: липсващ `googleProjectId` връща структурирана грешка 422 с указания за повторно свързване -**#510**— Windows: MSYS2/Git-Bash пътищата (`/c/Program Files/...`) вече са нормализирани към `C:\\Program Files\\...` -**#492**— `omniroute` CLI вече открива `mise`/`nvm`, когато `app/server.js` липсва и показва насочена корекция### Документация\n\n-**#513**— Нулиране на парола за Docker: документирано заобиколно решение на `INITIAL_PASSWORD` env var -**#520**— pnpm: `pnpm approve-builds better-sqlite3` документиран### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: Нови доставчици на OpenCode, корекция на идентификационни данни за вграждане, грешка в CLI маскиран ключ, корекция на CACHE_TAG_PATTERN.### 🐛 Bug Fixes\n\n-**CLI инструментите запазват маскиран API ключ към конфигурационни файлове**— `claude-settings`, `cline-settings` и `openclaw-settings` POST маршрутите вече приемат параметър `keyId` и разрешават истинския API ключ от DB преди запис на диск. „ClaudeToolCard“ е актуализиран, за да изпраща „keyId“ вместо маскирания низ за показване. Коригира #523, #526. -**Персонализирани доставчици на вграждане: Грешка `Няма идентификационни данни`**— `/v1/embeddings` вече проследява `credentialsProviderId` отделно от префикса за маршрутизиране, така че идентификационните данни се извличат от съвпадащия ID на възела на доставчика, а не от обществения префиксен низ. Коригира регресия, при която `google/gemini-embedding-001` и подобни модели на персонализирани доставчици винаги се провалят с грешка в идентификационните данни. Поправки, свързани с #532. (PR #528 от @jacob2826) -**Регулярният израз за защита на контекстния кеш пропуска `\n` префикс**— `CACHE_TAG_PATTERN` в `comboAgentMiddleware.ts` актуализиран, за да съответства на двата литерала `\n` (обратна наклонена черта-n) и действителен нов ред U+000A, който `combo.ts` стрийминг инжектира около тага `` след корекция #515. Поправки #531.### ✨ New Providers\n\n-**OpenCode Zen**— Безплатен шлюз на ниво в `opencode.ai/zen/v1` с 3 модела: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano` -**OpenCode Go**— Абонаментна услуга на адрес `opencode.ai/zen/go/v1` с 4 модела: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (формат Claude), `minimax-m2.5` (формат Claude)\n\n- И двата доставчика използват новия `OpencodeExecutor`, който насочва динамично към `/chat/completions`, `/messages`, `/responses` или `/models/{model}:generateContent` въз основа на искания модел. (PR #530 от @kang-heewon)---\n\n## [2.9.4] — 2026-03-21\n\n> Спринт: Корекции на грешки — запазване на кеша на подканите на Codex, коригиране на екранирането на tagContent JSON, синхронизиране на състоянието на изтекъл токен с DB.### 🐛 Bug Fixes\n\n-**fix(translator)**: Запазване на `prompt_cache_key` в Responses API → Chat Completions превод (#517)\n— Полето е сигнал за афинитет на кеша, използван от Codex; отстраняването му предотвратяваше бързите посещения на кеша.\nКоригирано в `openai-responses.ts` и `responsesApiHelper.ts`.\n\n-**fix(combo)**: Escape `\n` в `tagContent`, така че инжектираният JSON низ е валиден (#515)\n— Новите редове на шаблонния литерал (U+000A) не се допускат неекранирани в стойностите на JSON низове.\nЗаменен с последователности от литерали „\\n“ в „open-sse/services/combo.ts“.\n\n-**fix(usage)**: Синхронизиране на статуса на изтекъл токен обратно към DB при отказ на удостоверяване на живо (#491)\n— Когато проверката на живо за ограничения и квоти върне 401/403, връзката „testStatus“ вече се актуализира\nна `\"изтекъл\"` в базата данни, така че страницата Доставчици отразява същото влошено състояние.\nКоригирано в `src/app/api/usage/[connectionId]/route.ts`.---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Добавете 5 нови безплатни доставчици на AI — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.### ✨ New Providers\n\n-**feat(providers/longcat)**: Добавете LongCat AI (`lc/`) — 50 милиона токена/ден безплатно (Flash-Lite) + 500K/ден (чат/мислене) по време на публична бета версия. Съвместим с OpenAI, стандартно удостоверяване на носителя. -**feat(providers/pollinations)**: Добавяне на AI за опрашвания (`pol/`) — не се изисква API ключ. Прокси GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s безплатно). Персонализираният изпълнител обработва незадължително удостоверяване. -**feat(providers/cloudflare-ai)**: Добавете Cloudflare Workers AI (`cf/`) — 10K неврона/ден безплатно (~150 LLM отговора или 500s Whisper аудио). 50+ модела в световен мащаб. Персонализираният изпълнител изгражда динамичен URL адрес с „accountId“ от идентификационни данни. -**feat(providers/scaleway)**: Добавяне на Scaleway Generative APIs (`scw/`) — 1 милион безплатни жетони за нови акаунти. Съвместим с ЕС/GDPR (Париж). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2. -**feat(providers/aimlapi)**: Добавяне на AI/ML API (`aiml/`) — $0,025/ден безплатен кредит, 200+ модела (GPT-4o, Claude, Gemini, Llama) чрез единична крайна точка на агрегатора.### 🔄 Provider Updates\n\n-**feat(providers/together)**: Добавяне на `hasFree: true` + 3 постоянно безплатни идентификатора на модел: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free` -**feat(providers/gemini)**: Добавете `hasFree: true` + `freeNote` (1500 req/ден, не е необходима кредитна карта, aistudio.google.com) -**chore(providers/gemini)**: Преименувайте показваното име на `Gemini (Google AI Studio)` за яснота### ⚙️ Infrastructure\n\n-**feat(executors/pollinations)**: Нов `PollinationsExecutor` — пропуска заглавката `Authorization`, когато не е предоставен API ключ -**feat(executors/cloudflare-ai)**: Нов `CloudflareAIExecutor` — изграждането на динамичен URL изисква `accountId` в идентификационните данни на доставчика -**feat(executors)**: Регистрирайте `pollinations`, `pol`, `cloudflare-ai`, `cf` съпоставяния на изпълнители### Документация\n\n-**docs(readme)**: Разширен безплатен комбиниран стек до 11 доставчика ($0 завинаги) -**docs(readme)**: Добавени са 4 нови безплатни раздела за доставчици (LongCat, Pollinations, Cloudflare AI, Scaleway) с таблици с модели -**docs(readme)**: Актуализирана ценова таблица с 4 нови реда за безплатни нива -**docs(i18n/pt-BR)**: Актуализирана ценова таблица + добавени секции LongCat/Pollinations/Cloudflare AI/Scaleway на португалски -**docs(new-features/ai)**: 10 файла със спецификация на задачи + главен план за внедряване в `docs/new-features/ai/`### 🧪 Tests\n\n- Тестов пакет:**821 теста, 0 неуспеха**(непроменени)---\n\n## [2.9.2] — 2026-03-21\n\n> Спринт: Коригиране на медийна транскрипция (Deepgram/HuggingFace Content-Type, откриване на език) и TTS показване на грешки.### 🐛 Bug Fixes\n\n-**fix(transcription)**: Аудио транскрипцията на Deepgram и HuggingFace вече правилно картографира `video/mp4` → `audio/mp4` и други медийни MIME типове чрез нов помощник `resolveAudioContentType()`. Преди това качването на `.mp4` файлове постоянно връщаше „Няма открита реч“, защото Deepgram получаваше `Content-Type: video/mp4`. -**fix(transcription)**: Добавено е `detect_language=true` към заявките на Deepgram — автоматично разпознава аудио езика (португалски, испански и т.н.) вместо английски по подразбиране. Коригира неанглийски транскрипции, връщащи празни или ненужни резултати. -**fix(transcription)**: Добавено е `punctuate=true` към заявките на Deepgram за по-висококачествен транскрипционен изход с правилна пунктуация. -**fix(tts)**: показване на грешка `[object Object]` в отговорите на Text-to-Speech, коригирано както в `audioSpeech.ts`, така и в `audioTranscription.ts`. Функцията `upstreamErrorResponse()` вече извлича правилно вложени низови съобщения от доставчици като ElevenLabs, които връщат `{ грешка: { съобщение: \"...\", status_code: 401 } }` вместо плосък низ за грешка.### 🧪 Tests\n\n- Тестов пакет:**821 теста, 0 неуспеха**(непроменени)### Triaged Issues\n\n-**#508**— Регресия на формат на извикване на инструмента: заявени прокси регистрационни файлове и информация за веригата на доставчика (`needs-info`) -**#510**— Windows CLI път за проверка на състоянието: поискана информация за версията на обвивката/възела (`needs-info`) -**#485**— Извиквания на инструмента Kiro MCP: затворени като външен проблем с Kiro (не OmniRoute) -**#442**— Крайна точка на Baseten /models: затворено (документирано ръчно решение) -**#464**— API за предоставяне на ключове: потвърдено като елемент от пътната карта---\n\n## [2.9.1] — 2026-03-21\n\n> Спринт: Коригиране на загубата на данни на SSE omniModel, съвместимост на модела на сливане на протокол.### Bug Fixes\n\n-**#511**— Критично: Етикетът `` беше изпратен след `finish_reason:stop` в SSE потоци, причинявайки загуба на данни. Етикетът вече се инжектира в първата непразна част от съдържанието, гарантирайки доставка, преди SDK да затвори връзката.### Merged PRs\n\n-**PR #512**(@zhangqiang8vip): Съвместимост на модел на протокол — `normalizeToolCallId` и `preserveOpenAIDeveloperRole` вече могат да бъдат конфигурирани за клиентски протокол (OpenAI, Claude, Responses API). Ново поле `compatByProtocol` в конфигурацията на модела с Zod валидиране.### Triaged Issues\n\n-**#510**— Windows CLI healthcheck_failed: поискана информация за PATH/версия -**#509**— Turbopack Electron регресия: грешка в Next.js нагоре по веригата, документирани заобиколни решения -**#508**— черен екран на macOS: предложено заобиколно решение `--disable-gpu`---\n\n## [2.9.0] — 2026-03-20\n\n> Спринт: Корекция на machineId за различни платформи, ограничения за скоростта на ключ за API, кеш на контекста на поточно предаване, Alibaba DashScope, анализ на търсенето, ZWS v5 и 8 приключени проблема.### ✨ New Features\n\n-**feat(search)**: раздел Анализ за търсене в `/dashboard/analytics` — разбивка на доставчика, процент на попадения в кеша, проследяване на разходите. Нов API: `GET /api/v1/search/analytics` (#feat/search-provider-routing) -**feat(provider)**: Alibaba Cloud DashScope е добавен с персонализирано валидиране на пътя на крайната точка — конфигурируеми `chatPath` и `modelsPath` на възел (#feat/custom-endpoint-paths) -**feat(api)**: Ограничения за брой заявки за ключ на API — колони `max_requests_per_day` и `max_requests_per_minute` с прилагане на плъзгащ се прозорец в паметта, връщащо HTTP 429 (#452) -**feat(dev)**: ZWS v5 — корекция на изтичане на HMR (485 DB връзки → 1), памет 2,4GB → 195MB, `globalThis` единични елементи, корекция на предупреждение за Edge Runtime (@zhangqiang8vip)### 🐛 Bug Fixes\n\n-**fix(#506)**: Междуплатформен `machineId` — `getMachineIdRaw()` пренаписан с try/catch каскада (Windows REG.exe → macOS ioreg → четене на Linux файл → име на хост → `os.hostname()`). Елиминира разклоняването на `process.platform`, което Next.js bundler елиминира мъртъв код, коригирайки `'head' не се разпознава` в Windows. Също така коригира #466. -**fix(#493)**: Персонализирано именуване на модела на доставчика — премахнато е премахването на неправилни префикси в `DefaultExecutor.transformRequest()`, което обезобразява идентификаторите на модели с обхват на организация като `zai-org/GLM-5-FP8`. -**fix(#490)**: Поточно предаване + защита на кеша на контекста — `TransformStream` прихваща SSE, за да инжектира тага `` преди маркера `[DONE]`, като активира защитата на кеша на контекста за поточно предаване на отговори. -**fix(#458)**: Валидиране на комбинирана схема — полетата `system_message`, `tool_filter_regex`, `context_cache_protection` вече преминават валидиране на Zod при запазване. -**fix(#487)**: Почистване на KIRO MITM карта — премахнат ZWS_README, генериран `AntigravityToolCard` за използване на динамични метаданни на инструмента.### 🧪 Tests\n\n- Добавени единични тестове за филтриране на инструменти в антропичен формат (PR #397) — 8 регресионни теста за `tool.name` без обвивка `.function`\n- Набор от тестове:**821 теста, 0 неуспеха**(от 813)### 📋 Issues Closed (8)\n\n-**#506**— Windows machineId `head` не е разпознат (коригиран) -**#493**— Наименуване на потребителски модел на доставчик (коригирано) -**#490**— Кеш на контекста на поточно предаване (коригиран) -**#452**— Ограничения на заявките за ключ на API (въведени) -**#466**— Грешка при влизане в Windows (същата основна причина като #506) -**#504**— MITM неактивен (очаквано поведение) -**#462**— Gemini CLI PSA (решено) -**#434**— Срив на приложението Electron (дубликат на #402)## [2.8.9] — 2026-03-20\n\n> Спринт: Обединяване на PR на общността, коригиране на KIRO MITM карта, актуализации на зависимости.### Merged PRs\n\n-**PR #498**(@Sajid11194): Коригиране на срив на ID на Windows машина (`undefined\\REG.exe`). Заменя `node-machine-id` със заявки за собствен регистър на OS.**Затваря #486.** -**PR #497**(@zhangqiang8vip): Коригиране на течове на HMR ресурси в режим за разработка — 485 изтекли DB връзки → 1, памет 2,4 GB → 195 MB. `globalThis` сингълтони, корекция на предупреждение за Edge Runtime, стабилност при тестване на Windows. (+1168/-338 в 22 файла) -**PRs #499-503**(Dependabot): Актуализации на GitHub Actions — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.### Bug Fixes\n\n-**#505**— Картата KIRO MITM вече показва специфични за инструмента инструкции (`api.anthropic.com`) вместо специфичен за Antigravity текст. -**#504**— Отговорено с UX пояснение (MITM „Неактивен“ е очаквано поведение, когато проксито не работи).---\n\n## [2.8.8] — 2026-03-20\n\n> Спринт: Коригирайте срива при партиден тест на OAuth, добавете бутона „Тествай всички“ към отделните страници на доставчика.### Bug Fixes\n\n-**Срив на партиден тест на OAuth**(ERR_CONNECTION_REFUSED): Заменен последователен for-loop с ограничение за паралелност от 5 връзки + 30 секунди изчакване на връзка чрез `Promise.race()` + `Promise.allSettled()`. Предотвратява срив на сървъра при тестване на големи групи доставчици на OAuth (~30+ връзки).### Функции\n\n-**Бутон „Тествай всички“ на страниците на доставчика**: Страниците на отделни доставчици (напр. `/providers/codex`) вече показват бутон „Тествай всички“ в заглавката на връзките, когато има 2+ връзки. Използва `POST /api/providers/test-batch` с `{mode: \"provider\", providerId}`. Резултатите се показват в модален режим с обобщение за преминаване/неуспех и диагностика за всяка връзка.---\n\n## [2.8.7] — 2026-03-20\n\n> Спринт: Обединяване на PR #495 (отпадане на Bottleneck 429), корекция #496 (персонализирани доставчици на вграждане), функции за сортиране.### Bug Fixes\n\n-**Bottleneck 429 безкрайно чакане**(PR #495 от @xandr0s): На 429, `limiter.stop({ dropWaitingJobs: true })` незабавно проваля всички заявки на опашка, така че повикващите нагоре по веригата могат да задействат резервен вариант. Limiter се изтрива от картата, така че следващата заявка създава нов екземпляр. -**Неразрешими модели за персонализирано вграждане**(#496): `POST /v1/embeddings` вече разрешава потребителски модели за вграждане от ВСИЧКИ provider_nodes (не само localhost). Активира модели като `google/gemini-embedding-001`, добавени чрез таблото за управление.### Issues Responded\n\n-**#452**— Ограничения за броя на заявките за API ключ (потвърдено, в пътна карта) -**#464**— Автоматично издаване на API ключове с ограничения за доставчик/акаунт (има нужда от повече подробности) -**#488**— Автоматично актуализиране на списъци с модели (потвърдено, на пътна карта) -**#496**— Персонализирана резолюция на доставчика на вграждане (коригирана)---\n\n## [2.8.6] — 2026-03-20\n\n> Спринт: Обединяване на PR #494 (корекция на ролята на MiniMax), коригиране на таблото за управление на KIRO MITM, сортиране на 8 проблема.### Функции\n\n-**MiniMax разработчик→корекция на системна роля**(PR #494 от @zhangqiang8vip): Превключване на `preserveDeveloperRole` за всеки модел. Добавя потребителски интерфейс „Съвместимост“ в страницата на доставчиците. Коригира 422 „грешка в параметъра на ролята“ за MiniMax и подобни шлюзове. -**roleNormalizer**: `normalizeDeveloperRole()` вече приема параметър `preserveDeveloperRole` с поведение в три състояния (undefined=keep, true=keep, false=convert). -**DB**: Нови `getModelPreserveOpenAIDeveloperRole()` и `mergeModelCompatOverride()` в `models.ts`.### Bug Fixes\n\n-**Табло за управление на KIRO MITM**(#481/#487): `CLIToolsPageClient` сега насочва всеки инструмент `configType: \"mitm\"` към `AntigravityToolCard` (контроли за стартиране/спиране на MITM). Преди само Antigravity беше твърдо кодирана. -**AntigravityToolCard generic**: Използва `tool.image`, `tool.description`, `tool.id` вместо твърдо кодирани стойности на Antigravity. Предпазва от липсващи `defaultModels`.### Cleanup\n\n- Премахнат `ZWS_README_V2.md` (документи само за разработка от PR #494).### Issues Triaged (8)\n\n-**#487**— Затворен (KIRO MITM е коригиран в тази версия) -**#486**— информация за нуждите (проблем с Windows REG.exe PATH) -**#489**— информация за нуждите (Antigravity projectId липсва, необходимо е повторно свързване с OAuth) -**#492**— информация за нуждите (липсва app/server.js на неправилно управляван възел) -**#490**— Потвърдено (поточно предаване + блокиране на контекстния кеш, планирана корекция) -**#491**— Потвърдено (несъответствие на състоянието на удостоверяване на Codex) -**#493**— Потвърдено (префикс на името на модела на модален доставчик, предоставено заобиколно решение) -**#488**— Натрупване на заявки за функции (списъци с модели за автоматично актуализиране)---\n\n## [2.8.5] — 2026-03-19\n\n> Спринт: Коригиране на зомби SSE потоци, първи ход на контекстния кеш, KIRO MITM и сортиране на 5 външни проблеми.### Bug Fixes\n\n-**Зомби SSE потоци**(#473): Намаляване на `STREAM_IDLE_TIMEOUT_MS` от 300s → 120s за по-бързо комбо резервно връщане, когато доставчиците висят по средата на потока. Може да се конфигурира чрез env var. -**Context Cache Tag**(#474): Коригирайте `injectModelTag()` за обработка на заявки за първи ход (без помощни съобщения) — защитата на контекстния кеш вече работи от първия отговор. -**KIRO MITM**(#481): Променете KIRO `configType` от `guide` → `mitm`, така че таблото за управление да изобразява MITM Start/Stop контроли. -**E2E Test**(CI): Коригирайте `providers-bailian-coding-plan.spec.ts` — отхвърлете съществуващото модално наслагване, преди да щракнете върху бутона Добавяне на API ключ.### Closed Issues\n\n- #473 — Zombie SSE потоците заобикалят комбо резервния вариант\n- #474 — Липсва етикет `` на контекстния кеш при първо завъртане\n- #481 — MITM за KIRO не може да се активира от таблото за управление\n- #468 — Gemini CLI отдалечен сървър (заменен от #462 оттегляне)\n- #438 — Клод не може да записва файлове (проблем с външен CLI)\n- #439 — AppImage не работи (документирано решение на libfuse2)\n- #402 — ARM64 DMG \"повреден\" (документирано xattr -cr решение)\n- #460 — CLI не може да се изпълнява на Windows (документирана корекция на PATH)---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Отмяна на Gemini CLI, корекция на i18n за VM ръководство, корекция на сигурността на dependabot, разширяване на схемата на доставчика.### Функции\n\n-**Отмяна на Gemini CLI**(#462): Маркирайте доставчика на `gemini-cli` като отхвърлен с предупреждение — Google ограничава използването на OAuth от трети страни от март 2026 г. -**Схема на доставчика**(#462): Разширете валидирането на Zod с незадължителни полета `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint`### Bug Fixes\n\n-**VM Guide i18n**(#471): Добавяне на `VM_DEPLOYMENT_GUIDE.md` към конвейера за превод на i18n, повторно генериране на всички 30 локални превода от английски източник (бяха заседнали на португалски)### Сигурност\n\n-**deps**: Bump `flatted` 3.3.3 → 3.4.2 — поправя CWE-1321 прототипно замърсяване (#484, @dependabot)### Closed Issues\n\n- #472 — Регресия на псевдонимите на модела (коригирана във v2.8.2)\n- #471 — Преводите на ръководството за VM са повредени\n- #483 — Завършващо `data: null` след `[DONE]` (коригирано във v2.8.3)### Merged PRs\n\n- #484 — deps: изравняване от 3.3.3 на 3.4.2 (@dependabot)---\n\n## [2.8.3] — 2026-03-19\n\n> Спринт: чешки i18n, корекция на SSE протокол, превод на ръководство за VM.### Функции\n\n-**Чешки език**(#482): Пълен чешки (cs) i18n — 22 документа, 2606 UI низа, актуализации за превключване на език (@zen0bit) -**Ръководство за внедряване на VM**: Преведено от португалски на английски като изходен документ (@zen0bit)### Bug Fixes\n\n-**SSE Protocol**(#483): Спрете да изпращате крайни `data: null` след `[DONE]` сигнал — коригира `AI_TypeValidationError` в стриктни AI SDK клиенти (Zod-базирани валидатори)### Merged PRs\n\n- #482 — Добавяне на чешки език + Коригиране на VM_DEPLOYMENT_GUIDE.md английски източник (@zen0bit)---\n\n## [2.8.2] — 2026-03-19\n\n> Спринт: 2 обединени PR, коригиране на маршрута на псевдоними на модела, експортиране на регистрационни файлове и сортиране на проблеми.### Функции\n\n-**Експортиране на регистрационни файлове**: Нов бутон за експортиране на `/dashboard/logs` с падащо меню за времеви диапазон (1h, 6h, 12h, 24h). Изтегля JSON на регистрационни файлове на заявки/прокси/обаждания чрез `/api/logs/export` API (#user-request)### Bug Fixes\n\n-**Маршрутизиране на псевдонимите на модела**(#472): Настройки → Псевдонимите на модела вече засягат правилно маршрутизирането на доставчика, а не само откриването на формат. Преди това изходът на `resolveModelAlias()` се използваше само за `getModelTargetFormat()`, но оригиналният ID на модела беше изпратен на доставчика -**Използване на поток за промиване**(#480): Данните за използване от последното SSE събитие в буфера вече се извличат правилно по време на промиване на поток (обединени от @prakersh)### Merged PRs\n\n- #480 — Извличане на използването от оставащия буфер в манипулатора за промиване (@prakersh)\n- #479 — Добавяне на липсващи записи за ценообразуване на Codex 5.3/5.4 и Anthropic модел (@prakersh)---\n\n## [2.8.1] — 2026-03-19\n\n> Спринт: Пет PR-а на общността — корекции на регистъра на обажданията за поточно предаване, съвместимост с Kiro, анализ на кеш токени, превод на китайски и конфигурируеми идентификатори на обаждания с инструменти.### Функции\n\n-**feat(logs)**: Съдържанието на отговора на регистъра на обажданията вече се натрупва правилно от необработени части на доставчика (OpenAI/Claude/Gemini) преди превод, коригирайки празните полезни товари на отговора в режим на поточно предаване (#470, @zhangqiang8vip) -**feat(providers)**: Нормализиране на идентификатора на повикване на инструмент с 9 символа за всеки модел (в стил Mistral) — само модели с активирана опция получават съкратени идентификатори (#470) -**feat(api)**: Key PATCH API е разширен, за да поддържа полета `allowedConnections`, `name`, `autoResolve`, `isActive` и `accessSchedule` (#470) -**feat(dashboard)**: Оформление за първи отговор в потребителския интерфейс с детайли на регистрационния файл на заявката (#470) -**feat(i18n)**: Подобрен китайски (zh-CN) превод — пълен повторен превод (#475, @only4copilot)### 🐛 Bug Fixes\n\n-**fix(kiro)**: Премахване на инжектирано поле `model` от тялото на заявката — Kiro API отхвърля неизвестни полета от най-високо ниво (#478, @prakersh) -**fix(usage)**: Включете жетони за четене на кеша + токени за създаване на кеш в сумите за въвеждане на хронологията на използване за точни анализи (#477, @prakersh) -**fix(callLogs)**: Поддържа полета за използване на формат Claude (`input_tokens`/`output_tokens`) заедно с OpenAI формат, включва всички варианти на кеш токени (#476, @prakersh)---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Доставчик на Bailian Coding Plan с редактируеми основни URL адреси, плюс принос на общността за Alibaba Cloud и Kimi Coding.### Функции\n\n-**feat(providers)**: Добавен план за кодиране на Bailian (`bailian-coding-plan`) — Alibaba Model Studio с API, съвместим с Anthropic. Статичен каталог от 8 модела, включително Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5 и Kimi K2.5. Включва персонализирано валидиране на удостоверяване (400=валидно, 401/403=невалидно) (#467, @Mind-Dragon) -**feat(admin)**: Редактируем URL адрес по подразбиране в потоците за създаване/редактиране на администратора на доставчика — потребителите могат да конфигурират персонализирани базови URL адреси за всяка връзка. Съхраняван в „providerSpecificData.baseUrl“ с валидиране на Zod схема, отхвърлящо не-http(s) схеми (#467)### 🧪 Tests\n\n- Добавени са 30+ модулни теста и 2 e2e сценария за доставчик на план за кодиране на Bailian, обхващащ валидиране на удостоверяване, втвърдяване на схемата, поведение на ниво маршрут и интеграция на различни слоеве---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Два нови доставчици, предоставени от общността (Alibaba Cloud Coding, Kimi Coding API-key) и Docker pino fix.### Функции\n\n-**feat(providers)**: Добавена поддръжка на Alibaba Cloud Coding Plan с две OpenAI-съвместими крайни точки — `alicode` (Китай) и `alicode-intl` (международен), всеки с 8 модела (#465, @dtk1985) -**feat(providers)**: Добавен е специален път на доставчика `kimi-coding-apikey` — достъпът до Kimi Coding, базиран на API ключ, вече не е принудителен чрез OAuth-само маршрут `kimi-coding`. Включва регистър, константи, API за модели, конфигурация и тест за валидиране (#463, @Mind-Dragon)### 🐛 Bug Fixes\n\n-**fix(docker)**: Добавена липсваща зависимост `split2` към изображението на Docker — `pino-abstract-transport` го изисква по време на изпълнение, но не се копира в самостоятелния контейнер, причинявайки сривове `Не може да се намери модул 'split2'` (#459)---\n\n## [2.7.9] — 2026-03-18\n\n> Спринт: Преминаването на подпътеката на отговорите на Codex се поддържа естествено, сривът на Windows MITM е коригиран и схемите на Combos агент са коригирани.### Функции\n\n-**feat(codex)**: Преминаване на подпътеката на естествените отговори за Codex — нативно маршрутизира `POST /v1/responses/compact` към Codex нагоре по веригата, поддържайки съвместимост с Claude Code без премахване на суфикса `/compact` (#457)### 🐛 Bug Fixes\n\n-**fix(combos)**: Схемите на Zod (`updateComboSchema` и `createComboSchema`) вече включват `system_message`, `tool_filter_regex` и `context_cache_protection`. Коригира грешка, при която специфичните за агент настройки, създадени чрез таблото за управление, бяха тихо отхвърлени от слоя за валидиране на бекенда (#458) -**fix(mitm)**: Коригиран срив на профила на Kiro MITM в Windows — `node-machine-id` се провали поради липсващ `REG.exe` env, а резервният вариант хвърли фатална грешка `crypto is not defined`. Резервният вариант вече безопасно и правилно импортира крипто (#456)---\n\n## [2.7.8] — 2026-03-18\n\n> Спринт: Грешка при спестяване на бюджет + потребителски интерфейс с функции на комбо агент + корекция на сигурността на етикета omniModel.### 🐛 Bug Fixes\n\n-**fix(budget)**: \"Save Limits\" вече не връща 422 — `warningThreshold` вече се изпраща правилно като дроб (0–1) вместо процент (0–100) (#451) -**fix(combos)**: Вътрешният таг на `` вече е премахнат преди препращане на заявки към доставчици, предотвратявайки прекъсвания на кеш сесии (#454)### Функции\n\n-**feat(combos)**: Секцията с функции на агента е добавена към мода за създаване/редактиране на комбо — показване на `system_message` override, `tool_filter_regex` и `context_cache_protection` директно от таблото за управление (#454)---\n\n## [2.7.7] — 2026-03-18\n\n> Спринт: Срив на Docker pino, корекция на работния отговор на Codex CLI, синхронизиране на заключване на пакет.### 🐛 Bug Fixes\n\n-**fix(docker)**: `pino-abstract-transport` и `pino-pretty` вече изрично копирани в етапа на изпълнение на Docker — Самостоятелното проследяване на Next.js пропуска тези peer deps, причинявайки `Cannot find module pino-abstract-transport` срив при стартиране (#449) -**fix(responses)**: Премахване на `initTranslators()` от маршрута `/v1/responses` — сриваше Next.js работник с `работникът е излязъл` uncaughtException на Codex CLI заявки (#450)### 🔧 Maintenance\n\n-**chore(deps)**: `package-lock.json` вече се ангажира при всяка грешка на версията, за да се гарантира, че Docker `npm ci` използва точни версии на зависимости---\n\n## [2.7.5] — 2026-03-18\n\n> Спринт: Подобрения на UX и корекция на Windows CLI проверка на състоянието.### 🐛 Bug Fixes\n\n-**fix(ux)**: Показване на подсказка за парола по подразбиране на страницата за вход — новите потребители вече виждат „Парола по подразбиране: 123456“ под въвеждането на парола (#437) -**fix(cli)**: Claude CLI и други инструменти, инсталирани на npm, вече са правилно открити като работещи в Windows — spawn използва `shell:true`, за да разреши `.cmd` обвивки чрез PATHEXT (#447)---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Табло за инструменти за търсене, корекции на i18n, ограничения на Copilot, корекция за валидиране на Serper.### Функции\n\n-**feat(search)**: Добавяне на Playground за търсене (10-та крайна точка), страница с инструменти за търсене със Сравняване на доставчици/тръбопровод за прекласиране/хронология на търсенето, маршрутизиране на локално прекласиране, охрана на автентичността при API за търсене (#443 от @Regis-RCR)\n\n- Нов маршрут: `/dashboard/search-tools`\n- Запис в страничната лента под секцията за отстраняване на грешки\n- `GET /api/search/providers` и `GET /api/search/stats` с защита на удостоверяването\n- Местно маршрутизиране на доставчик_възли за `/v1/rerank`\n- 30+ i18n ключа в пространството на имената за търсене### 🐛 Bug Fixes\n\n-**fix(search)**: Коригиране на нормализатора на Brave news (връщаше 0 резултата), налагане на съкращаване на max_results след нормализиране, коригиране на URL за извличане на страница на крайни точки (#443 от @Regis-RCR) -**fix(analytics)**: Локализирайте етикетите за ден/дата на анализа — заменете твърдо кодираните португалски низове с `Intl.DateTimeFormat(locale)` (#444 от @hijak) -**fix(copilot)**: Правилно показване на типа акаунт на GitHub Copilot, филтриране на подвеждащи редове за неограничени квоти от таблото за управление на ограниченията (#445 от @hijak) -**fix(providers)**: Спрете да отхвърляте валидни Serper API ключове — третирайте не-4xx отговорите като валидно удостоверяване (#446 от @hijak)---\n\n## [2.7.3] — 2026-03-18\n\n> Спринт: Резервна корекция на Codex Direct API квота.### 🐛 Bug Fixes\n\n-**fix(codex)**: Блокиране на седмично изчерпани акаунти в директен резервен API (#440)\n\n- `resolveQuotaWindow()` съвпадение на префикса: `\"weekly\"` вече съвпада с `\"weekly (7d)\"` кеш ключове\n- `applyCodexWindowPolicy()` налага `useWeekly`/`use5h` превключва правилно\n- 4 нови регресионни теста (общо 766)---\n\n## [2.7.2] — 2026-03-18\n\n> Спринт: Корекции на контраста на потребителския интерфейс в светъл режим.### 🐛 Bug Fixes\n\n-**fix(logs)**: Коригиране на контраста на светъл режим в бутоните за филтър на регистрационните файлове на заявките и комбинираната значка (#378)\n\n- Бутоните за филтър за грешка/успех/комбинирани вече могат да се четат в лек режим\n- Значката за комбиниран ред използва по-силно виолетово в светъл режим---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Унифицирано маршрутизиране на уеб търсене (POST /v1/search) с 5 доставчика + корекции на сигурността Next.js 16.1.7 (6 CVE).### ✨ New Features\n\n-**feat(search)**: Унифицирано маршрутизиране на уеб търсене — `POST /v1/search` с 5 доставчика (Serper, Brave, Perplexity, Exa, Tavily)\n\n- Автоматично прехвърляне на грешки между доставчици, 6500+ безплатни търсения/месец\n- Кеш в паметта с обединяване на заявки (конфигурируем TTL)\n- Табло за управление: раздел Анализ на търсенето в `/dashboard/analytics` с разбивка на доставчика, честота на попадения в кеша, проследяване на разходите\n- Нов API: `GET /api/v1/search/analytics` за статистика на заявките за търсене\n- Миграция на DB: колона `request_type` в `call_logs` за проследяване на заявки без чат\n- Валидиране на Zod (`v1SearchSchema`), удостоверено, цената се записва чрез `recordCost()`### Сигурност\n\n-**deps**: Next.js 16.1.6 → 16.1.7 — коригира 6 CVE: -**Критично**: CVE-2026-29057 (контрабанда на HTTP заявки чрез http-прокси) -**Високо**: CVE-2026-27977, CVE-2026-27978 (WebSocket + действия на сървъра) -**Среден**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7### 📁 New Files\n\n| Файл | Цел |\n| ------------------------------------------------------------------------------------ | ------------------------------------------------------- | --- |\n| `open-sse/handlers/search.ts` | Манипулатор за търсене с маршрутизиране на 5 доставчика |\n| `open-sse/config/searchRegistry.ts` | Регистър на доставчика (авторизация, цена, квота, TTL) |\n| `open-sse/services/searchCache.ts` | Кеш в паметта с обединяване на заявки |\n| `src/app/api/v1/search/route.ts` | Next.js маршрут (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | API за статистика за търсене |\n| `src/app/(табло за управление)/табло за управление/analytics/SearchAnalyticsTab.tsx` | Табло за управление на Анализ |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB миграция |\n| `tests/unit/search-registry.test.mjs` | 277 реда модулни тестове | --- |\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: Вдъхновени от ClawRouter функции — флаг за toolCalling, многоезично откриване на намерения, резервен вариант, управляван от бенчмарк, дедупликация на заявки, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 ценообразуване.### ✨ New Models & Pricing\n\n-**feat(pricing)**: xAI Grok-4 Fast — `$0,20/$0,50 за 1M токени`, 1143ms p50 латентност, поддържа се извикване на инструмент -**feat(pricing)**: xAI Grok-4 (стандартен) — `$0,20/$1,50 за 1M токени`, разсъждаващ флагман -**feat(pricing)**: GLM-5 чрез Z.AI — `$0.5/1M`, 128K изходен контекст -**feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, разсъждения + агентски задачи -**feat(pricing)**: DeepSeek V3.2 — актуализирана цена `$0,27/$1,10 за 1M` -**feat(pricing)**: Kimi K2.5 чрез Moonshot API — директен достъп до Moonshot API -**feat(providers)**: добавен Z.AI доставчик (псевдоним „zai“) — семейство GLM-5 с 128K изход### 🧠 Routing Intelligence\n\n-**feat(registry)**: флаг `toolCalling` за модел в регистъра на доставчика — комбинациите вече могат да предпочитат/изискват модели с възможност за извикване на инструменти -**feat(scoring)**: Откриване на многоезично намерение за AutoCombo точкуване — PT/ZH/ES/AR скрипт/езикови модели влияят върху избора на модел за контекст на заявка -**feat(fallback)**: Резервни вериги, управлявани от бенчмарк — реални данни за латентност (p50 от `comboMetrics`), използвани за динамично пренареждане на приоритета на резервния вариант -**feat(dedup)**: Заявка за дедупликация чрез content-hash — 5-секунден прозорец за идемпотентност предотвратява дублиращи се обаждания на доставчика от повторен опит на клиенти -**feat(router)**: Pluggable `RouterStrategy` интерфейс в `autoCombo/routerStrategy.ts` — персонализирана логика за маршрутизиране може да бъде инжектирана без модифициране на ядрото### 🔧 MCP Server Improvements\n\n-**feat(mcp)**: 2 нови усъвършенствани схеми на инструменти: `omniroute_get_provider_metrics` (p50/p95/p99 на доставчик) и `omniroute_explain_route` (обяснение на решението за маршрутизиране) -**feat(mcp)**: обхватите за удостоверяване на MCP инструмента са актуализирани — добавен е обхватът на `metrics:read` за инструментите за показатели на доставчика -**feat(mcp)**: `omniroute_best_combo_for_task` вече приема параметър `languageHint` за многоезично маршрутизиране### 📊 Observability\n\n-**feat(metrics)**: `comboMetrics.ts` разширен с проследяване на процента на латентност в реално време за доставчик/акаунт -**feat(health)**: Health API (`/api/monitoring/health`) вече връща полета `p50Latency` и `errorRate` за всеки доставчик -**feat(usage)**: Миграция на историята на използването за проследяване на латентността на модела### 🗄️ DB Migrations\n\n-**feat(migrations)**: Нова колона `latency_p50` в таблицата `combo_metrics` — нулиране, безопасно за съществуващи потребители### 🐛 Bug Fixes / Closures\n\n-**close(#411)**: по-добра-sqlite3 хеширана разделителна способност на модула в Windows — коригирано във v2.6.10 (f02c5b5) -**close(#409)**: Завършванията на чат GitHub Copilot се провалят с Claude модели, когато са прикачени файлове — коригирано във v2.6.9 (838f1d6) -**close(#405)**: Дубликат на #411 — решен## [2.6.10] — 2026-03-17\n\n> Поправка за Windows: изтегляне на предварително изграден по-добър sqlite3 без node-gyp/Python/MSVC (#426).### 🐛 Bug Fixes\n\n-**fix(install/#426)**: В Windows, `npm install -g omniroute` се проваляше с `better_sqlite3.node не е валидно Win32 приложение`, тъй като комплектът нативния двоичен файл беше компилиран за Linux. Добавя**Стратегия 1.5**към `scripts/postinstall.mjs`: използва `@mapbox/node-pre-gyp install --fallback-to-build=false` (включен в `better-sqlite3`), за да изтегли правилния предварително изграден двоичен файл за текущата OS/arch, без да са необходими инструменти за изграждане (без node-gyp, без Python, без MSVC). Връща се към `npm rebuild` само ако изтеглянето е неуспешно. Добавя специфични за платформата съобщения за грешка с ясни инструкции за ръчно коригиране.---\n\n## [2.6.9] — 2026-03-17\n\n> Корекции на CI (t11 за всякакъв бюджет), корекция на грешка #409 (прикачени файлове чрез Copilot+Claude), корекция на работния процес на издание.### 🐛 Bug Fixes\n\n-**fix(ci)**: Премахнете думата \"any\" от коментари в `openai-responses.ts` и `chatCore.ts`, които не са преминали проверката на t11 `any` бюджет (фалшиво положително от коментари за преброяване на regex) -**fix(chatCore)**: Нормализиране на неподдържаните типове части на съдържанието преди препращане към доставчици (#409 — Курсорът изпраща `{type:\"file\"}`, когато `.md` файлове са прикачени; Copilot и други доставчици, съвместими с OpenAI, отхвърлят с \"type трябва да бъде или 'image_url', или 'text'\"; корекцията преобразува `file`/`document` блокове в `text` и изпуска неизвестни типове)### 🔧 Workflow\n\n-**chore(generate-release)**: Добавяне на ПРАВИЛО ЗА ATOMIC COMMIT — промяна на версията (`npm версия patch`) ТРЯБВА да се случи преди ангажиране на файлове с функции, за да се гарантира, че етикетът винаги сочи към ангажиране, съдържащо всички промени на версията заедно---\n\n## [2.6.8] — 2026-03-17\n\n> Спринт: Комбо като агент (системна подкана + филтър за инструменти), защита на контекстно кеширане, автоматично актуализиране, подробни регистрационни файлове, MITM Kiro IDE.### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n-**005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0` -**006_detailed_request_logs.sql**: Нова таблица `request_detail_logs` със задействане на ринг-буфер с 500 записа, включване чрез превключване на настройките### Функции\n\n-**feat(combo)**: Замяна на системно съобщение за комбо (#399 — полето `system_message` замества или инжектира системна подкана преди препращане към доставчика) -**feat(combo)**: Tool Filter Regex за Combo (#399 — `tool_filter_regex` запазва само инструменти, съответстващи на модела; поддържа OpenAI + Anthropic формати) -**feat(combo)**: Защита от кеширане на контекста (#401 — `context_cache_protection` маркира отговорите с `доставчик/модел` и закрепва модела за непрекъснатост на сесията) -**feat(settings)**: Автоматично обновяване чрез настройки (#320 — `GET /api/system/version` + `POST /api/system/update` — проверява npm регистъра и обновява във фонов режим с рестартиране на pm2) -**feat(logs)**: Подробни регистрационни файлове на заявки (#378 — улавя пълните тела на конвейера на 4 етапа: клиентска заявка, преведена заявка, отговор на доставчика, отговор на клиента — превключване за включване, 64KB изрязване, 500-влизащ пръстен буфер) -**feat(mitm)**: MITM Kiro IDE профил (#336 — `src/mitm/targets/kiro.ts` е насочен към api.anthropic.com, използва повторно съществуващата MITM инфраструктура)---\n\n## [2.6.7] — 2026-03-17\n\n> Спринт: подобрения на SSE, локални разширения provider_nodes, прокси регистър, корекции на Claude passthrough.### Функции\n\n-**feat(health)**: Проверка на изправността на фона за локални `provider_nodes` с експоненциално забавяне (30s→300s) и `Promise.allSettled` за избягване на блокиране (#423, @Regis-RCR) -**feat(embeddings)**: Насочете `/v1/embeddings` към локални `provider_nodes` — `buildDynamicEmbeddingProvider()` с валидиране на име на хост (#422, @Regis-RCR) -**feat(audio)**: Насочете TTS/STT към локални `provider_nodes` — `buildDynamicAudioProvider()` със SSRF защита (#416, @Regis-RCR) -**feat(proxy)**: Прокси регистър, API за управление и обобщаване на лимита на квотата (#429, @Regis-RCR)### 🐛 Bug Fixes\n\n-**fix(sse)**: Премахване на специфични за Claude полета (`metadata`, `anthropic_version`), когато целта е OpenAI-compat (#421, @prakersh) -**fix(sse)**: Извлечете използването на Claude SSE (`input_tokens`, `output_tokens`, кеш токени) в режим на преминаващ поток (#420, @prakersh) -**fix(sse)**: Генериране на резервен `call_id` за извиквания на инструменти с липсващи/празни идентификатори (#419, @prakersh) -**fix(sse)**: преминаване от Claude-to-Claude — предното тяло е напълно недокоснато, без повторен превод (#418, @prakersh) -**fix(sse)**: Филтрирайте осиротели `tool_result` елементи след уплътняване на контекста на Claude Code, за да избегнете 400 грешки (#417, @prakersh) -**fix(sse)**: Пропуснете извикванията на инструмента за празни имена в преводача на API за отговори, за да предотвратите безкрайните цикли на `placeholder_tool` (#415, @prakersh) -**fix(sse)**: Премахване на празни текстови блокове преди превод (#427, @prakersh) -**fix(api)**: Добавяне на `refreshable: true` към Claude OAuth тестова конфигурация (#428, @prakersh)### 📦 Dependencies\n\n- Премахване на `vitest`, `@vitest/*` и свързани devDependencies (#414, @dependabot)---\n\n## [2.6.6] — 2026-03-17\n\n> Актуална корекция: Съвместимост с Turbopack/Docker — премахнете протокола `node:` от всички импортирания `src/`.### 🐛 Bug Fixes\n\n-**fix(build)**: Премахнат е префиксът на протокола `node:` от инструкциите `import` в 17 файла под `src/`. Импортиранията на `node:fs`, `node:path`, `node:url`, `node:os` и т.н. причиниха `Ecmascript файлът имаше грешка` при компилации на Turbopack (Next.js 15 Docker) и при надстройки от по-стари глобални инсталации на npm. Засегнати файлове: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts` и 12 други в `src/app/api/` и `src/lib/`. -**chore(workflow)**: Актуализиран `generate-release.md`, за да направи**задължителни**стъпки за синхронизиране на Docker Hub и разгръщане на двоен VPS във всяко издание.---\n\n## [2.6.5] — 2026-03-17\n\n> Спринт: филтриране на параметрите на модела на разсъжденията, корекция 404 на местен доставчик, доставчик на Kilo Gateway, неравности на зависимостта.### ✨ New Features\n\n-**feat(api)**: Добавен**Kilo Gateway**(`api.kilo.ai`) като нов доставчик на API ключове (псевдоним `kg`) — 335+ модела, 6 безплатни модела, 3 модела за автоматично маршрутизиране (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Преминаващи модели, поддържани чрез крайна точка `/api/gateway/models`. (PR #408 от @Regis-RCR)### 🐛 Bug Fixes\n\n-**fix(sse)**: Премахване на неподдържаните параметри за разсъждаващи модели (o1, o1-mini, o1-pro, o3, o3-mini). Моделите в семейството `o1`/`o3` отхвърлят `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs` и `n` с HTTP 400. Параметрите вече се премахват в слоя `chatCore` преди препращане. Използва декларативно поле `unsupportedParams` за модел и предварително изчислена O(1) карта за търсене. (PR #412 от @Regis-RCR) -**fix(sse)**: Локален доставчик 404 вече води до**заключване само за модел (5 секунди)**вместо заключване на ниво връзка (2 минути). Когато локален бекенд за изводи (Ollama, LM Studio, oMLX) върне 404 за неизвестен модел, връзката остава активна и другите модели продължават да работят незабавно. Също така поправя съществуващ бъг, при който `model` не беше предаден на `markAccountUnavailable()`. Местни доставчици, открити чрез име на хост (`localhost`, `127.0.0.1`, `::1`, разширяемо чрез `LOCAL_HOSTNAMES` env var). (PR #410 от @Regis-RCR)### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `агентна база` 7 → 8---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n-**fix(providers)**: Премахнати несъществуващи имена на модели в 5 доставчика: -**gemini / gemini-cli**: премахнати `gemini-3.1-pro/flash` и `gemini-3-*-preview` (не съществуват в Google API v1beta); заменено с `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash` -**antigravity**: премахнати `gemini-3.1-pro-high/low` и `gemini-3-flash` (невалидни вътрешни псевдоними); заменени с реални 2.x модели -**github (Copilot)**: премахнати `gemini-3-flash-preview` и `gemini-3-pro-preview`; заменен с `gemini-2.5-flash` -**nvidia**: коригирано `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM използва пространство от имена `meta/` за Meta модели); добавени `nvidia/llama-3.1-70b-instruct` и `nvidia/llama-3.1-405b-instruct` -**fix(db/combo)**: Актуализиран `free-stack` комбо на отдалечена DB: премахнато `qw/qwen3-coder-plus` (изтекъл токен за опресняване), коригирано `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, коригирано `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, добавено `if/deepseek-v3.2`---\n\n## [2.6.3] — 2026-03-16\n\n> Спринт: zod/pino hash-strip, включен в конвейер за изграждане, добавен синтетичен доставчик, VPS PM2 път коригиран.### 🐛 Bug Fixes\n\n-**fix(build)**: Turbopack hash-strip вече работи по време на**компилиране**за ВСИЧКИ пакети — не само за `better-sqlite3`. Стъпка 5.6 в `prepublish.mjs` обхожда всеки `.js` в `app/.next/server/` и премахва 16-значния шестнадесетичен суфикс от всеки хеширан `require()`. Коригира `zod-dcb22c...`, `pino-...` и т.н. MODULE_NOT_FOUND при глобални инсталации на npm. Затваря #398 -**fix(deploy)**: PM2 и на двата VPS сочеше към остарели git-clone директории. Преконфигуриран на `app/server.js` в глобалния пакет npm. Актуализиран работен процес `/deploy-vps` за използване на `npm pack + scp` (npm регистърът отхвърля 299MB пакети).### Функции\n\n-**feat(provider)**: Синтетичен ([synthetic.new](https://synthetic.new)) — фокусирано върху поверителността заключение, съвместимо с OpenAI. `passthroughModels: true` за динамичен каталог с модели HuggingFace. Първоначални модели: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 от @Regis-RCR)### 📋 Issues Closed\n\n-**close #398**: npm хеш регресия — коригирано от хеш-лента по време на компилиране в prepublish -**triage #324**: Екранна снимка на грешка без стъпки — изисквани подробности за възпроизвеждане---\n\n## [2.6.2] — 2026-03-16\n\n> Спринт: хеширането на модула е напълно фиксирано, 2 PR са обединени (филтър за антропни инструменти + потребителски пътища на крайни точки), добавен доставчик на Alibaba Cloud DashScope, 3 остарели проблеми са затворени.### 🐛 Bug Fixes\n\n-**fix(build)**: Разширена хеш-лента `externals` на webpack за покриване на ВСИЧКИ `serverExternalPackages`, а не само `better-sqlite3`. Next.js 16 Turbopack хешира `zod`, `pino` и всеки друг външен сървърен пакет в имена като `zod-dcb22c6336e0bc69`, които не съществуват в `node_modules` по време на изпълнение. HASH_PATTERN regex catch-all сега премахва суфикса от 16 знака и се връща към името на основния пакет. Също така добавен `NEXT_PRIVATE_BUILD_WORKER=0` в `prepublish.mjs` за подсилване на режима на webpack, плюс сканиране след компилация, което отчита всички останали хеширани реф. (#396, #398, PR #403) -**fix(chat)**: Имената на инструменти в антропичен формат (`tool.name` без обвивка `.function`) бяха премахнати тихо от филтъра за празни имена, въведен в #346. LiteLLM проксира заявки с префикс `anthropic/` във формат на API на Anthropic Messages, което кара всички инструменти да бъдат филтрирани и Anthropic да връща `400: tool_choice.any може да бъде посочен само при предоставяне на инструменти`. Коригирано чрез връщане към „tool.name“, когато „tool.function.name“ отсъства. Добавени са 8 регресионни единични теста. (PR #397)### Функции\n\n-**feat(api)**: Персонализирани пътища на крайни точки за възли на доставчици, съвместими с OpenAI — конфигурирайте `chatPath` и `modelsPath` за възел (напр. `/v4/chat/completions`) в потребителския интерфейс на връзката на доставчика. Включва миграция на DB (`003_provider_node_custom_paths.sql`) и дезинфекция на пътя на URL (без преминаване на `..`, трябва да започва с `/`). (PR #400) -**feat(provider)**: Alibaba Cloud DashScope е добавен като OpenAI-съвместим доставчик. Международна крайна точка: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 модела: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Удостоверяване: API ключ на носител.### 📋 Issues Closed\n\n-**close #323**: Cline грешка при свързване `[object Object]` — коригирана във v2.3.7; инструктира потребителя да надстрои от v2.2.9 -**close #337**: Кредитно проследяване на Kiro — внедрено във v2.5.5 (#381); посочи потребителя към Табло → Използване -**триаж #402**: ARM64 macOS DMG повреден — поискана версия на macOS, точна грешка и препоръчано заобиколно решение `xattr -d com.apple.quarantine`---\n\n## [2.6.1] — 2026-03-15\n\n> Критична корекция при стартиране: глобалните инсталации на v2.6.0 npm се сринаха с грешка 500 поради грешка с хеширане на име на модул Turbopack/webpack в инструменталната кука Next.js 16.### 🐛 Bug Fixes\n\n-**fix(build)**: Принуждава `better-sqlite3` винаги да се изисква от точното му име на пакет в пакета на сървъра на webpack. Next.js 16 компилира инструменталната кука в отделна част и излъчва `require('better-sqlite3-')` — хеширано име на модул, което не съществува в `node_modules` — въпреки че пакетът е посочен в `serverExternalPackages`. Добавена е изрична функция `externals` към конфигурацията на уебпакета на сървъра, така че пакетът винаги излъчва `require('better-sqlite3')`, разрешавайки стартирането `500 Internal Server Error` при чисти глобални инсталации. (#394, PR #395)### 🔧 CI\n\n-**ci**: Добавен `workflow_dispatch` към `npm-publish.yml` със защита на синхронизирането на версията за ръчни задействания (#392) -**ci**: Добавен `workflow_dispatch` към `docker-publish.yml`, актуализирани GitHub действия до най-новите версии (#392)---\n\n## [2.6.0] - 2026-03-15\n\n> Спринт за разрешаване на проблеми: поправени са 4 грешки, подобрен UX на журналите, добавено проследяване на кредита на Kiro.### 🐛 Bug Fixes\n\n-**fix(media)**: ComfyUI и SD WebUI вече не се показват в списъка с доставчици на медийната страница, когато не са конфигурирани — извлича `/api/providers` при монтиране и скрива локалните доставчици без връзки (#390) -**fix(auth)**: Round-robin вече не избира повторно акаунти с ограничена скорост веднага след охлаждане — `backoffLevel` вече се използва като основен ключ за сортиране в ротацията на LRU (#340) -**fix(oauth)**: Qoder (и други доставчици, които пренасочват към техния собствен потребителски интерфейс) вече не оставят модала OAuth заседнал в „Изчакване за упълномощаване“ — автоматичен преход на детектор при затворен изскачащ прозорец към режим на ръчно въвеждане на URL (#344) -**fix(logs)**: Таблицата с регистрационни файлове на заявките вече може да се чете в светъл режим — значките за състояние, броят на токените и комбинираните тагове използват адаптивни цветови класове `dark:` (#378)### Функции\n\n-**feat(kiro)**: Кредитното проследяване на Kiro е добавено към инструмента за извличане на използване — заявки `getUserCredits` от крайна точка на AWS CodeWhisperer (#337)### 🛠 Chores\n\n-**chore(tests)**: Подравнени `test:plan3`, `test:fixes`, `test:security`, за да се използва същото средство за зареждане `tsx/esm` като `npm test` — елиминира фалшивите отрицателни резултати за разрешаване на модула при целеви изпълнения (PR #386)---\n\n## [2.5.9] - 2026-03-15\n\n> Корекция на родния пропуск на Codex + втвърдяване на валидирането на тялото на маршрута.### 🐛 Bug Fixes\n\n-**fix(codex)**: Запазване на естественото преминаване на Responses API за клиенти на Codex — избягва ненужни мутации на превода (PR #387) -**fix(api)**: Валидирайте телата на заявките за маршрути за ценообразуване/синхронизиране и маршрутизиране на задачи — предотвратява сривове от неправилно формирани входове (PR #388) -**fix(auth)**: JWT тайните се запазват при рестартирания чрез `src/lib/db/secrets.ts` — елиминира 401 грешки след рестартиране на pm2 (PR #388)---\n\n## [2.5.8] - 2026-03-15\n\n> Корекция на компилация: възстановяване на VPS свързаността, прекъсната от v2.5.7 непълно публикуване.### 🐛 Bug Fixes\n\n-**fix(build)**: `scripts/prepublish.mjs` все още използва остарял флаг `--webpack`, причинявайки неуспешна неуспешна самостоятелна компилация на Next.js — публикуването на npm е завършено без `app/server.js`, нарушавайки внедряването на VPS---\n\n## [2.5.7] - 2026-03-15\n\n> Корекции при обработка на грешки в медийната площадка.### 🐛 Bug Fixes\n\n-**fix(media)**: Транскрипцията „Изисква се API ключ“ фалшиво положителна, когато аудиото не съдържа реч (музика, тишина) — сега вместо това показва „Няма открита реч“ -**fix(media)**: `upstreamErrorResponse` в `audioTranscription.ts` и `audioSpeech.ts` вече връща правилен JSON (`{error:{message}}`), позволявайки правилно откриване на грешки в идентификационните данни 401/403 в MediaPageClient -**fix(media)**: `parseApiError` вече обработва полето `err_msg` на Deepgram и открива `\"api key\"` в съобщенията за грешка за точна класификация на грешките при идентификационните данни---\n\n## [2.5.6] - 2026-03-15\n\n> Критични корекции на сигурността/удостоверяването: Antigravity OAuth повреден + JWT сесиите са загубени след рестартиране.### 🐛 Bug Fixes\n\n-**fix(oauth) #384**: Antigravity Google OAuth сега изпраща правилно `client_secret` към крайната точка на токена. Резервният вариант за `ANTIGRAVITY_OAUTH_CLIENT_SECRET` беше празен низ, който е фалшив — така че `client_secret` никога не е бил включен в заявката, причинявайки грешки `\"client_secret is missing\"` за всички потребители без персонализирана env var. Затваря #383. -**fix(auth) #385**: `JWT_SECRET` вече се запазва в SQLite (`namespace='secrets'`) при първото поколение и се презарежда при следващи стартирания. Преди това се генерираше нова произволна тайна при всяко стартиране на процес, което правеше невалидни всички съществуващи бисквитки/сесии след всяко рестартиране или надграждане. Засяга както `JWT_SECRET`, така и `API_KEY_SECRET`. Затваря #382.---\n\n## [2.5.5] - 2026-03-15\n\n> Корекция на дедупиране на списък с модели, самостоятелна защита на изграждането на Electron и проследяване на кредити на Kiro.### 🐛 Bug Fixes\n\n-**fix(models) #380**: `GET /api/models` вече включва псевдоними на доставчика при изграждане на филтъра за активен доставчик — моделите за `claude` (псевдоним `cc`) и `github` (псевдоним `gh`) винаги се показват независимо от това дали връзката е конфигурирана, защото ключовете `PROVIDER_MODELS` са псевдоними, но DB връзките са съхранявани под идентификатори на доставчик. Коригирано чрез разширяване на идентификатора на всеки активен доставчик, за да включва също неговия псевдоним чрез „PROVIDER_ID_TO_ALIAS“. Затваря #353. -**fix(electron) #379**: Нов `scripts/prepare-electron-standalone.mjs` поставя специален пакет `/.next/electron-standalone` преди пакетирането на Electron. Прекратява с ясна грешка, ако `node_modules` е символна връзка (electron-builder би изпратил зависимост по време на изпълнение на машината за изграждане). Дезинфекция на пътя между платформи чрез `path.basename`. От @kfiramar.### ✨ New Features\n\n-**feat(kiro) #381**: Проследяване на кредитния баланс на Kiro — крайната точка за използване вече връща кредитни данни за акаунтите на Kiro чрез извикване на `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (същата крайна точка, която Kiro IDE използва вътрешно). Връща оставащите кредити, общата сума, датата на подновяване и нивото на абонамента. Затваря #337.## [2.5.4] - 2026-03-15\n\n> Корекция при стартиране на Logger, корекция на сигурността при стартиране на влизане и подобрение на надеждността на dev HMR. Подсилена CI инфраструктура.### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n-**fix(logger) #376**: Възстановяване на пътя на pino транспортния регистратор — `formatters.level`, комбиниран с `transport.targets`, се отхвърля от pino. Конфигурациите, поддържани от транспорт, вече премахват инструмента за форматиране на ниво чрез `getTransportCompatibleConfig()`. Също така коригира картографирането на числово ниво в `/api/logs/console`: `30→info, 40→warn, 50→error` (беше изместено с едно). -**fix(login) #375**: Страницата за вход вече стартира от публичната крайна точка `/api/settings/require-login` вместо защитената `/api/settings`. При защитени с парола настройки страницата за предварително удостоверяване получаваше 401 и ненужно се връщаше към безопасни настройки по подразбиране. Публичният маршрут вече връща всички метаданни за първоначално зареждане (`requireLogin`, `hasPassword`, `setupComplete`) с консервативен 200 резервен вариант при грешка. -**fix(dev) #374**: Добавяне на `localhost` и `127.0.0.1` към `allowedDevOrigins` в `next.config.mjs` — HMR websocket беше блокиран при достъп до приложението чрез обратен адрес, създавайки повтарящи се кръстосани предупреждения.### 🔧 CI & Infrastructure\n\n-**ESLint OOM fix**: `eslint.config.mjs` сега игнорира `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**` и `clipr/**` — ESLint се срива с JS heap OOM чрез сканиране на двоични петна на VS Code и компилиран буци. -**Поправка на тест на единица**: Премахнато остаряло `ALTER TABLE provider_connections ADD COLUMN \"group\"` от 2 тестови файла — колоната вече е част от основната схема (добавена в #373), причинявайки `SQLITE_ERROR: дублирано име на колона` при всяко изпълнение на CI. -**Pre-commit hook**: Добавен е `npm run test:unit` към `.husky/pre-commit` — модулните тестове вече блокират повредени комити, преди да достигнат CI.## [2.5.3] - 2026-03-14\n\n> Критични корекции на грешки: миграция на DB схема, зареждане при стартиране на env, изчистване на състоянието на грешка на доставчика и корекция на подсказка за i18n. Подобрения в качеството на кода върху всеки PR.### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n-**fix(db) #373**: Добавяне на колона `provider_connections.group` към основната схема + миграция за запълване за съществуващи бази данни — колоната е използвана във всички заявки, но липсва в дефиницията на схемата -**fix(i18n) #371**: Замяна на несъществуващ ключ `t(\"deleteConnection\")` със съществуващ ключ `providers.delete` — поправя `MISSING_MESSAGE: providers.deleteConnection` грешка по време на изпълнение на страницата с подробности за доставчика -**fix(auth) #372**: Изчистване на остарели метаданни за грешка (`errorCode`, `lastErrorType`, `lastErrorSource`) от акаунти на доставчик след истинско възстановяване — преди това възстановените акаунти продължаваха да се показват като неуспешни -**fix(startup) #369**: Унифициране на зареждането на env в `npm run start`, `run-standalone.mjs` и Electron за спазване на `DATA_DIR/.env → ~/.omniroute/.env → ./.env` приоритет — предотвратява генерирането на нов `STORAGE_ENCRYPTION_KEY` върху съществуваща криптирана база данни### 🔧 Code Quality\n\n- Документирани шаблони `result.success` срещу `response?.ok` в `auth.ts` (и двете преднамерени, вече са обяснени)\n- Нормализиран `overridePath?.trim()` в `electron/main.js`, за да съответства на `bootstrap-env.mjs`\n- Добавен коментар за поръчка на сливане `preferredEnv` при стартиране на Electron\n\n> Политика за квоти на акаунти в Codex с автоматично завъртане, бързо превключване на нива, gpt-5.4 модел и корекция на етикета за анализ.### ✨ New Features (PRs #366, #367, #368)\n\n-**Правила за квота на Codex (PR #366)**: Прозорецът за квота от 5 часа/седмично за акаунт се превключва в таблото за управление на доставчика. Акаунтите се пропускат автоматично, когато активираните прозорци достигнат прага от 90% и се допускат отново след „resetAt“. Включва `quotaCache.ts` с инструмент за получаване на състояние без странични ефекти. -**Codex Fast Tier Toggle (PR #367)**: Табло → Настройки → Codex Service Tier. Превключвателят за изключване по подразбиране инжектира `service_tier: \"flex\"` само за заявки на Codex, намалявайки разходите ~80%. Пълен стек: UI раздел + API крайна точка + изпълнител + преводач + възстановяване при стартиране. -**gpt-5.4 Model (PR #368)**: Добавя `cx/gpt-5.4` и `codex/gpt-5.4` към регистъра на моделите на Codex. Включен регресионен тест.### 🐛 Bug Fixes\n\n-**поправка #356**: Графиките на анализ (Най-добър доставчик, по акаунт, разбивка на доставчика) вече показват четими за човека имена/етикети на доставчици вместо необработени вътрешни идентификатори за доставчици, съвместими с OpenAI.\n\n> Основно издание: стратегия за стриктно произволно маршрутизиране, контроли за достъп на API ключове, групи за свързване, синхронизиране на външно ценообразуване и критични корекции на грешки за мислещи модели, комбинирано тестване и валидиране на името на инструмента.### ✨ New Features (PRs #363 & #365)\n\n-**Стратегия за строго произволно маршрутизиране**: тесте за разбъркване на Fisher-Yates с гаранция против повторение и сериализация на mutex за едновременни заявки. Независими тестета за комбо и за доставчик. -**API Key Access Controls**: `allowedConnections` (ограничаване на връзките, които даден ключ може да използва), `is_active` (активиране/деактивиране на ключ с 403), `accessSchedule` (базиран на времето контрол на достъпа), `autoResolve` превключване, преименуване на ключове чрез PATCH. -**Групи за свързване**: Групирайте връзките на доставчика по среда. Изглед на акордеон в страницата с ограничения с постоянство на localStorage и интелигентно автоматично превключване. -**Външно синхронизиране на цените (LiteLLM)**: 3-степенна резолюция на ценообразуването (потребителят отменя → синхронизирано → по подразбиране). Включете се чрез `PRICING_SYNC_ENABLED=true`. MCP инструмент `omniroute_sync_pricing`. 23 нови теста. -**i18n**: 30 езика, актуализирани със стриктно произволна стратегия, низове за управление на ключове за API. pt-BR напълно преведен.### 🐛 Bug Fixes\n\n-**поправка #355**: Времето за изчакване на потока при неактивност се увеличи от 60s на 300s — предотвратява прекъсването на модели с разширено мислене (claude-opus-4-6, o3 и т.н.) по време на дълги фази на разсъждение. Може да се конфигурира чрез `STREAM_IDLE_TIMEOUT_MS`. -**поправка #350**: Комбинираният тест вече заобикаля `REQUIRE_API_KEY=true` с помощта на вътрешна заглавка и универсално използва формат, съвместим с OpenAI. Времето за изчакване е удължено от 15s на 20s. -**поправка #346**: Инструменти с празно `function.name` (препратено от Claude Code) вече се филтрират преди доставчиците нагоре по веригата да ги получат, предотвратявайки грешки \"Невалиден вход [N].name: празен низ\".### 🗑️ Closed Issues\n\n-**#341**: Разделът за отстраняване на грешки е премахнат — замяната е `/dashboard/logs` и `/dashboard/health`.\n\n> Поддръжка на API Key Round-Robin за настройки на доставчици с множество ключове и потвърждение за маршрутизиране със заместващи знаци и квотен прозорец, който вече е налице.### ✨ New Features\n\n-**API Key Round-Robin (T07)**: Връзките на доставчика вече могат да съдържат множество API ключове (Редактиране на връзка → Допълнителни API ключове). Заявките се редуват кръгово между първични + допълнителни ключове чрез „providerSpecificData.extraApiKeys[]“. Ключовете се съхраняват в паметта, индексирани за връзка — не са необходими промени в схемата на DB.### 📝 Already Implemented (confirmed in audit)\n\n-**Wildcard Model Routing (T13)**: `wildcardRouter.ts` със съвпадение на заместващи знаци в глобален стил (`gpt*`, `claude-?-sonnet` и т.н.) вече е интегриран в `model.ts` със специфично класиране. -**Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` вече автоматично напредва в прозореца — ако `Date.now() > entry.until`, заключването се изтрива незабавно (няма остаряло блокиране).\n\n> Подобряване на потребителския интерфейс, допълнения в стратегията за маршрутизиране и елегантно обработване на грешки за ограничения на употребата.### ✨ New Features\n\n-**Fill-First & P2C Routing Strategies**: Добавени са `fill-first` (източване на квота, преди да продължите) и `p2c` (избор с ниска латентност при Power-of-Two-Choices) към инструмента за избор на комбинирана стратегия, с пълни панели с насоки и цветно кодирани значки. -**Предварително зададени модели на безплатен стек**: Създаването на комбо с шаблона Free Stack вече автоматично попълва 7 най-добри в класа безплатни модела на доставчик (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Потребителите просто активират доставчиците и получават комбо от $0/месец веднага. -**Wider Combo Modal**: Модалът за създаване/редактиране на комбо вече използва `max-w-4xl` за удобно редактиране на големи комбинации.### 🐛 Bug Fixes\n\n-**Страница с ограничения HTTP 500 за Codex & GitHub**: `getCodexUsage()` и `getGitHubUsage()` вече връщат удобно за потребителя съобщение, когато доставчикът върне 401/403 (изтекъл токен), вместо да изхвърля и причинява грешка 500 на страницата с ограничения. -**MaintenanceBanner фалшиво положителен**: Банерът вече не показва фалшиво „Сървърът е недостъпен“ при зареждане на страницата. Поправено чрез извикване на `checkHealth()` незабавно при монтиране и премахване на остаряло затваряне на състояние `show`. -**Подсказки за икона на доставчик**: Бутоните за редактиране (молив) и изтриване на икони в реда за свързване на доставчика вече имат собствени HTML подсказки — всичките 6 икони за действие вече са самостоятелно документирани.\n\n> Множество подобрения от анализ на проблеми на общността, поддръжка на нов доставчик, корекции на грешки за проследяване на токени, маршрутизиране на модела и надеждност на стрийминг.### ✨ New Features\n\n-**Task-Aware Smart Routing (T05)**: Автоматичен избор на модел въз основа на типа съдържание на заявката — кодиране → deepseek-chat, анализ → gemini-2.5-pro, vision → gpt-4o, обобщение → gemini-2.5-flash. Може да се конфигурира чрез Настройки. Нов `GET/PUT/POST /api/settings/task-routing` API. -**HuggingFace Provider**: Добавен HuggingFace Router като OpenAI-съвместим доставчик с Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini. -**Vertex AI Provider**: Добавен Vertex AI (Google Cloud) доставчик с Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude чрез Vertex. -**Качване на файлове на Playground**: Качване на аудио за транскрипция, качване на изображения за модели на зрение (автоматично откриване по име на модел), рендиране на вградено изображение за резултати от генериране на изображение. -**Визуална обратна връзка за избор на модел**: Вече добавените модели в инструмента за избор на комбо вече показват ✓ зелена значка — предотвратява дублиране на объркване. -**Съвместимост с Qwen (PR #352)**: Актуализирани настройки за пръстов отпечатък на потребителския агент и CLI за съвместимост с Qwen доставчик. -**Кръгово управление на състоянието (PR #349)**: Подобрена циклична логика за обработка на изключени акаунти и правилно поддържане на състоянието на ротация. -**Clipboard UX (PR #360)**: Подсилени операции с клипборда с резервен вариант за незащитени контексти; Подобрения в нормализирането на инструмента Claude.### 🐛 Bug Fixes\n\n-**Коригиране #302 — OpenAI SDK stream=False изпуска tool_calls**: T01 Договарянето на заглавката за приемане вече не налага поточно предаване, когато `body.stream` е изрично `false`. Причиняваше тихо премахване на tool_calls при използване на OpenAI Python SDK в режим без поточно предаване. -**Коригиране #73 — Claude Haiku, насочен към OpenAI без префикс на доставчика**: моделите `claude-*`, изпратени без префикс на доставчик, сега правилно се насочват към доставчика на `antigravity` (Anthropic). Добавена е и евристика `gemini-*`/`gemma-*` → `gemini`. -**Коригиране #74 — Броят на токените винаги е 0 за поточно предаване на Antigravity/Claude**: SSE събитието `message_start`, което носи `input_tokens`, не се анализира от `extractUsage()`, причинявайки отпадане на броя на всички входни токени. Проследяването на токени за вход/изход вече работи правилно за поточно предаване на отговори. -**Коригиране #180 — Дубликати за импортиране на модели без обратна връзка**: `ModelSelectModal` сега показва ✓ зелено осветяване за модели, които вече са в комбото, което прави очевидно, че те вече са добавени. -**Грешки при генериране на медийни страници**: Резултатите от изображенията вече се изобразяват като тагове `` вместо необработен JSON. Резултатите от транскрипцията се показват като четим текст. Грешките в идентификационните данни показват кехлибарен банер вместо безшумен отказ. -**Бутон за опресняване на токени на страницата на доставчика**: Добавен потребителски интерфейс за ръчно опресняване на токени за доставчиците на OAuth.### 🔧 Improvements\n\n-**Регистър на доставчици**: HuggingFace и Vertex AI добавени към `providerRegistry.ts` и `providers.ts` (frontend). -**Кеш за четене**: Нов `src/lib/db/readCache.ts` за ефективно кеширане на четене на DB. -**Quota Cache**: Подобрен квотен кеш с TTL-базирано изгонване.### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)### 📁 New Files\n\n| Файл | Цел |\n| --------------------------------------------- | ----------------------------------------------------------------- | ----------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Логика за маршрутизиране, съобразена със задачите (7 типа задачи) |\n| `src/app/api/settings/task-routing/route.ts` | API за конфигуриране на маршрутизиране на задачи |\n| `src/app/api/providers/[id]/refresh/route.ts` | Ръчно опресняване на токена за OAuth |\n| `src/lib/db/readCache.ts` | Ефективен кеш за четене на DB |\n| `src/shared/utils/clipboard.ts` | Закален клипборд с резервен | ## [2.4.1] - 2026-03-13 |\n\n### 🐛 Fix\n\n-**Модални комбинации: Свободен стек видим и изпъкнал**— Шаблонът за свободен стек беше скрит (4-ти в мрежата с 3 колони). Коригирано: преместено на позиция 1, превключено на решетка 2x2, така че всичките 4 шаблона да са видими, зелена граница + БЕЗПЛАТНО открояване на значка.## [2.4.0] - 2026-03-13\n\n> **Основно издание**— Безплатна екосистема на Stack, ремонт на площадката за транскрипция, 44+ доставчици, изчерпателна безплатна документация за ниво и подобрения на потребителския интерфейс навсякъде.### Функции\n\n-**Комбинации: Безплатен стек шаблон**— Нов 4-ти шаблон „Безплатен стек ($0)“ с използване на кръгов режим между Kiro + Qoder + Qwen + Gemini CLI. Предлага предварително изградената комбинация с нулеви разходи при първа употреба. -**Медия/Транскрипция: Deepgram по подразбиране**— Deepgram (Nova 3, $200 безплатно) вече е доставчикът на транскрипция по подразбиране. AssemblyAI ($50 безплатно) и Groq Whisper (безплатно завинаги), показани с безплатни кредитни значки. -**README: Раздел „Стартирайте безплатно“**— Нова таблица с 5 стъпки за ранен README, показваща как да настроите AI с нулеви разходи за минути. -**README: Комбинация за безплатна транскрипция**— Нов раздел с предложение за комбо Deepgram/AssemblyAI/Groq и безплатни кредитни подробности за всеки доставчик. -**providers.ts: флаг hasFree**— NVIDIA NIM, Cerebras и Groq, маркирани със значка hasFree и freeNote за потребителския интерфейс на доставчиците. -**i18n: templateFreeStack keys**— Комбиниран шаблон за безплатен стек, преведен и синхронизиран на всички 30 езика.## [2.3.16] - 2026-03-13\n\n### Документация\n\n-**README: 44+ доставчици**— Актуализирани всичките 3 срещания на „36+ доставчици“ до „44+“, отразяващи действителния брой кодова база (44 доставчици в providers.ts) -**README: Нов раздел \"🆓 Безплатни модели — Какво всъщност получавате\"**— Добавена е таблица със 7 доставчици с лимити на скоростта за всеки модел за: Kiro (Claude неограничен чрез AWS Builder ID), Qoder (5 модела неограничен), Qwen (4 модела неограничен), Gemini CLI (180K/месец), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/ден / 60K TPM), Groq (30 RPM / 14,4K RPD). Включва препоръката \\/usr/bin/bash Ultimate Free Stack combo. -**README: Актуализирана таблица с цените**— Добавен Cerebras към ниво API KEY, фиксиран NVIDIA от „1000 кредита“ на „dev-forever free“, актуализиран брой и имена на модели Qoder/Qwen -**README: Qoder 8→5 модели**(наименувани: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2) -**README: Qwen 3→4 модели**(наименувани: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)## [2.3.15] - 2026-03-13\n\n### Функции\n\n-**Auto-Combo Dashboard (Tier Priority)**: Добавен е `🏷️ Tier` като 7-ми етикет на коефициента на точкуване в дисплея с разбивка на факторите `/dashboard/auto-combo` — всичките 7 Auto-Combo коефициента на точкуване вече са видими. -**i18n — секция autoCombo**: Добавени са 20 нови ключа за превод за таблото за управление на Auto-Combo (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority` и т.н.) към всичките 30 езикови файла.## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n-**Qoder OAuth (#339)**: Възстановен е валидният `clientSecret` по подразбиране — преди това беше празен низ, което причиняваше \"лоши идентификационни данни на клиента\" при всеки опит за свързване. Публичните идентификационни данни вече са резервни по подразбиране (може да се замени чрез `QODER_OAUTH_CLIENT_SECRET` env var). -**MITM сървърът не е намерен (#335)**: `prepublish.mjs` вече компилира `src/mitm/*.ts` в JavaScript с помощта на `tsc`, преди да копира в пакета npm. Преди това бяха копирани само необработени файлове `.ts` — което означава, че `server.js` никога не е съществувал в глобалните инсталации на npm/Volta. -**GeminiCLI missing projectId (#338)**: Вместо да извежда твърда грешка 500, когато `projectId` липсва в съхранените идентификационни данни (напр. след рестартиране на Docker), OmniRoute вече записва предупреждение и се опитва да изпълни заявката — връща значима грешка от страна на доставчика вместо срив на OmniRoute. -**Несъответствие на версията на Electron (#323)**: Синхронизирана версията на `electron/package.json` с `2.3.13` (беше `2.0.13`), така че двоичната версия за настолен компютър съвпада с пакета npm.### ✨ New Models (#334)\n\n-**Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto` -**Кодекс**: `gpt5.4`### 🔧 Improvements\n\n-**Tier Scoring (API + Validation)**: Добавено е `tierPriority` (тегло `0.05`) към `ScoringWeights` Zod схема и `combos/auto` API маршрут — 7-ият точкуващ фактор вече е напълно приет от REST API и валидиран при въвеждане. теглото на `стабилност` е коригирано от `0,10` до `0,05`, за да се запази общата сума = `1,0`.### ✨ New Features\n\n-**Отчитане на нива на квота (автоматично комбинирано)**: Добавен е `tierPriority` като 7-ми фактор за оценяване — акаунтите с нива Ultra/Pro вече се предпочитат пред нивата Free, когато другите фактори са равни. Нови незадължителни полета `accountTier` и `quotaResetIntervalSecs` на `ProviderCandidate`. Актуализирани са всички 4 пакета с режими („бърз кораб“, „спестяващ разходи“, „първо качество“, „удобен офлайн“). -**Intra-Family Model Fallback (T5)**: Когато даден модел не е наличен (404/400/403), OmniRoute вече автоматично се връща към сродни модели от същото семейство, преди да върне грешка (`modelFamilyFallback.ts`). -**Конфигурируемо време за изчакване на API мост**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var позволява на операторите да настроят времето за изчакване на проксито (по подразбиране 30 секунди). Коригира грешки 504 при бавни отговори нагоре по веригата. (#332) -**Star History**: Заменен widget star-history.com със starchart.cc (`?variant=adaptive`) във всичките 30 README — адаптира се към светла/тъмна тема, актуализации в реално време.### 🐛 Bug Fixes\n\n-**Auth — Парола за първи път**: `INITIAL_PASSWORD` env var вече се приема при задаване на първата парола на таблото за управление. Използва `timingSafeEqual` за сравнение на постоянно време, предотвратявайки атаки за определяне на времето. (#333) -**Отрязване на README**: Коригиран е липсващ затварящ таг `` в раздела за отстраняване на неизправности, който е накарал GitHub да спре да изобразява всичко под него (технически стек, документи, пътна карта, сътрудници). -**pnpm install**: Премахнато е излишното заместване на `@swc/helpers` от `package.json`, което е в конфликт с пряката зависимост, причинявайки грешки `EOVERRIDE` на pnpm. Добавена е конфигурация `pnpm.onlyBuiltDependencies`. -**CLI Path Injection (T12)**: Добавен е `isSafePath()` валидатор в `cliRuntime.ts` за блокиране на преминаването на пътя и метасимволите на обвивката в `CLI_*_BIN` env vars. -**CI**: Регенериран `package-lock.json` след премахване на замяната, за да се коригират грешките `npm ci` в GitHub Actions.### 🔧 Improvements\n\n-**Формат на отговор (T1)**: `response_format` (json_schema/json_object) вече се инжектира като системна подкана за Claude, което позволява структурирана съвместимост на изхода. -**429 Повторен опит (T2)**: Вътрешен URL повторен опит за 429 отговора (2 × опита с 2 секунди закъснение) преди връщане към следващия URL адрес. -**Gemini CLI Headers (T3)**: Добавени са `User-Agent` и `X-Goog-Api-Client` заглавки за пръстови отпечатъци за съвместимост с Gemini CLI. -**Ценови каталог (T9)**: Добавени са ценови записи `deepseek-3.1`, `deepseek-3.2` и `qwen3-coder-next`.### 📁 New Files\n\n| Файл | Цел |\n| ------------------------------------------ | ---------------------------------------------------------------- | --------- |\n| `open-sse/services/modelFamilyFallback.ts` | Дефиниции на моделни семейства и вътрешносемейна резервна логика | ### Fixed |\n\n-**KiloCode**: времето за изчакване на проверката на състоянието на kilocode вече е фиксирано във v2.3.11 -**OpenCode**: Добавяне на отворен код към регистъра на cliRuntime с 15 секунди изчакване за проверка на състоянието -**OpenClaw / Cursor**: Увеличете времето за изчакване на проверката на здравето до 15 s за варианти с бавен старт -**VPS**: Инсталирайте droid и openclaw npm пакети; активирайте CLI_EXTRA_PATHS за kiro-cli -**cliRuntime**: Добавете регистрация на инструмента за отворен код и увеличете времето за изчакване за продължаване## [2.3.11] - 2026-03-12\n\n### Fixed\n\n-**KiloCode Healthcheck**: Увеличете `healthcheckTimeoutMs` от 4000ms на 15000ms — kilocode изобразява банер с ASCII лого при стартиране, причинявайки фалшиво `healthcheck_failed` при бавно/студено стартиране## [2.3.10] - 2026-03-12\n\n### Fixed\n\n-**Lint**: Коригирайте грешката `check:any-budget:t11` — заменете `as any` с `as Record` в OAuthModal.tsx (3 случая)### Docs\n\n-**CLI-TOOLS.md**: Пълно ръководство за всички 11 CLI инструмента (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw) -**i18n**: CLI-TOOLS.md синхронизиран на 30 езика с преведено заглавие + интро## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n-**/v1/completions**: Нова наследена крайна точка за завършвания на OpenAI — приема както `prompt` низ, така и `messages` масив, автоматично се нормализира във формат за чат -**EndpointPage**: Сега показва всички 3 типа крайни точки, съвместими с OpenAI: Завършвания на чат, API за отговори и наследени завършвания -**i18n**: Добавено е `completionsLegacy/completionsLegacyDesc` към 30 езикови файла### Fixed\n\n-**OAuthModal**: Коригиране на `[object Object]`, показван при всички грешки на връзката OAuth — правилно извличане на `.message` от обекти за отговор на грешка във всичките 3 извиквания `throw new Error(data.error)` (обмен, код на устройство, авторизиране)\n\n- Засяга Cline, Codex, GitHub, Qwen, Kiro и всички други доставчици на OAuth## [2.3.7] - 2026-03-12\n\n### Fixed\n\n-**Cline OAuth**: Добавяне на `decodeURIComponent` преди base64 декодиране, така че кодираните с URL кодове за удостоверяване от URL адреса за обратно извикване да се анализират правилно, коригирайки грешките „невалиден или изтекъл код за оторизация“ при отдалечени (LAN IP) настройки -**Cline OAuth**: `mapTokens` вече попълва `name = firstName + lastName || имейл`, така че Cline акаунтите показват реални потребителски имена вместо „Account #ID“ -**Имена на OAuth акаунти**: Всички OAuth обменни потоци (обмен, анкета, анкета-обратно извикване) вече нормализират `име = имейл`, когато името липсва, така че всеки OAuth акаунт показва имейла си като етикет за показване в таблото за управление на доставчиците -**Имена на OAuth акаунти**: Премахнато е последователно резервно „Акаунт N“ в `db/providers.ts` — акаунти без имейл/име сега използват стабилен етикет, базиран на ID чрез `getAccountDisplayName()` вместо пореден номер, който се променя при изтриване на акаунти## [2.3.6] - 2026-03-12\n\n### Fixed\n\n-**Тестова партида на доставчик**: Фиксирана Zod схема за приемане на `providerId: null` (фронтендът изпраща null за режими без доставчик); неправилно връщаше „Невалидна заявка“ за всички пакетни тестове -**Модален тест на доставчика**: Коригирано показване на `[object Object]` чрез нормализиране на обекти за грешка на API към низове преди изобразяване в `setTestResults` и `ProviderTestResultsView` -**i18n**: Добавени са липсващи ключове `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` към `en.json` -**i18n**: Синхронизирани 1111 липсващи ключа във всичките 29 файла на неанглийски език, използвайки английски стойности като резервни варианти## [2.3.5] - 2026-03-11\n\n### Fixed\n\n-**@swc/helpers**: Добавена е постоянна корекция `postinstall` за копиране на `@swc/helpers` в `node_modules` на самостоятелното приложение — предотвратява срив на MODULE_NOT_FOUND при глобални инсталации на npm## [2.3.4] - 2026-03-10\n\n### Added\n\n- Множество интеграции на доставчици и подобрения на таблото за управление\n"}, "b100325fe0e34ff2cbf20eb3e0b78929d25babbf": {"t": 1785765424.1797357, "n": 167970, "h": "9ee747224775d250", "c": "# Changelog (Български)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n\n## [Unreleased]\n\n---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n- **Qoder API Native Integration:** Completely refactored the Qoder Executor to bypass the legacy COSY AES/RSA encryption algorithm, routing directly into the native DashScope OpenAi-compatible URL. Eliminates complex dependencies on Node `crypto` modules while improving stream fidelity.\n- **Resilience Engine Overhaul:** Integrated context overflow graceful fallbacks, proactive OAuth token detection, and empty-content emission prevention (#990).\n- **Context-Optimized Routing Strategy:** Added new intelligent routing capability to natively maximize context windows in automated combo deployments (#990).\n\n### 🐛 Bug Fixes\n\n- **Responses API Stream Corruption:** Fixed deep-cloning corruption where Anthropic/OpenAI translation boundaries stripped `response.` specific SSE prefixes from streaming boundaries (#992).\n- **Claude Cache Passthrough Alignment:** Aligned CC-Compatible cache markers consistently with upstream Client Pass-Through mode preserving prompt caching.\n- **Turbopack Memory Leak:** Pinned Next.js to strict `16.0.10` preventing memory leaks and build staleness from recent upstream Turbopack hashed module regressions (#987).\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **Models.dev Integration:** Integrated models.dev as the authoritative runtime source for model pricing, capabilities, and specifications, overriding hardcoded prices. Includes a settings UI to manage sync intervals, translation strings for all 30 languages, and robust test coverage.\n- **Provider Native Capabilities:** Added support for declaring and checking native API features (e.g. `systemInstructions_supported`) preventing failures by sanitizing invalid roles. Currently configured for Gemini Base and Antigravity OAuth providers.\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Сигурност\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Функции\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Сигурност\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Сигурност\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Сигурност\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Документация\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Документация\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Функции\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Функции\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Функции\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Сигурност\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Функции\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Функции\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Функции\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Функции\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Функции\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Функции\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Функции\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Функции\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Сигурност\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Функции\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Функции\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Функции\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Функции\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Функции\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Функции\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Документация\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Функции\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "bd281e5753a872fcae52091f909734e96710f61e": {"t": 1785765426.1044436, "n": 166228, "h": "dcb1f93b69cdc4c5", "c": "# Changelog (Български)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Сигурност\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Функции\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Сигурност\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Сигурност\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Сигурност\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Документация\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Документация\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Функции\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Функции\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Функции\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Сигурност\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Функции\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Функции\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Функции\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Функции\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Функции\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Функции\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Функции\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Функции\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Сигурност\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Функции\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Функции\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Функции\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Функции\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Функции\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Функции\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Документация\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Функции\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "19f46eb81743cf9992edc6ff7af268a1da79ffe6": {"t": 1785765428.0073848, "n": 165547, "h": "4002fa3d8f48e382", "c": "# Changelog (Български)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Сигурност\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Функции\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Сигурност\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Сигурност\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Сигурност\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Документация\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Документация\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Функции\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Функции\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Функции\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Сигурност\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Функции\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Функции\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Функции\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Функции\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Функции\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Функции\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Функции\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Функции\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Сигурност\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Функции\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Функции\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Функции\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Функции\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Функции\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Функции\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Документация\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Функции\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "bfeb1693d691d7e3e60da1fc1c81b3ccf113c42f": {"t": 1785765430.0348606, "n": 151733, "h": "8e61c3bd23fd62b3", "c": "# Changelog (Български)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n### 🛠️ Maintenance\n\n- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.\n\n## [3.4.2] - 2026-04-01\n\n### 🐛 Bug Fixes\n\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.\n\n### 🛠️ Maintenance\n\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Сигурност\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Сигурност\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Документация\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Документация\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Функции\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Функции\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Функции\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Сигурност\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Функции\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Функции\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Функции\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Функции\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Функции\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Функции\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Функции\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Функции\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Сигурност\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Функции\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Функции\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Функции\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Функции\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Функции\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Функции\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Документация\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Функции\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "e071393eb5ed2de0eff9eefa7d275cd313b3b40a": {"t": 1785765432.0659075, "n": 143813, "h": "ad17d6538a00a40c", "c": "# Changelog (Български)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)\n\n---\n\n\n## [Unreleased]\n\n---\n\n## [3.3.9] - 2026-03-31\n\n### 🐛 Bug Fixes\n\n- **Custom Provider Rotation:** Integrated `getRotatingApiKey` internally inside DefaultExecutor, ensuring `extraApiKeys` rotation triggers correctly for custom and compatible upstream providers (#815)\n\n---\n\n## [3.3.8] - 2026-03-30\n\n### Функции\n\n- **Models API Filtering:** Endpoint `/v1/models` now dynamically filters its list based on the permissions tied to the `Authorization: Bearer ` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Сигурност\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Сигурност\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Документация\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Документация\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Функции\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Функции\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Функции\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Сигурност\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Функции\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Функции\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Функции\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Функции\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Функции\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Функции\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Функции\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Функции\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Сигурност\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Функции\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Функции\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Функции\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Функции\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Функции\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Функции\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Документация\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Функции\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}}, "docs/i18n/de/CHANGELOG.md": {"63029ae7eb5118baa91257939233db8fb0aed60b": {"t": 1785746545.0743945, "n": 229494, "h": "2924cc22bcef6cf5", "c": "# Changelog (Deutsch)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.6.8] — 2026-04-17\n\n### ✨ New Features\n\n- **feat(providers):** Support `xhigh` reasoning tier exclusively on Claude models that expose it (#1356)\n- **feat(providers):** Add CC Compatible connection-level 1M context toggle (#1357)\n- **feat(core):** Add full support for Node.js 24 LTS (Krypton) environments with continuous integration coverage (#1340)\n- **feat(dashboard):** Display Antigravity credit balance in dashboard Limits & Quotas (#1338)\n- **feat(i18n):** Add internationalization support for combo features and dashboard components; sync translations across 31 keys (#1318)\n- **feat(providers):** Add Claude Opus 4.7 to Claude Code OAuth models natively with extended context and caching (#1347)\n- **feat(core):** Add stopSequences support and expand tool definitions to include Google Search capabilities\n- **feat(auth):** Enforce dashboard session authentication on all management API routes, preventing unauthenticated access to configuration endpoints\n- **feat(runtime):** Add hot-reloadable guardrails and model diagnostics for real-time rule evaluation without restarts\n- **feat(core):** Add payload rules, tag-based routing, and scheduled budget systems for fine-grained request governance\n- **feat(providers):** Expose Antigravity preview model aliases and Gemini CLI onboarding flow for first-time setup\n- **feat(antigravity):** Add client model aliases and thoughtSignature bypass modes for Antigravity OAuth connections\n- **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations\n- **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages\n\n### Sicherheit\n\n- **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns\n- **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353)\n- **fix(providers):** Resolve Codex token refresh race condition via mutex `getAccessToken` preventing `refresh_token_reused` Auth0 revocations\n\n### 🔧 Maintenance & Architecture\n\n- **refactor(core):** Split CLI runner and decouple migration engine for extensibility (#1358)\n- **refactor(audit):** Rewire audit dashboard from dead in-memory `configAudit` store to live SQLite `audit_log` table — 331+ hidden compliance entries now visible in `/dashboard/audit`\n- **build(deps):** Bump `softprops/action-gh-release` from v2 to v3\n- **ci:** Bump GitHub Actions CI node-version to Node.js 24 natively\n- **fix(types):** Resolve TypeScript compilation errors in `claudeCodeCompatible.ts` (type predicates, `cache_control` index access) and `proxyFetch.ts` (`signal` nullability)\n\n### 🐛 Bug Fixes\n\n- **fix(context):** Scale reserved context tokens dynamically using a 15% sliding window for smaller models\n- **test(core):** Replace unit test with integration test for proactive context compression to align with isolated runner rules (#1378)\n- **fix(services):** Pass origin provider to refreshWithRetry to avoid tripping the generic \"unknown\" circuit breaker (fixes Codex accounts erroneously disabling)\n- **fix(db):** Prevent native module ABI load crashes from assuming database corruption and skipping databases\n- **fix(db):** Increase mass-migration threshold from 5 to 50 pending migrations to protect legacy users upgrading node\n- **fix(db):** Prevent migration runner safety aborts from triggering on fresh `DATA_DIR` installations by detecting new databases (#1328)\n- **fix(mcp):** Checkpoint and close MCP audit SQLite database safely on process signals and shutdown (#1348)\n- **fix(mcp):** Fully decouple MCP audit SQLite connection caching via globalThis to fix unhandled teardown in standalone Next.js chunks (#1349)\n- **fix(cli):** Avoid creating app router directory during postinstall initialization on non-built source trees (#1351)\n- **fix(codex):** Correctly translate `system` role to `developer` in input array to unlock GPT-5 automatic prompt caching (#1346)\n- **fix(core):** Pass client headers to executor in chatCore (#1335)\n- **fix(providers):** Separate test batch calls and ignore unknown connections\n- **fix(providers):** Add grok-web SSO cookie validation handler (#1334)\n- **fix(db):** Preserve key_value settings (dashboard passwords, saved aliases) across DB heuristic recreation cycles (#1333)\n- **fix(routing):** Allow combo fallback to cascade context overflow 400 errors instead of immediate aborts (#1331)\n- **fix(core):** Resolve thinking leaks, consecutive roles, and missing thoughtSignatures for Antigravity translator (#1316)\n- **fix(translator):** Only apply thoughtSignature to the first `functionCall` part in Gemini parallel tool calls, preventing duplicate signatures\n- **fix(providers):** Default to batch testing execution blocks for web, search, and audio modalities to prevent connection timeouts\n- **fix(cli):** Resolve Node 22 TS entrypoint incompatibility by using esbuild compilation (#1315)\n- **fix(chat):** Preserve max_output_tokens for Responses API targets in chatCore sanitization (#1313)\n- **fix(api):** API Manager usage stats showing 0 for all registered keys (#1310)\n- **fix(api):** Support image-only models in catalog and allow authless search providers to bypass validation requirements\n- **fix(routes):** Require prompts for media generation requests (`/images`, `/videos`, `/music`), returning 400 on missing payloads\n- **fix(dashboard):** Auto-scroll ActivityHeatmap to show current date (#1309)\n- **fix(dashboard):** Restore horizontal layout with `w-max` wrapper in heatmap components\n- **fix(i18n):** Update `nodeIncompatibleHint` to recommend Node 24 LTS across all 31 languages\n- **fix(i18n):** Add Chinese i18n support to remaining dashboard components (`Loading.tsx`, `DataTable`, etc.)\n- **fix(requestLogger):** Add missing `cacheSource` and `tps` columns to i18n log detail views\n\n## [3.6.6] — 2026-04-15\n\n### ✨ New Features\n\n- **feat(storage):** Add database backup cleanup controls, UI management, and customizable retention period env vars (#1304)\n- **feat(providers):** Add Freepik Pikaso image generation provider with support for cookie/subscription-based auth modes (#1277)\n- **feat(providers): Add Perplexity Web (Session) Provider** — Routes through Perplexity's internal SSE API using a session cookie, giving native proxy access without separate API costs to GPT-5.4, Claude Opus, Gemini 3.1 Pro, and Nemotron via preferences mapping (#1289)\n- **feat(api): Sync Tokens & V1 WebSocket Bridge** — Dedicated sync token storage, issuance, revocation, and bundle download routes backed by stable config bundle versioning with ETag support. Exposes `/v1/ws` WebSocket upgrade route and a custom Next.js server bridge (`scripts/v1-ws-bridge.mjs`) so OpenAI-compatible WebSocket traffic can be proxied through the gateway. Compliance auditing expanded with structured metadata, pagination, request context, auth/provider credential events, and SSRF-blocked validation logging. New migrations: `024_create_sync_tokens.sql`. New modules: `syncTokens.ts`, `src/lib/sync/bundle.ts`, `src/lib/sync/tokens.ts`, `src/lib/ws/handshake.ts`, `src/lib/apiBridgeServer.ts`, `src/lib/compliance/providerAudit.ts`.\n- **feat(models): GLM Thinking Preset & Hybrid Token Counting** — GLM Thinking (`glmt`) registered as a first-class provider preset with shared GLM model metadata, pricing, per-connection usage sync, dashboard support, and `maxTokens: 65536 / thinkingBudgetTokens: 24576` request defaults with 900s extended timeout. Provider-side `/messages/count_tokens` endpoint used when a Claude-compatible upstream supports it; gracefully falls back to estimation on missing models, missing credentials, or upstream failures. Startup seeding of default model aliases (`src/lib/modelAliasSeed.ts`) normalizes common cross-proxy model dialects so canonical slash-based model IDs are not misrouted. New file `open-sse/config/glmProvider.ts`.\n- **feat(core): Hardened Outbound Provider Calls & Cooldown Retries** — Guarded outbound fetch helpers (`src/shared/network/safeOutboundFetch.ts`, `src/shared/network/outboundUrlGuard.ts`) blocking private/local URLs with configurable retry, timeout normalisation, and route-level status propagation for provider validation and model discovery. Cooldown-aware chat retries (`src/sse/services/cooldownAwareRetry.ts`) with configurable `requestRetry` and `maxRetryIntervalSec` settings and model-scoped cooldown responses. Improved rate-limit learning from headers and error bodies so short upstream lockouts can recover automatically. Runtime environment validation (`src/lib/env/runtimeEnv.ts`) checks env at startup. Pollinations now requires an API key. Antigravity and Codex header handling aligned via `open-sse/config/antigravityUpstream.ts` and `open-sse/config/codexClient.ts`. Gemini tool names restored in translated responses; synthetic Claude text block injected when upstream SSE completes empty.\n- **feat(logs):** Add TPS (Tokens Per Second) metric to log details modal metadata grid (#1182)\n- **feat(memory+skills):** Full-featured Memory & Skills systems with FTS5 SQLite search, dynamic UI pagination, backend observability, and extensive test coverage (#1228)\n- **feat(bailian-quota):** Add Alibaba Coding Plan quota monitoring, multi-window quota extraction, and UI credential validation (#1235)\n- **feat(storage): Call Log Storage Refactor** — Extracted heavy request/response JSON payloads from the core SQLite database (`storage.sqlite`) into filesystem artifacts stored within `DATA_DIR/call_logs`. This massively reduces WAL bloat and eliminates `SQLITE_FULL` crashes on high-traffic nodes (#1307).\n- **feat(providers): Add Grok Web (Subscription) Provider** — Routes through the xAI web interface for subscription users via cookie session mapping (#1295).\n- **feat(api): Advanced Media Support** — Extends OpenAI generic proxy layer to natively support `image`, `embeddings`, `audio-transcriptions`, and `audio-speech` workflows (#1297).\n- **feat(cli-tools): Qwen Code CLI Integration** — Full integration for Qwen Code local execution mapping, model resolution, and dynamic API key fetching (#1266, #1263).\n- **feat(oauth):** Supports `cursor-agent` CLI as a native Cursor credential source alongside the standard configuration (#1258).\n- **feat(models):** Custom and imported models now merge correctly into filter lists for all available global providers (#1191).\n\n### 🐛 Bug Fixes\n\n- **fix(providers):** match correct endpoint api.xiaomimimo.com for Xiaomi MiMo (#1303)\n- **fix(core):** strip provider alias routing prefix from payload for custom endpoints to fix Azure OpenAI 400 errors (#1261)\n- **fix(core):** ProxyFetch Undici dispatcher automatically bypasses LAN/local addresses, preventing fetch failures on internal OpenRouter requests (#1254)\n- **fix(core):** Gemini thought stream signature detection upgraded to use native part.thought boolean, preventing reasoning text leaks (#1298)\n- **deps:** bump hono from 4.12.12 to 4.12.14 to resolve CVE SSR HTML injection vulnerability (#1306, #59)\n- **deps:** update dompurify to 3.4.0 in frontend overrides mitigating XSS HTML Injection (CVE-XYZ / Dependabot #60)\n- **test:** Disable SQLite automatic backups during continuous integration (CI) tests to resolve E2E timeout issues limiting runner scaling (#24481475058)\n- **feat(core): Proactive Context Compression** — `chatCore` now proactively compresses oversized message contexts before hitting upstream providers to dramatically reduce `context_length_exceeded` errors. Employs binary-search message pruning with structural integrity guarantees tracking explicit `tool_use` boundaries ensuring truncated tool inputs drop paired outputs appropriately (#1292, #1293)\n\n- **fix(cli):** Resolve codex routing config parsing by strictly quoting section keys array, enforcing responses wire_api with fallback, and standardizing select-model button positioning mirroring Claude UI\n- **fix(providers):** Correct Lobehub provider icons rendering by removing unsupported local references ensuring local SVG/PNG fallback mechanism invokes natively\n- **fix(db):** Implement Database migration tracking safety abort safeguards (pre-migration backups via `VACUUM INTO` and mass renumbering warnings) to protect existing database structures on startup upgrades (#1281)\n- **fix(dashboard):** Cleaned up target codex `config.toml` structure preventing recursive section rendering by enforcing quotes on section dot paths and mapping correct UI `OMNIROUTE_API_KEY` names.\n- **fix(mcp):** Add dedicated explicit timeout constraint overrides for search handlers (#1280)\n- **fix(crypto):** Add validation guard to encryption layer to surface clear UI errors when cryptographic environment variables are missing, replacing raw Node.js TypeErrors. Legacy env vars `OMNIROUTE_CRYPT_KEY` and `OMNIROUTE_API_KEY_BASE64` now also accepted as fallbacks (#1165)\n- **fix(providers):** Update Pollinations provider definition to require API keys and specify their new limited pollen/hour free tier (#1177)\n- **Streaming `\\n\\n` Artifact Fix (#1211):** Changed `` tag-stripping regex from `?` to `*` quantifier across `combo.ts`, `comboAgentMiddleware.ts`, and `contextHandoff.ts` to greedily strip all accumulated JSON-escaped newline sequences surrounding the tag. This prevents literal `\\n\\n` prefix artifacts from appearing in consumer streaming responses\n- **E2E Combo Test Locator:** Fixed Playwright strict-mode violation in `combo-unification.spec.ts` by replacing ambiguous `getByRole` locator with a compound filter locator for the \"All\" strategy tab\n- **fix(cc-compatible):** Trim beta flags and preserve cache passthrough for third-party HTTP proxy compatibility (#1230)\n- **fix(providers):** Update Xiaomi MiMo endpoints to the live token-plan, migrating away from dead API URLs (#1238)\n- **fix:** Forward client `x-initiator` header to GitHub Copilot upstream to accurately distinguish agent vs user turns (#1227)\n- **fix:** Resolve backlog bugs including streaming edge cases, unhandled rejections, and quota parse failures (#1206, #1220, #1231, #1175, #1187, #1218, #1202)\n- **fix(tests):** Resolve memory migration and skills route pagination bugs arising from PR overlaps\n- **fix(i18n):** Add missing Chinese i18n support to dashboard components (`DataTable`, `EmptyState`, etc), update `en.json/zh-CN.json` routing keys, and natively resolve JSX defaults via `next-intl` (#1274)\n\n### 🔧 Internal Improvements\n\n- **Compliance Audit Expansion:** `src/lib/compliance/index.ts` expanded with structured metadata, pagination support, request context enrichment, and new `providerAudit.ts` module logging auth and provider credential events, SSRF-blocked validation attempts, and provider CRUD operations\n- **Config Sync Bundle:** `src/lib/sync/bundle.ts` exports `buildConfigBundle()` generating a versioned JSON snapshot of settings, provider connections, nodes, model aliases, combos, and API keys (passwords redacted) with ETag support for bandwidth-efficient polling\n- **Codex Client Constants:** Centralized `CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT_PLATFORM`, and pattern-validated env overrides (`CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT`) in `open-sse/config/codexClient.ts`\n- **Antigravity Upstream Constants:** `open-sse/config/antigravityUpstream.ts` consolidates all Antigravity base URLs and model/fetchAvailableModels discovery path builders\n- **Model Alias Seed:** `src/lib/modelAliasSeed.ts` seeds 30+ cross-proxy model dialect aliases (e.g. `openai/gpt-5` → `gpt-5`, `anthropic/claude-opus-4-6` → `cc/claude-opus-4-6`) at startup via idempotent `upsert`\n- **Test Coverage:** 15+ new unit test suites covering sync routes, WebSocket bridge, compliance index, GLM provider config, cooldown-aware retry, safe outbound fetch, stream utilities, Codex executor, provider validation branches, model cross-proxy compatibility, and model alias seeding\n- **TypeScript Migration:** Finalized migration of remaining JS tests (`proxy-load` and `testFromFile`) to TypeScript ES modules, ensuring a fully synchronized TS stack.\n- **Reliability & Resilience:** Added exponential backoff to `models.dev` auto-sync to combat transient network failures, raised interval floor to 1 hour, and added LKGP debug logging for enhanced observability during routing. (#1286)\n\n---\n\n## [3.6.5] — 2026-04-13\n\n### ✨ New Features\n\n- **Antigravity AI Credits Fallback:** Automatically retries with `GOOGLE_ONE_AI` credit injection when free-tier quota is exhausted. Per-account credit balance (5-hour TTL) is cached from SSE `remainingCredits` and exposed as a numeric badge in the Provider Usage dashboard (#1190 — thanks @sFaxsy)\n- **Claude Code Native Parity:** Full header/body signing parity with the Claude Code 2.1.87 OAuth client — CCH xxHash64 body signing with singleton WASM initialization promise (fixing race conditions), dynamic per-request fingerprint, bidirectional TitleCase ↔ lowercase tool name remapping (14 tools), API constraint enforcement (`temperature=1` for thinking, max 4 `cache_control` blocks, auto-inject ephemeral on last user message), and optional ZWJ obfuscation. Wired into `BaseExecutor` for automatic CCH signing on all `anthropic-compatible-cc-*` providers and into `chatCore` for synchronous parity pipeline steps (#1188 — thanks @RaviTharuma)\n- **Per-Connection Codex Defaults:** Codex Fast Service Tier and Reasoning Effort settings are now per-connection instead of a single global toggle. Existing connections are migrated automatically on startup via an idempotent backfill migration (#1176 — thanks @rdself)\n- **Cursor Usage Dashboard:** New `getCursorUsage()` fetches quotas from Cursor's `/api/usage`, `/api/auth/me`, and `/api/subscription` endpoints. Displays standard requests, on-demand usage, and per-plan limits (Free/Pro/Business/Team). Client version bumped to `3.1.0` and `x-cursor-user-agent` header added for parity\n- **Database Health Check System:** Automated periodic SQLite integrity monitoring via `runDbHealthCheck()` — detects orphan quota/domain rows, broken combo references, stale snapshots, and invalid JSON state. Runs every 6 hours (configurable via `OMNIROUTE_DB_HEALTHCHECK_INTERVAL_MS`), with auto-repair and pre-repair backup. Exposed as **MCP tool #18** (`omniroute_db_health_check`) with Zod schemas and `autoRepair` option. Dashboard panel in Health page with status card, issue count, repaired count, and one-click repair button\n- **OpenAI Responses API Store Opt-In:** Per-connection `openaiStoreEnabled` flag controls whether the `store` field is preserved or forced to `false` on Codex Responses API requests. When enabled, `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields are round-tripped through the Chat Completions → Responses translation, enabling multi-turn context caching on supported providers\n- **Email Privacy Toggle (Combos Page):** Global email visibility toggle (`EmailPrivacyToggle`) added to the Combos page header with responsive layout, tooltip guidance, and per-connection label masking via `pickDisplayValue()`. All combo builder options, provider connection lists, and quota screens now respect the global privacy state from `emailPrivacyStore`\n- **skills.sh Integration:** Added `skills.sh` as an external skill provider. Users can now search, browse, and install agent skills directly from a new \"skills.sh\" tab in the Skills dashboard. Includes backend API resolvers, frontend implementation with search/install states, and a dedicated unit test suite (#1223 — thanks @RaviTharuma)\n- **Stabilization Settings:** Added persistence support for `lkgpEnabled` and `backgroundDegradation` settings, integrated into `instrumentation-node.ts` for improved lifecycle awareness (#1212)\n- **xxhash-wasm dependency:** Added `xxhash-wasm@^1.1.0` for CCH signing (xxHash64 with seed `0x6E52736AC806831E`)\n\n### 🐛 Bug Fixes\n\n- **Codex `stream: false` via Combo (ALL_ACCOUNTS_INACTIVE):** Fixed a critical bug where Codex combos returned `ALL_ACCOUNTS_INACTIVE` or empty content when the client sent `stream: false`. Root cause was triple: (1) `CodexExecutor.transformRequest()` mutated `body.stream` in-place to `true`, contaminating the combo's quality check which skipped validation thinking it was streaming; (2) the non-stream SSE parser used the wrong format (Chat Completions instead of Responses API) for Codex SSE output; (3) combo quality validation read the mutated `body.stream` instead of the client's original intent. Fixed by: cloning the body via `structuredClone()` in CodexExecutor, detecting Codex/Responses SSE format in the non-stream fallback path (with auto-translation back to Chat Completions), and capturing `clientRequestedStream` before the combo loop\n- **Gemini CLI Tool Schema Rejection:** Fixed 400 Bad Request errors from the Google API by strictly filtering non-standard vendor extensions (starting with `x-`) and `deprecated` fields from tool parameter schemas (#1206)\n- **SOCKS5 Proxy Interop (Node.js 22):** Resolved `invalid onRequestStart method` crashes caused by `undici` version mismatches between dispatchers and the built-in fetch. Hardened `proxyFetch.ts` to strictly use the library's fetch implementation for custom dispatchers (#1219)\n- **Search Cache Coalescing with TTL=0:** Fixed a bug where providers configured with `cacheTTLMs: 0` (caching explicitly disabled) still had concurrent requests coalesced and returned `{ cached: true }`. Now each call gets its own independent upstream fetch (#1178 — thanks @sjhddh)\n- **Antigravity Credit Cache Alignment (PR #1190):** Reconciled `accountId` derivation between `AntigravityExecutor.collectStreamToResponse` and `getAntigravityUsage` to use consistent cache keys (`email || sub || \"unknown\"`). Previously, SSE-parsed credit balances could be written under a different key than the one read by the usage dashboard, causing stale/missing credit badges\n- **Non-streaming reasoning_content Duplication:** Fixed clients rendering duplicated reasoning panels when both `reasoning_content` and visible `content` were present in non-streaming responses. `responseSanitizer` now strips `reasoning_content` from messages that already have visible text content, preserving it only for reasoning-only messages\n- **Streaming Regression Fix:** Hardened the `sanitize` TransformStream in the combo engine to strip both literal and JSON-escaped newline sequences, eliminating leading `\\n\\n` prefixes in assistant responses (#1211)\n- **Gemini Empty Choice Fix:** Ensured initial assistant deltas always include an empty `content: \"\"` string to satisfy strict OpenAI client requirements and prevent empty choice responses in tools (#1209)\n- **Gemini Tools Sanitizer Deduplication:** Extracted shared tool conversion logic into `buildGeminiTools()` helper (`geminiToolsSanitizer.ts`), eliminating duplicate implementations between `openai-to-gemini.ts` and `claude-to-gemini.ts`. The new helper correctly handles `web_search` / `web_search_preview` tool types by emitting `googleSearch` tools with priority over function declarations\n- **Qwen/Qoder Thinking+Tool_Choice Conflict:** Added `sanitizeQwenThinkingToolChoice()` to both `DefaultExecutor` (for Qwen provider) and `QoderExecutor` to prevent provider-side 400 errors when clients send `tool_choice` alongside thinking/reasoning parameters that are mutually exclusive upstream\n- **API Key Deletion Orphan Cleanup:** Deleting an API key now also removes associated `domain_budgets` and `domain_cost_history` rows, preventing orphan data accumulation\n- **CC-compatible test assertion:** Fixed pre-existing test that expected no `cache_control` on system blocks — the billing header system block now carries `cache_control: { type: \"ephemeral\" }` per PR #1188 design\n- **Codex Combo Smoke Test False Positives:** Fixed combo tests incorrectly reporting `ERROR` for valid Codex streaming responses when `response.output` is empty but text deltas were emitted. The summary now falls back to accumulated delta text (#1176 — thanks @rdself)\n- **Electron Builder Version Mismatch:** Fixed Electron desktop startup failures on Windows packaged builds caused by native modules (`better-sqlite3`) being under `app.asar.unpacked` while helpers were in `app/node_modules`. `resolveServerNodePath()` now merges both locations with deduplication and existence checks (#1172 — thanks @backryun)\n\n### 🔧 Internal Improvements\n\n- **SSE Parser: Responses API Non-Stream Conversion:** Added full `parseSSEToResponsesOutput()` implementation in `sseParser.ts` (255+ lines) — reconstructs complete Responses API objects from SSE event streams, handling `response.output_text.delta/done`, `response.reasoning_summary_text.delta/done`, `response.function_call_arguments.delta/done`, and terminal events. Used by the new chatCore non-stream fallback path for Codex\n- **Cursor Executor Version Sync:** Updated Cursor client User-Agent to `3.1.0` and centralized version constants (`CURSOR_CLIENT_VERSION`, `CURSOR_USER_AGENT`) for consistent fingerprinting across executor, usage fetcher, and OAuth flows\n- **Responses API Translator Parity:** `convertResponsesApiFormat()` now accepts credentials and passes them through to the translator, enabling store-aware field propagation. Round-trip preservation of `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields\n- **Provider Schema Validation:** Added `openaiStoreEnabled` boolean validation to `providerSpecificData` Zod schema\n- **Combo Error Response Normalization:** Empty combo targets now return 404 (`comboModelNotFoundResponse`) instead of generic 503, improving client-side error differentiation\n- **Dependency Updates:** Bumps `typescript-eslint` to `8.58.2` (dev), `axios` to `1.15.0` (prod), and `next` to `16.2.2` (prod) (#1224, #1225)\n\n### ⚠️ Breaking Changes\n\n- **`DELETE /api/settings/codex-service-tier` removed:** This endpoint no longer exists. Codex Service Tier configuration has moved to per-connection `providerSpecificData.requestDefaults`. Existing connections are migrated automatically on first startup after upgrade. Any external scripts or integrations that call this endpoint should be updated — use `PUT /api/providers/:id` with `providerSpecificData.requestDefaults.serviceTier` instead (#1176).\n- **CCH signing on CC-compatible providers:** All requests to `anthropic-compatible-cc-*` providers now include an xxHash64 integrity token (`cch=...`) in the billing header. Providers that do not validate CCH will ignore it (no behavioral change), but any custom middleware inspecting the billing header should expect a 5-character hex token instead of the `00000` placeholder\n\n---\n\n## [3.6.4] — 2026-04-12\n\n### ✨ New Features\n\n- **Combo Builder v2 (Wizard UI):** Completely redesigned the combo creation/editing interface as a multi-stage wizard with stages: Basics → Steps → Strategy → Review. The builder fetches provider, model, and connection metadata via a new `GET /api/combos/builder/options` endpoint, enabling precise provider/model/account selection with duplicate detection and automatic next-connection suggestion. Heavy UI components (`ModelSelectModal`, `ProxyConfigModal`, `ModelRoutingSection`) are now lazily loaded via `next/dynamic` for faster initial page render\n- **Combo Step Architecture (Schema v2):** Introduced a structured step model (`ComboModelStep`, `ComboRefStep`) replacing the legacy flat string/object combo entries. Steps carry explicit `id`, `kind`, `providerId`, `connectionId`, `weight`, and `label` fields, enabling pinned-account routing, cross-combo references, and per-step metrics. All combo CRUD operations normalize entries through the new `src/lib/combos/steps.ts` module. Zod schemas updated with `comboModelStepInputSchema` and `comboRefStepInputSchema` unions\n- **Composite Tiers System:** Added tiered model routing via `config.compositeTiers` — each tier maps a named stage to a specific combo step with optional fallback chains. Includes comprehensive validation (`src/lib/combos/compositeTiers.ts`) ensuring step existence, preventing circular fallback, and validating default tier references. Zod schema enforcement blocks composite tiers on global defaults (concrete combos only)\n- **Model Capabilities Registry:** Created `src/lib/modelCapabilities.ts` providing `getResolvedModelCapabilities()` — a unified resolver that merges static specs, provider registry data, and live-synced capabilities into a single `ResolvedModelCapabilities` object covering tool calling, reasoning, vision, context window, thinking budget, modalities, and model lifecycle metadata\n- **Observability Module:** Extracted health and telemetry payload construction into `src/lib/monitoring/observability.ts` with `buildHealthPayload()`, `buildTelemetryPayload()`, and `buildSessionsSummary()` builders. The health endpoint now returns session activity, quota monitor status, and per-provider breakdowns alongside existing system metrics\n- **Session & Quota Monitor Dashboard:** Added live Session Activity and Quota Monitors panels to the Health dashboard, showing active session counts, sticky-bound sessions, per-API-key breakdowns, and top session details alongside quota monitor alerting/exhausted/error status with per-provider drill-down\n- **Combo Health Per-Target Analytics:** The combo-health API now resolves per-target metrics using the new `resolveNestedComboTargets()` function, providing step-level success rates, latency, and historical usage breakdowns per execution key — enabling per-account, per-connection health visibility\n- **Auto-Combo → Combos Unification:** Merged the separate `/dashboard/auto-combo` page into the main `/dashboard/combos` page. Auto/LKGP combos are now managed alongside all other combos with a new strategy filter tabs system (All / Intelligent / Deterministic). The old auto-combo route redirects to `/dashboard/combos?filter=intelligent`. Removed the `auto-combo` sidebar entry, consolidating navigation into the single `Combos` item\n- **Intelligent Routing Panel (`IntelligentComboPanel`):** New inline panel (371 lines) within the combos page that shows real-time provider scores, 6-factor scoring breakdown (quota, health, cost, latency, task fitness, stability), mode pack selector, incident mode status, and excluded providers for `auto`/`lkgp` combos — replacing the former standalone auto-combo dashboard\n- **Builder Intelligent Step (`BuilderIntelligentStep`):** New conditional wizard step (280 lines) that appears in the Builder v2 flow only when `strategy=auto` or `strategy=lkgp` is selected. Exposes candidate pool selection, mode pack presets, router sub-strategy selector, exploration rate slider, budget cap, and collapsible advanced scoring weights configuration\n- **Intelligent Routing Module (`intelligentRouting.ts`):** Extracted strategy categorization and filtering logic into a dedicated shared module (210 lines) with `getStrategyCategory()`, `isIntelligentStrategy()`, `filterCombosByStrategyCategory()`, `normalizeIntelligentRoutingFilter()`, and `normalizeIntelligentRoutingConfig()` utility functions\n- **LKGP Standalone Strategy:** Implemented `lkgp` (Last Known Good Provider) as a fully functional standalone combo strategy. Previously, `lkgp` as a combo strategy silently fell through to `priority` ordering — the LKGP lookup only ran inside the `auto` engine. Now `strategy: \"lkgp\"` correctly queries the LKGP state, moves the last successful provider to the top of the target list, and saves the LKGP state after each successful request. Falls back to priority ordering when no LKGP state exists\n- **Unified Routing Rules & Model Aliases:** Consolidated the routing rules and model alias management controls into the Settings page, reducing fragmentation across the dashboard\n\n### ⚡ Performance\n\n- **Middleware Lazy Loading:** Refactored `src/proxy.ts` to lazy-import `apiAuth`, `db/settings`, and `modelSyncScheduler` modules, reducing middleware cold-start overhead. Added inline `isPublicApiRoute()` to avoid loading the full auth module for public routes\n- **E2E Auth Bypass:** Added `NEXT_PUBLIC_OMNIROUTE_E2E_MODE` environment flag to bypass authentication gates for dashboard and management API routes during Playwright E2E test runs\n\n### 🐛 Bug Fixes\n\n- **P2C Credential Selection:** Implemented Power-of-Two-Choices (P2C) connection scoring in `src/sse/services/auth.ts` with quota headroom awareness, error/recency penalties, and forced/excluded connection support. The new `getProviderCredentialsWithQuotaPreflight()` function integrates quota preflight checks directly into credential selection, eliminating the separate Codex-only preflight path\n- **Fixed-Account Combo Steps:** Combo steps with explicit `connectionId` now correctly bypass provider-level model cooldowns and circuit breakers, preventing a single account failure from blocking pinned-connection routing for the same model\n- **Combo Metrics Per-Target Tracking:** Extended `comboMetrics.ts` to track `byTarget` metrics keyed by execution path, recording per-step `provider`, `providerId`, `connectionId`, and `label` alongside existing per-model aggregates\n- **Call Logs Schema Expansion:** Added `requested_model`, `request_type`, `tokens_cache_read`, `tokens_cache_creation`, `tokens_reasoning`, `combo_step_id`, and `combo_execution_key` columns to `call_logs` with auto-migration. Added composite index `idx_cl_combo_target` for efficient per-target historical queries\n- **Quota Monitor Enrichment:** Expanded `quotaMonitor.ts` with full lifecycle state tracking (`status`, `startedAt`, `lastPolledAt`, `consecutiveFailures`, `totalPolls`, `totalAlerts`), ISO-formatted snapshots via `getQuotaMonitorSnapshots()`, and sorted summary via `getQuotaMonitorSummary()`\n- **Codex Quota Fetcher Hardening:** Improved `codexQuotaFetcher.ts` with safer connection registration and quota fetch error handling\n- **LKGP Save Refactored to Async/Await:** Replaced fire-and-forget `.then()` chain for LKGP persistence after successful combo routing with proper `async/await` + `try/catch`, preventing unhandled promise rejections and ensuring LKGP state is reliably saved before the response is returned\n- **Duplicate `auto` in Combo Strategy Schema:** Removed duplicate `\"auto\"` entry from `comboStrategySchema` (was listed on both line 104 and 108). Harmless to Zod runtime but cleaned up to avoid confusion. Schema now has exactly 13 unique strategy values\n- **Legacy Combo Refs Normalization:** Fixed combo step normalization to preserve legacy string combo references during CRUD operations, preventing data loss when editing combos created before the v2 step architecture\n\n### Sicherheit\n\n- **Auth Bypass on Backup Routes (Critical):** Added `isAuthenticated` guards to `/api/db-backups/exportAll` (full database export) and `/api/db-backups` (list, create, and restore backups) — both were previously accessible without authentication\n- **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency\n- **API Key Secret Hardening:** Removed the hardcoded `\"omniroute-default-insecure-api-key-secret\"` fallback from `apiKey.ts` — the function now fails fast if `API_KEY_SECRET` is unset, relying on the startup validator to auto-generate it\n- **NPM Tarball Leak Fix:** Added `app/.env*` to `.npmignore` to prevent the working `.env` file from being shipped inside the npm tarball distribution\n- **Electron Builder CVE Fix:** Bumped `electron-builder` to 26.8.1 to resolve `tar` CVEs in the desktop build pipeline\n\n### 🔧 Maintenance & Infrastructure\n\n- **DB Migration 021:** Added `combo_call_log_targets` migration for `combo_step_id` and `combo_execution_key` columns in call_logs\n- **Combo CRUD Normalization:** `db/combos.ts` now normalizes all stored combo entries through the step normalization pipeline on read, ensuring consistent step IDs and kind annotations regardless of when the combo was created\n- **Playwright Config:** Updated Playwright configuration and `run-next-playwright.mjs` script for improved E2E test orchestration\n- **Build Script:** Updated `build-next-isolated.mjs` with additional reliability improvements\n- **Auto-Combo UI Cleanup:** Deleted `AutoComboModal.tsx` (161 lines), replaced `auto-combo/page.tsx` (478→5 lines) with a server-side redirect to `/dashboard/combos?filter=intelligent`\n- **Sidebar Consolidation:** Removed `\"auto-combo\"` from `HIDEABLE_SIDEBAR_ITEM_IDS` and `PRIMARY_SIDEBAR_ITEMS` — `normalizeHiddenSidebarItems()` silently discards any stale `\"auto-combo\"` entries in user settings\n- **Schema Cleanup:** Removed obsolete `createAutoComboSchema` from `schemas.ts`. Exported `comboStrategySchema` for direct use in test and filter modules\n- **A2A Agent Card Update:** Renamed skill ID from `auto-combo` to `intelligent-routing` with updated description referencing the unified combos dashboard\n- **Builder Draft Refactor:** Extended `builderDraft.ts` with dynamic stage list generation via `getComboBuilderStages()` and `isIntelligentBuilderStrategy()`. Stage navigation (`getNextComboBuilderStage`, `getPreviousComboBuilderStage`, `canAccessComboBuilderStage`) now accepts options to conditionally include/skip the `intelligent` wizard step\n- **i18n Consolidation:** Removed the standalone `\"autoCombo\"` i18n block (22 keys) from all 30 language files. Migrated keys into the `\"combos\"` block with new additions for filter tabs, intelligent panel, and builder step labels\n\n### 🧪 Tests\n\n- **16 New Test Suites:** Added comprehensive test coverage including:\n - `combo-builder-draft.test.mjs` (186 lines) — Builder draft step construction and validation\n - `combo-builder-options-route.test.mjs` (228 lines) — Builder options API endpoint\n - `combo-health-route.test.mjs` (266 lines) — Combo health analytics with per-target metrics\n - `combo-routes-composite-tiers.test.mjs` (157 lines) — Composite tiers API integration\n - `composite-tiers-validation.test.mjs` (131 lines) — Composite tier validation rules\n - `db-combos-crud.test.mjs` — Combo CRUD with step normalization\n - `db-core-init.test.mjs` (129 lines) — DB initialization and column migrations\n - `model-capabilities-registry.test.mjs` (105 lines) — Model capabilities resolution\n - `observability-payloads.test.mjs` (165 lines) — Health/telemetry payload construction\n - `openapi-spec-route.test.mjs` — OpenAPI spec generation\n - `proxy-e2e-mode.test.mjs` (74 lines) — E2E mode auth bypass\n - `quota-monitor.test.mjs` — Quota monitor lifecycle state\n - `run-next-playwright.test.mjs` (119 lines) — Playwright runner script\n - `sse-auth.test.mjs` (154 lines) — P2C credential selection and quota preflight\n - `telemetry-summary-route.test.mjs` (35 lines) — Telemetry summary endpoint\n - Plus updates to 12 existing test files for compatibility with new step architecture\n- **Auto-Combo Unification Tests:**\n - `autocombo-unification.test.mjs` (156 lines) — Strategy categorization, schema deduplication, sidebar cleanup, and routing strategies metadata validation\n - `combo-unification.spec.ts` (189 lines) — Playwright E2E tests for filter tabs, intelligent panel rendering, redirect from old route, sidebar entry removal, and Builder v2 intelligent step flow\n - 3 new LKGP standalone tests in `combo-routing-engine.test.mjs` — Validates LKGP provider prioritization, fallback to priority when no state exists, and LKGP state persistence after successful requests\n - Updated `combo-builder-draft.test.mjs` with intelligent stage navigation tests\n - Updated `sidebar-visibility.test.mjs` to reflect `auto-combo` removal\n\n---\n\n## [3.6.3] — 2026-04-11\n\n### ✨ New Features\n\n- **OpenAI-Compatible Loose Validation:** Empty API keys can now be naturally submitted and saved for any `openai-compatible-*` providers (e.g. Pollinations, localized routes) directly in the UI instead of blocking save actions (#1152)\n- **Cloudflare Configuration:** Updated the provider schema and UI integration for Cloudflare AI to officially expose and support the backend `accountId` field securely without overrides (#1150)\n\n### 🐛 Bug Fixes\n\n- **Vertex JSON Validation Crash:** Prevented `invalid character in header` crashes inside the `/validate` endpoint by creating a native authentication parser that correctly handles Google Identity Service Account JSON flows prior to pinging endpoints (#1153)\n- **Extraneous Payload Rejection:** Globally prevented upstream `400 Bad Request` execution crashes by stripping the non-standard `prompt_cache_retention` attribute forcibly attached by Cursor/Cline IDE engines when targeting strict OpenAI/Anthropic routes (#1154)\n- **Reasoning Content Drop:** Prevented pure reasoning packets, common in advanced fallback models like DeepSeek, from being aborted mid-stream by explicitly adjusting the `Empty Content (502)` circuit breakers to acknowledge `reasoning_content` states as valid (#1155)\n- **Desktop Windows Build Crash:** Fixed `better_sqlite3.node is not a valid Win32 application` preventing OmniRoute Desktop from launching on Windows by properly removing the ABI-mismatched sqlite cache from Next.js standalone and falling back to the cross-compiled Electron equivalent during packager build steps (#1163)\n- **Login Visual Security:** Removed the raw fallback hash dump that artificially rendered underneath the login modal in Docker instances missing `OMNIROUTE_API_KEY_BASE64` flags (#1148)\n\n### 🔧 Maintenance & Dependencies\n\n- **Dependabot Updates:** Safely bumped GitHub Actions `docker/build-push-action` to v7 and `actions/download-artifact` to v8\n- **Electron Updates:** Upgraded desktop wrapper core to Electron `41.2.0` and `electron-builder` to `26.8.1`, incorporating essential V8/Chromium security patches\n- **NPM Package Groups:** Updated `production` and `development` NPM groups to securely handle minor audit warnings and keep toolchains modern\n- **CI/CD Reliability:** Fixed persistent `Snyk` token-absence failures on automated pull requests by appropriately bypassing on dependabot actions\n\n## [3.6.2] — 2026-04-11\n\n### ✨ New Features\n\n- **33 New API Key Providers:** Massive provider expansion adding DeepInfra, Vercel AI Gateway, Lambda AI, SambaNova, nScale, OVHcloud AI, Baseten, PublicAI, Moonshot AI, Meta Llama API, v0 (Vercel), Morph, Featherless AI, FriendliAI, LlamaGate, Galadriel, Weights & Biases Inference, Volcengine, AI21 Labs, Venice.ai, Codestral, Upstage, Maritalk, Xiaomi MiMo, Inference.net, NanoGPT, Predibase, Bytez, Heroku AI, Databricks, Snowflake Cortex, and GigaChat (Sber). OmniRoute now supports **100+ providers** (4 Free + 8 OAuth + 91 API Key + Custom compatible)\n- **Global Email Privacy Toggle:** Added a persistent eye-icon toggle button across all dashboard pages (Providers, Usage Limits, Playground) that reveals or hides masked email addresses. Toggle state is stored in localStorage and synced globally via Zustand store\n- **Documentation Refresh:** Updated README, ARCHITECTURE, FEATURES, AGENTS.md, and API_REFERENCE for v3.6.2 with accurate provider counts (100+), new executor list, and system API documentation\n- **Uninstall Guide:** Created comprehensive `docs/UNINSTALL.md` covering clean uninstallation for all deployment methods (npm, Docker, Electron, source)\n\n### 🐛 Bug Fixes\n\n- **PDF Attachments:** Unlocked deep string object parsing (`geminiHelper`) ensuring Gemini translation successfully passes complex PDF payloads from OpenAI-compatible streams without dropping them silently (#993)\n- **SkillsMP Engine:** Corrected object extraction path mappings inside the API router to fix UI marketplace rendering under Docker/Standalone Node isolated deployments (#988)\n\n---\n\n## [3.6.1] — 2026-04-10\n\n### ✨ New Features\n\n- **OAuth Env Repair Action:** Added a \"Repair env\" button to the OAuth Providers dashboard that detects and restores missing OAuth client IDs from `.env.example` — with timestamped backup and append-only safety. Includes full 33-language i18n support and sanitized API responses (#1116, by @yart)\n\n### 🐛 Bug Fixes\n\n- **i18n: Missing Provider Keys:** Added missing `filterModels`, `modelsActive`, `showModel`, `hideModel` keys across all 32 locale files, fixing runtime `MISSING_MESSAGE` errors in the providers UI. Also cleaned up duplicate keys in `en.json` (#1111, by @rilham97)\n- **GPT-5.4 Routing:** Added missing `targetFormat: \"openai-responses\"` to `gpt-5.4` and `gpt-5.4-mini` models in both the Codex and GitHub Copilot providers, fixing `[400]: model not accessible via /chat/completions` errors (#1114, by @ask33r)\n\n---\n\n## [3.6.0] — 2026-04-10\n\n### ✨ New Features & Analytics\n\n- **Combo Smoke Test:** Raised the default token budget to 2048 to prevent truncation of thinking models during preflight checks, and fully randomized the arithmetic probe prompt to bypass deterministic caching from upstream relays (#1105)\n\n### 🐛 Bug Fixes & Compliance\n\n- **DB Bloat / Row Limits:** Added `CALL_LOGS_TABLE_MAX_ROWS` and `PROXY_LOGS_TABLE_MAX_ROWS` (default: 100,000) to the backend DB compliance cleaner to prevent runaway SQLite growth. Limits are enforced automatically on the TTL cycle (#1104, fixes #1101)\n- **HTML Error Handling:** The router now correctly identifies unexpected HTML responses (e.g. ``) sent by upstream providers (like Azure/Copilot) instead of throwing obscure `Unexpected token '<'` JSON parse errors, bubbling up a clean 502 Bad Gateway (#1104, fixes #1066)\n- **Android/Termux SQLite Native Support:** `better-sqlite3` is now correctly built from source with cross-compilation flags in ARM64 local Termux deployments without failing on missing prebuilt binaries (#1107)\n\n---\n\n## [3.5.9] — 2026-04-09\n\n### ✨ New Features\n\n- **Persistent Combo Ordering:** Drag combo cards by handle to reorder them in the dashboard; order is persisted to SQLite via a new `sort_order` column and `POST /api/combos/reorder` endpoint. Includes DB migration `020_combo_sort_order.sql` and JSON import preservation (#1095)\n- **Sidebar Group Reorder:** Moved \"Logs\" before \"Health\" in the System section and \"Limits & Quotas\" after \"Cache\" in the Primary section for a more logical navigation flow (#1095)\n\n### 🐛 Bug Fixes\n\n- **Stream Failure Surfacing:** Upstream `response.failed` events (e.g. Codex rate-limit errors) are now properly surfaced as non-200 errors instead of being silently swallowed as empty 200 OK streams. Rate-limit failures return HTTP 429 (#1098, closes #1093)\n- **Upstream Model Preservation:** The Responses-to-OpenAI stream translator now preserves the actual upstream model (e.g. `gpt-5.4`) instead of hardcoding a `gpt-4` fallback (#1098, closes #1094)\n- **Docker EXDEV Fix:** `build-next-isolated.mjs` now falls back from `fs.rename()` to `cp/rm` when Docker buildx raises `EXDEV` (cross-device link), unblocking the Docker image publish workflow (#1097)\n- **macOS CLI Path Resolution:** `cliRuntime.ts` resolves symlink parents with `fs.realpath()` to handle macOS `/var` → `/private/var` chains, preventing false `symlink_escape` rejections (#1097)\n- **Request Log Token Layout:** Split token badges into separate Input (Total In, Cache Read, Cache Write) and Output (Total Out, Reasoning) groups for clearer readability; renamed \"Time\" label to \"Completed Time\" (#1096)\n\n---\n\n## [3.5.8] — 2026-04-09\n\n### ✨ New Features & Analytics\n\n- **Analytics Layout Redesign:** Replaced flat metrics with a responsive `CompactStatGrid`, grouping data visually across sections (#1089)\n\n### 🐛 Bug Fixes\n\n- **Build Core:** Force Turbopack cleanup via Prepbulish script to prevent Next.js 16 app/ routing conflicts on runtime.\n- **Provider Quarantine:** Introduces model/provider circuit-breakers with adaptive TTL exponential backoff for recurring upstream errors (#1090)\n- **Oauth Keep-Alive:** Safely protects authenticated active accounts against spontaneous dropping from router due to transient token refresh failures (#1085)\n\n### 🔒 Security & Maintenance\n\n- **Dependabot:** bumped axios from 1.14.0 to 1.15.0 addressing SSRF flags (#1088)\n\n---\n\n## [3.5.7] — 2026-04-09\n\n### 🐛 Bug Fixes & Security\n\n- **Turbopack Standalone Chunks:** Fixed a critical bug in `scripts/prepublish.mjs` where Turbopack chunks missing from the `.next/standalone` trace resulted in a `500 ChunkLoadError` (e.g., `_not-found` page crash) during production deployments via NPM or Docker. Standalone chunks are now explicitly copied and correctly stripped of Turbopack hashes.\n\n---\n\n## [3.5.6] — 2026-04-09\n\n### ✨ New Features\n\n- **Email Privacy Masking:** OAuth account emails are now masked in the provider dashboard (e.g. `di*****@g****.com`) to prevent accidental exposure when sharing screenshots. Full address visible on hover via `title` attribute (#1025).\n- **OpenRouter & GitHub in Embedding/Image Registries:** OpenRouter (3 embedding models, 4 image models) and GitHub Models (2 embedding models via Azure inference) are now first-class entries in the provider registries, enabling their use for `/v1/embeddings` and `/v1/images/generations` (#960).\n- **Model Visibility Toggle & Search Filter:** The provider page model list now includes a real-time search/filter bar and a per-model visibility toggle (👁 icon). Hidden models are grayed out and excluded from the `/v1/models` catalog. An active-count badge (`N/M active`) shows at a glance how many models are enabled (#750).\n- **Chinese Localization (zh-CN):** Added missing translations for Context Relay, Memory, LKGP, and Models.dev sync features, while standardizing terminology across the application (#1079).\n- **Environment Auto-Sync:** Added `sync-env.mjs` to auto-generate and append `.env` from `.env.example` during installation, automatically generating cryptographic secrets on first run.\n- **Source Mode Dashboard Update:** Fixed real-time Source (git-checkout) updating in the dashboard, enabling secure, real-time update pipelines for non-NPM installations.\n\n### 🐛 Bug Fixes & Security\n\n- **Hardcoded Secret Cleanup:** Removed 12 hardcoded OAuth credential fallbacks from the source code, forcing secure reliance on environment variables and resolving static analysis security alerts.\n- **Next.js Security Patch:** Bumped `next` from 16.2.2 to 16.2.3 to resolve critical RSC deserialization RCE vulnerability (SNYK-JS-NEXT-15954202).\n- **Memory/Cache UI Crash:** Added null-safety guards (`?? 0`) to `.toLocaleString()` calls in Memory and Cache dashboard pages, preventing `TypeError` crashes when database tables are empty or contain null numeric values (#1083).\n- **WebSearch tool_choice Translation:** Fixed OpenAI-to-Claude translator dropping `tool_choice` objects with `type: \"function\"` as-is, which Claude rejects. Now properly maps all OpenAI `tool_choice` variants (`function`, `required`, `none`) to Claude-compatible format (`tool`, `any`, `auto`), fixing \"Did 0 searches\" in Claude Code WebSearch (#1072).\n- **Provider Validation baseUrl Override:** Added `baseUrl` passthrough from frontend validation requests to the backend validation endpoint. Chinese-site users of Alibaba Coding Plan (bailian-coding-plan) can now validate API keys against their custom Base URL instead of always hitting the international endpoint (#1078).\n- **Minimax Auth Header:** Switched Minimax provider from `x-api-key` to `Authorization: Bearer` header format, matching the current API spec (#1076).\n- **Native Fetch Fallback:** Added graceful fallback to native `fetch` when the `undici` dispatcher fails, improving resilience in environments where undici is unavailable (#1054).\n- **EPIPE Flood Fix:** Added circuit-breaker logic to prevent EPIPE errors from creating a feedback loop that fills logs at GB/s (#1006).\n- **Qoder PAT Validation:** Improved Qoder Personal Access Token validation with actionable error messages that guide users to the correct token format (#966).\n- **CI/CD Pipeline:** Fixed `check:docs-sync` failure by syncing OpenAPI version to 3.5.6 and finalizing CHANGELOG release heading. Commented out `DATA_DIR` in `.env.example` to prevent E2E test failures in CI runners lacking root permissions.\n\n### 🌍 i18n\n\n- **Auto Language Generation (CI):** Added CI pipeline to auto-generate missing language files and strings via `feat(CI,i18n)` workflow, covering 30+ locales (#1071).\n\n---\n\n## [3.5.5] — 2026-04-08\n\n### ✨ New Features\n\n- **Node.js 24 Compatibility Warning:** Added a proactive version incompatibility warning on the login page to guide users to the stable Node.js 22 LTS, preventing native sqlite binding crashes.\n- **Context Relay Combo Strategy:** Added the new `context-relay` combo strategy with priority-style routing, structured handoff summary generation once quota usage reaches the warning threshold, and handoff injection after the next real account switch.\n- **Global Context Relay Defaults:** Added global Settings defaults plus combo-level configuration for `handoffThreshold`, `handoffModel`, and `handoffProviders`, so new or unconfigured combos can inherit the feature consistently.\n\n### 🐛 Bug Fixes\n\n- **Proxy Connection Healthchecks:** Applied proxy resolution per connection in the sweeping loop (`tokenHealthCheck.ts`) and global provider validation sweeps, resolving Node 22 bypass and improving proxy stability (#1051, #1056, #1061).\n- **Security Vulnerability Remediation:** Resolved multiple CodeQL scanning alerts including SSRF in model sync, insecure randomness in web crypto (`generateSessionId`), and incomplete URL sanitization.\n- **Context Relay Typing & Synchronization:** Reverted out-of-scope test breakages and resolved `handoffProvider` and response `input` extraction payload typing.\n- **Legacy OpenAI-Compatible Responses Routing:** Fixed legacy/imported OpenAI-compatible providers (for example `openai-compatible-sp-openai`) incorrectly routing Chat Completions traffic to `/chat/completions` when the real provider node was configured as `apiType: \"responses\"`. OmniRoute now treats `providerSpecificData.apiType` as authoritative across routing, executors, and translator tools, avoiding false empty-content failures during combo/provider smoke tests (#1069).\n- **Gemini PDF Attachment Integration:** Fixed payload generation and format for parsing `inline_data` and generic base64 sources for deep Gemini PDF routing (#993, #1021).\n- **Vercel AI SDK Fallbacks:** Mapped `max_output_tokens` to `max_tokens` for strict OpenAI-compatible providers, resolving errors from standard AI agents and frameworks (#994).\n- **External Auth & UI Reliability:** Handled null `state` failures in Cline OAuth exchange (#1016), added 3rd-party 400 error patterns to combo fallback (#1024), and resolved desktop sidebar layout and popover overflows (#1039, #1001).\n- **Context Relay In-Flight Deduplication:** Prevented duplicate handoff generation for the same session/combo while an earlier summary request is still in flight.\n- **Context Relay Provider Gating:** Aligned runtime behavior with configuration so explicit `handoffProviders` exclusions, including an empty array, now disable handoff generation as expected.\n\n### 🛠️ Maintenance & Dependabot\n\n- **Updated Sub-dependencies:** Bumped `hono` to `4.12.12` and `@hono/node-server` to `1.19.13` to patch critical security gaps (#1063, #1064, #1067, #1068).\n\n### Dokumentation\n\n- **Documentation Synchronization:** Updated system documentation (README, Architecture, Features, Tools, Troubleshooting) and synced `i18n` configurations to match the v3.5.5 context relay patterns and proxy troubleshooting steps.\n- **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance.\n\n---\n\n## [3.5.4] — 2026-04-07\n\n### ✨ New Features\n\n- **Detailed Token Tracking:** Added granular token breakdown columns (cache read, cache write, reasoning) to call logs with proper null vs zero distinction. Includes DB migration 018 and 5-label UI display per provider capability (#1017 — thanks @rdself).\n- **Legacy JSON Config Import/Export:** Restored JSON-based settings export and import for migration from legacy 9router configurations. Security-hardened with Zero-Trust redaction of passwords and `requireLogin` fields, and automatic pre-import database backups (#1012 — thanks @luandiasrj).\n- **Non-Stream Aliases:** Added API support for explicit non-streaming aliases (`non_stream`, `disable_stream`, `disable_streaming`, `streaming=false`), normalized at the boundary before provider translation (#1036 — thanks @wlfonseca).\n- **Russian Dashboard Localization:** Comprehensive Russian translation for the dashboard UI, including fixes for 2 Ukrainian locale keys (#1003 — thanks @mercs2910).\n\n### 🐛 Bug Fixes\n\n- **Anthropic Streaming Input Undercount:** Fixed a critical bug where Anthropic streaming `prompt_tokens` only reported non-cached tokens (e.g., `in=3` when actual total was 113,616). Cache tokens are now summed into prompt_tokens during streaming (#1017).\n- **Built-in Responses API Tool Types:** Preserved built-in Responses API tools (`web_search`, `file_search`, `computer`, `code_interpreter`, `image_generation`) from being silently stripped by the empty-name tool filter — these tools carry no `.name` field (#1014 — thanks @rdself).\n- **Cursor/Codex Responses Compatibility:** Fixed empty output in Cursor when using Codex models by hoisting system input items to `instructions`, sanitizing invalid tool names, and detecting Responses-format payloads on chat/completions endpoint (#1002 — thanks @mercs2910).\n- **OAuth Token Expiry Display:** Fixed OAuth connections showing \"expired\" badge even with valid tokens by reading `tokenExpiresAt` (updated on refresh) instead of `expiresAt` (original grant timestamp) (#1032 — thanks @tombii).\n- **Codex Fast-Tier Copy:** Corrected dashboard settings copy from `service_tier=fast` to `service_tier=priority`, matching the actual Codex wire format (#1045 — thanks @kfiramar).\n- **macOS Desktop App Startup:** Stabilized packaged macOS app launch by excluding desktop artifacts from the standalone bundle and improving launch path detection (#1004 — thanks @mercs2910).\n- **macOS Sidebar Layout:** Fixed macOS traffic light overlap, sidebar spacing, and button overflow in the Electron desktop app (#1001 — thanks @mercs2910).\n\n### ⚡ Performance\n\n- **Analytics Page Load:** Dramatically reduced analytics page load times (30s→1-2s for 50K entries) via date-filtered DB queries, parallel `Promise.all()` cost calculations, and merged 6 COUNT queries into a single CASE WHEN aggregate (#1038 — thanks @oyi77).\n\n### 🔒 Security & Dependencies\n\n- **Node Base Image:** Upgraded Docker base from `22-bookworm-slim` to `22.22.2-trixie-slim` (#1011 — Snyk).\n- **Production Dependencies:** Bumped 5 production dependencies (#1044 — Dependabot).\n- **Vite:** Bumped from 8.0.3 to 8.0.5 (#1031 — Dependabot).\n- **Development Dependencies:** Bumped 4 development dependencies (#1030 — Dependabot).\n\n### 🧪 Tests\n\n- **Token Accounting Tests:** Added 18 new unit tests covering detailed token breakdown, null vs zero semantics, per-provider token extraction, and Anthropic streaming input fix (#1017).\n- **Built-in Tool Tests:** Added 3 new test cases for built-in Responses API tool type preservation (#1014).\n- **ChatCore Sanitization:** Updated sanitization tests to accommodate Responses format detection (PR #1002) and built-in tool preservation (PR #1014).\n\n### 🛠️ Maintenance\n\n- **PR Workflow:** Updated `/review-prs` workflow to merge PRs into the release branch (`release/vX.Y.Z`) instead of directly into `main`, ensuring proper pre-release staging.\n\n### Coverage\n\n- **2537 tests, 2532 passing** — Statement coverage: 91.95%, Branch coverage: 78.79%, Function coverage: 93.19%\n\n## [3.5.3] - 2026-04-07\n\n### Sicherheit\n\n- **Vulnerabilities:** Fully remediated 12 High-Severity CodeQL vulnerabilities by migrating from Math.random to `crypto.randomUUID()`, wrapping SSE injection points with aggressive backslash escaping, sanitizing trailing HTTP fragments, and enforcing rigid SSRF HTTP verification schemes across internal routes.\n- **Dependencies:** Upgraded Next.js to `^16.2.2` and Vite to `>=8.0.5` resolving critical DoS, arbitrary file reads and CSRF vectors in the build/server environments.\n\n### Fixed\n\n- **E2E Stability:** Eliminated extreme CI unreliability and transient test timeouts (Playwright) by propagating internal standalone `_next/static` assets properly and refactoring deep UI interactions inside defensive `expect().toPass()` loops.\n- **Middleware:** Resolved infinite redirect loop on dashboard for fresh instances when requireLogin is disabled.\n- **Core Fallbacks:** Preserved primary failure contexts and enhanced Edge-case error handling pipelines across chat and fallback loops.\n- **Proxy/Hooks:** Optimized local git hooks, normalized token coverage endpoints into `/coverage`, and guarded GLM region lookups.\n\n### 🛠️ Maintenance\n\n- **CI/CD Stabilization:** Prevented random GitHub Runner freezes by decoupling sharded processes, adjusting test concurrencies, unref-ing active connections on server teardown, and strictly capping job timeout durations.\n\n### Dokumentation\n\n- **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned).\n\n### Coverage\n\n- **Testing:** Consolidated the workspace test coverage framework hitting 92.1% statement line coverage, with new rigid unit-tests matching API key policies and tool scopes.\n\n---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n- **Qoder API Native Integration:** Completely refactored the Qoder Executor to bypass the legacy COSY AES/RSA encryption algorithm, routing directly into the native DashScope OpenAi-compatible URL. Eliminates complex dependencies on Node `crypto` modules while improving stream fidelity.\n- **Resilience Engine Overhaul:** Integrated context overflow graceful fallbacks, proactive OAuth token detection, and empty-content emission prevention (#990).\n- **Context-Optimized Routing Strategy:** Added new intelligent routing capability to natively maximize context windows in automated combo deployments (#990).\n\n### 🐛 Bug Fixes\n\n- **Responses API Stream Corruption:** Fixed deep-cloning corruption where Anthropic/OpenAI translation boundaries stripped `response.` specific SSE prefixes from streaming boundaries (#992).\n- **Claude Cache Passthrough Alignment:** Aligned CC-Compatible cache markers consistently with upstream Client Pass-Through mode preserving prompt caching.\n- **Turbopack Memory Leak:** Pinned Next.js to strict `16.0.10` preventing memory leaks and build staleness from recent upstream Turbopack hashed module regressions (#987).\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **Models.dev Integration:** Integrated models.dev as the authoritative runtime source for model pricing, capabilities, and specifications, overriding hardcoded prices. Includes a settings UI to manage sync intervals, translation strings for all 30 languages, and robust test coverage.\n- **Provider Native Capabilities:** Added support for declaring and checking native API features (e.g. `systemInstructions_supported`) preventing failures by sanitizing invalid roles. Currently configured for Gemini Base and Antigravity OAuth providers.\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Sicherheit\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Funktionen\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Sicherheit\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicherheit\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicherheit\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Dokumentation\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Dokumentation\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funktionen\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funktionen\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funktionen\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicherheit\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funktionen\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funktionen\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funktionen\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funktionen\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funktionen\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funktionen\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funktionen\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funktionen\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicherheit\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\bany\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funktionen\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funktionen\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funktionen\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funktionen\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funktionen\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funktionen\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Dokumentation\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funktionen\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "e5c4e450c0cd597c2de3d9dde1d74b572c0a6bb3": {"t": 1785765398.8139362, "n": 229494, "h": "2924cc22bcef6cf5", "c": "# Changelog (Deutsch)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.6.8] — 2026-04-17\n\n### ✨ New Features\n\n- **feat(providers):** Support `xhigh` reasoning tier exclusively on Claude models that expose it (#1356)\n- **feat(providers):** Add CC Compatible connection-level 1M context toggle (#1357)\n- **feat(core):** Add full support for Node.js 24 LTS (Krypton) environments with continuous integration coverage (#1340)\n- **feat(dashboard):** Display Antigravity credit balance in dashboard Limits & Quotas (#1338)\n- **feat(i18n):** Add internationalization support for combo features and dashboard components; sync translations across 31 keys (#1318)\n- **feat(providers):** Add Claude Opus 4.7 to Claude Code OAuth models natively with extended context and caching (#1347)\n- **feat(core):** Add stopSequences support and expand tool definitions to include Google Search capabilities\n- **feat(auth):** Enforce dashboard session authentication on all management API routes, preventing unauthenticated access to configuration endpoints\n- **feat(runtime):** Add hot-reloadable guardrails and model diagnostics for real-time rule evaluation without restarts\n- **feat(core):** Add payload rules, tag-based routing, and scheduled budget systems for fine-grained request governance\n- **feat(providers):** Expose Antigravity preview model aliases and Gemini CLI onboarding flow for first-time setup\n- **feat(antigravity):** Add client model aliases and thoughtSignature bypass modes for Antigravity OAuth connections\n- **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations\n- **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages\n\n### Sicherheit\n\n- **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns\n- **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353)\n- **fix(providers):** Resolve Codex token refresh race condition via mutex `getAccessToken` preventing `refresh_token_reused` Auth0 revocations\n\n### 🔧 Maintenance & Architecture\n\n- **refactor(core):** Split CLI runner and decouple migration engine for extensibility (#1358)\n- **refactor(audit):** Rewire audit dashboard from dead in-memory `configAudit` store to live SQLite `audit_log` table — 331+ hidden compliance entries now visible in `/dashboard/audit`\n- **build(deps):** Bump `softprops/action-gh-release` from v2 to v3\n- **ci:** Bump GitHub Actions CI node-version to Node.js 24 natively\n- **fix(types):** Resolve TypeScript compilation errors in `claudeCodeCompatible.ts` (type predicates, `cache_control` index access) and `proxyFetch.ts` (`signal` nullability)\n\n### 🐛 Bug Fixes\n\n- **fix(context):** Scale reserved context tokens dynamically using a 15% sliding window for smaller models\n- **test(core):** Replace unit test with integration test for proactive context compression to align with isolated runner rules (#1378)\n- **fix(services):** Pass origin provider to refreshWithRetry to avoid tripping the generic \"unknown\" circuit breaker (fixes Codex accounts erroneously disabling)\n- **fix(db):** Prevent native module ABI load crashes from assuming database corruption and skipping databases\n- **fix(db):** Increase mass-migration threshold from 5 to 50 pending migrations to protect legacy users upgrading node\n- **fix(db):** Prevent migration runner safety aborts from triggering on fresh `DATA_DIR` installations by detecting new databases (#1328)\n- **fix(mcp):** Checkpoint and close MCP audit SQLite database safely on process signals and shutdown (#1348)\n- **fix(mcp):** Fully decouple MCP audit SQLite connection caching via globalThis to fix unhandled teardown in standalone Next.js chunks (#1349)\n- **fix(cli):** Avoid creating app router directory during postinstall initialization on non-built source trees (#1351)\n- **fix(codex):** Correctly translate `system` role to `developer` in input array to unlock GPT-5 automatic prompt caching (#1346)\n- **fix(core):** Pass client headers to executor in chatCore (#1335)\n- **fix(providers):** Separate test batch calls and ignore unknown connections\n- **fix(providers):** Add grok-web SSO cookie validation handler (#1334)\n- **fix(db):** Preserve key_value settings (dashboard passwords, saved aliases) across DB heuristic recreation cycles (#1333)\n- **fix(routing):** Allow combo fallback to cascade context overflow 400 errors instead of immediate aborts (#1331)\n- **fix(core):** Resolve thinking leaks, consecutive roles, and missing thoughtSignatures for Antigravity translator (#1316)\n- **fix(translator):** Only apply thoughtSignature to the first `functionCall` part in Gemini parallel tool calls, preventing duplicate signatures\n- **fix(providers):** Default to batch testing execution blocks for web, search, and audio modalities to prevent connection timeouts\n- **fix(cli):** Resolve Node 22 TS entrypoint incompatibility by using esbuild compilation (#1315)\n- **fix(chat):** Preserve max_output_tokens for Responses API targets in chatCore sanitization (#1313)\n- **fix(api):** API Manager usage stats showing 0 for all registered keys (#1310)\n- **fix(api):** Support image-only models in catalog and allow authless search providers to bypass validation requirements\n- **fix(routes):** Require prompts for media generation requests (`/images`, `/videos`, `/music`), returning 400 on missing payloads\n- **fix(dashboard):** Auto-scroll ActivityHeatmap to show current date (#1309)\n- **fix(dashboard):** Restore horizontal layout with `w-max` wrapper in heatmap components\n- **fix(i18n):** Update `nodeIncompatibleHint` to recommend Node 24 LTS across all 31 languages\n- **fix(i18n):** Add Chinese i18n support to remaining dashboard components (`Loading.tsx`, `DataTable`, etc.)\n- **fix(requestLogger):** Add missing `cacheSource` and `tps` columns to i18n log detail views\n\n## [3.6.6] — 2026-04-15\n\n### ✨ New Features\n\n- **feat(storage):** Add database backup cleanup controls, UI management, and customizable retention period env vars (#1304)\n- **feat(providers):** Add Freepik Pikaso image generation provider with support for cookie/subscription-based auth modes (#1277)\n- **feat(providers): Add Perplexity Web (Session) Provider** — Routes through Perplexity's internal SSE API using a session cookie, giving native proxy access without separate API costs to GPT-5.4, Claude Opus, Gemini 3.1 Pro, and Nemotron via preferences mapping (#1289)\n- **feat(api): Sync Tokens & V1 WebSocket Bridge** — Dedicated sync token storage, issuance, revocation, and bundle download routes backed by stable config bundle versioning with ETag support. Exposes `/v1/ws` WebSocket upgrade route and a custom Next.js server bridge (`scripts/v1-ws-bridge.mjs`) so OpenAI-compatible WebSocket traffic can be proxied through the gateway. Compliance auditing expanded with structured metadata, pagination, request context, auth/provider credential events, and SSRF-blocked validation logging. New migrations: `024_create_sync_tokens.sql`. New modules: `syncTokens.ts`, `src/lib/sync/bundle.ts`, `src/lib/sync/tokens.ts`, `src/lib/ws/handshake.ts`, `src/lib/apiBridgeServer.ts`, `src/lib/compliance/providerAudit.ts`.\n- **feat(models): GLM Thinking Preset & Hybrid Token Counting** — GLM Thinking (`glmt`) registered as a first-class provider preset with shared GLM model metadata, pricing, per-connection usage sync, dashboard support, and `maxTokens: 65536 / thinkingBudgetTokens: 24576` request defaults with 900s extended timeout. Provider-side `/messages/count_tokens` endpoint used when a Claude-compatible upstream supports it; gracefully falls back to estimation on missing models, missing credentials, or upstream failures. Startup seeding of default model aliases (`src/lib/modelAliasSeed.ts`) normalizes common cross-proxy model dialects so canonical slash-based model IDs are not misrouted. New file `open-sse/config/glmProvider.ts`.\n- **feat(core): Hardened Outbound Provider Calls & Cooldown Retries** — Guarded outbound fetch helpers (`src/shared/network/safeOutboundFetch.ts`, `src/shared/network/outboundUrlGuard.ts`) blocking private/local URLs with configurable retry, timeout normalisation, and route-level status propagation for provider validation and model discovery. Cooldown-aware chat retries (`src/sse/services/cooldownAwareRetry.ts`) with configurable `requestRetry` and `maxRetryIntervalSec` settings and model-scoped cooldown responses. Improved rate-limit learning from headers and error bodies so short upstream lockouts can recover automatically. Runtime environment validation (`src/lib/env/runtimeEnv.ts`) checks env at startup. Pollinations now requires an API key. Antigravity and Codex header handling aligned via `open-sse/config/antigravityUpstream.ts` and `open-sse/config/codexClient.ts`. Gemini tool names restored in translated responses; synthetic Claude text block injected when upstream SSE completes empty.\n- **feat(logs):** Add TPS (Tokens Per Second) metric to log details modal metadata grid (#1182)\n- **feat(memory+skills):** Full-featured Memory & Skills systems with FTS5 SQLite search, dynamic UI pagination, backend observability, and extensive test coverage (#1228)\n- **feat(bailian-quota):** Add Alibaba Coding Plan quota monitoring, multi-window quota extraction, and UI credential validation (#1235)\n- **feat(storage): Call Log Storage Refactor** — Extracted heavy request/response JSON payloads from the core SQLite database (`storage.sqlite`) into filesystem artifacts stored within `DATA_DIR/call_logs`. This massively reduces WAL bloat and eliminates `SQLITE_FULL` crashes on high-traffic nodes (#1307).\n- **feat(providers): Add Grok Web (Subscription) Provider** — Routes through the xAI web interface for subscription users via cookie session mapping (#1295).\n- **feat(api): Advanced Media Support** — Extends OpenAI generic proxy layer to natively support `image`, `embeddings`, `audio-transcriptions`, and `audio-speech` workflows (#1297).\n- **feat(cli-tools): Qwen Code CLI Integration** — Full integration for Qwen Code local execution mapping, model resolution, and dynamic API key fetching (#1266, #1263).\n- **feat(oauth):** Supports `cursor-agent` CLI as a native Cursor credential source alongside the standard configuration (#1258).\n- **feat(models):** Custom and imported models now merge correctly into filter lists for all available global providers (#1191).\n\n### 🐛 Bug Fixes\n\n- **fix(providers):** match correct endpoint api.xiaomimimo.com for Xiaomi MiMo (#1303)\n- **fix(core):** strip provider alias routing prefix from payload for custom endpoints to fix Azure OpenAI 400 errors (#1261)\n- **fix(core):** ProxyFetch Undici dispatcher automatically bypasses LAN/local addresses, preventing fetch failures on internal OpenRouter requests (#1254)\n- **fix(core):** Gemini thought stream signature detection upgraded to use native part.thought boolean, preventing reasoning text leaks (#1298)\n- **deps:** bump hono from 4.12.12 to 4.12.14 to resolve CVE SSR HTML injection vulnerability (#1306, #59)\n- **deps:** update dompurify to 3.4.0 in frontend overrides mitigating XSS HTML Injection (CVE-XYZ / Dependabot #60)\n- **test:** Disable SQLite automatic backups during continuous integration (CI) tests to resolve E2E timeout issues limiting runner scaling (#24481475058)\n- **feat(core): Proactive Context Compression** — `chatCore` now proactively compresses oversized message contexts before hitting upstream providers to dramatically reduce `context_length_exceeded` errors. Employs binary-search message pruning with structural integrity guarantees tracking explicit `tool_use` boundaries ensuring truncated tool inputs drop paired outputs appropriately (#1292, #1293)\n\n- **fix(cli):** Resolve codex routing config parsing by strictly quoting section keys array, enforcing responses wire_api with fallback, and standardizing select-model button positioning mirroring Claude UI\n- **fix(providers):** Correct Lobehub provider icons rendering by removing unsupported local references ensuring local SVG/PNG fallback mechanism invokes natively\n- **fix(db):** Implement Database migration tracking safety abort safeguards (pre-migration backups via `VACUUM INTO` and mass renumbering warnings) to protect existing database structures on startup upgrades (#1281)\n- **fix(dashboard):** Cleaned up target codex `config.toml` structure preventing recursive section rendering by enforcing quotes on section dot paths and mapping correct UI `OMNIROUTE_API_KEY` names.\n- **fix(mcp):** Add dedicated explicit timeout constraint overrides for search handlers (#1280)\n- **fix(crypto):** Add validation guard to encryption layer to surface clear UI errors when cryptographic environment variables are missing, replacing raw Node.js TypeErrors. Legacy env vars `OMNIROUTE_CRYPT_KEY` and `OMNIROUTE_API_KEY_BASE64` now also accepted as fallbacks (#1165)\n- **fix(providers):** Update Pollinations provider definition to require API keys and specify their new limited pollen/hour free tier (#1177)\n- **Streaming `\\n\\n` Artifact Fix (#1211):** Changed `` tag-stripping regex from `?` to `*` quantifier across `combo.ts`, `comboAgentMiddleware.ts`, and `contextHandoff.ts` to greedily strip all accumulated JSON-escaped newline sequences surrounding the tag. This prevents literal `\\n\\n` prefix artifacts from appearing in consumer streaming responses\n- **E2E Combo Test Locator:** Fixed Playwright strict-mode violation in `combo-unification.spec.ts` by replacing ambiguous `getByRole` locator with a compound filter locator for the \"All\" strategy tab\n- **fix(cc-compatible):** Trim beta flags and preserve cache passthrough for third-party HTTP proxy compatibility (#1230)\n- **fix(providers):** Update Xiaomi MiMo endpoints to the live token-plan, migrating away from dead API URLs (#1238)\n- **fix:** Forward client `x-initiator` header to GitHub Copilot upstream to accurately distinguish agent vs user turns (#1227)\n- **fix:** Resolve backlog bugs including streaming edge cases, unhandled rejections, and quota parse failures (#1206, #1220, #1231, #1175, #1187, #1218, #1202)\n- **fix(tests):** Resolve memory migration and skills route pagination bugs arising from PR overlaps\n- **fix(i18n):** Add missing Chinese i18n support to dashboard components (`DataTable`, `EmptyState`, etc), update `en.json/zh-CN.json` routing keys, and natively resolve JSX defaults via `next-intl` (#1274)\n\n### 🔧 Internal Improvements\n\n- **Compliance Audit Expansion:** `src/lib/compliance/index.ts` expanded with structured metadata, pagination support, request context enrichment, and new `providerAudit.ts` module logging auth and provider credential events, SSRF-blocked validation attempts, and provider CRUD operations\n- **Config Sync Bundle:** `src/lib/sync/bundle.ts` exports `buildConfigBundle()` generating a versioned JSON snapshot of settings, provider connections, nodes, model aliases, combos, and API keys (passwords redacted) with ETag support for bandwidth-efficient polling\n- **Codex Client Constants:** Centralized `CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT_PLATFORM`, and pattern-validated env overrides (`CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT`) in `open-sse/config/codexClient.ts`\n- **Antigravity Upstream Constants:** `open-sse/config/antigravityUpstream.ts` consolidates all Antigravity base URLs and model/fetchAvailableModels discovery path builders\n- **Model Alias Seed:** `src/lib/modelAliasSeed.ts` seeds 30+ cross-proxy model dialect aliases (e.g. `openai/gpt-5` → `gpt-5`, `anthropic/claude-opus-4-6` → `cc/claude-opus-4-6`) at startup via idempotent `upsert`\n- **Test Coverage:** 15+ new unit test suites covering sync routes, WebSocket bridge, compliance index, GLM provider config, cooldown-aware retry, safe outbound fetch, stream utilities, Codex executor, provider validation branches, model cross-proxy compatibility, and model alias seeding\n- **TypeScript Migration:** Finalized migration of remaining JS tests (`proxy-load` and `testFromFile`) to TypeScript ES modules, ensuring a fully synchronized TS stack.\n- **Reliability & Resilience:** Added exponential backoff to `models.dev` auto-sync to combat transient network failures, raised interval floor to 1 hour, and added LKGP debug logging for enhanced observability during routing. (#1286)\n\n---\n\n## [3.6.5] — 2026-04-13\n\n### ✨ New Features\n\n- **Antigravity AI Credits Fallback:** Automatically retries with `GOOGLE_ONE_AI` credit injection when free-tier quota is exhausted. Per-account credit balance (5-hour TTL) is cached from SSE `remainingCredits` and exposed as a numeric badge in the Provider Usage dashboard (#1190 — thanks @sFaxsy)\n- **Claude Code Native Parity:** Full header/body signing parity with the Claude Code 2.1.87 OAuth client — CCH xxHash64 body signing with singleton WASM initialization promise (fixing race conditions), dynamic per-request fingerprint, bidirectional TitleCase ↔ lowercase tool name remapping (14 tools), API constraint enforcement (`temperature=1` for thinking, max 4 `cache_control` blocks, auto-inject ephemeral on last user message), and optional ZWJ obfuscation. Wired into `BaseExecutor` for automatic CCH signing on all `anthropic-compatible-cc-*` providers and into `chatCore` for synchronous parity pipeline steps (#1188 — thanks @RaviTharuma)\n- **Per-Connection Codex Defaults:** Codex Fast Service Tier and Reasoning Effort settings are now per-connection instead of a single global toggle. Existing connections are migrated automatically on startup via an idempotent backfill migration (#1176 — thanks @rdself)\n- **Cursor Usage Dashboard:** New `getCursorUsage()` fetches quotas from Cursor's `/api/usage`, `/api/auth/me`, and `/api/subscription` endpoints. Displays standard requests, on-demand usage, and per-plan limits (Free/Pro/Business/Team). Client version bumped to `3.1.0` and `x-cursor-user-agent` header added for parity\n- **Database Health Check System:** Automated periodic SQLite integrity monitoring via `runDbHealthCheck()` — detects orphan quota/domain rows, broken combo references, stale snapshots, and invalid JSON state. Runs every 6 hours (configurable via `OMNIROUTE_DB_HEALTHCHECK_INTERVAL_MS`), with auto-repair and pre-repair backup. Exposed as **MCP tool #18** (`omniroute_db_health_check`) with Zod schemas and `autoRepair` option. Dashboard panel in Health page with status card, issue count, repaired count, and one-click repair button\n- **OpenAI Responses API Store Opt-In:** Per-connection `openaiStoreEnabled` flag controls whether the `store` field is preserved or forced to `false` on Codex Responses API requests. When enabled, `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields are round-tripped through the Chat Completions → Responses translation, enabling multi-turn context caching on supported providers\n- **Email Privacy Toggle (Combos Page):** Global email visibility toggle (`EmailPrivacyToggle`) added to the Combos page header with responsive layout, tooltip guidance, and per-connection label masking via `pickDisplayValue()`. All combo builder options, provider connection lists, and quota screens now respect the global privacy state from `emailPrivacyStore`\n- **skills.sh Integration:** Added `skills.sh` as an external skill provider. Users can now search, browse, and install agent skills directly from a new \"skills.sh\" tab in the Skills dashboard. Includes backend API resolvers, frontend implementation with search/install states, and a dedicated unit test suite (#1223 — thanks @RaviTharuma)\n- **Stabilization Settings:** Added persistence support for `lkgpEnabled` and `backgroundDegradation` settings, integrated into `instrumentation-node.ts` for improved lifecycle awareness (#1212)\n- **xxhash-wasm dependency:** Added `xxhash-wasm@^1.1.0` for CCH signing (xxHash64 with seed `0x6E52736AC806831E`)\n\n### 🐛 Bug Fixes\n\n- **Codex `stream: false` via Combo (ALL_ACCOUNTS_INACTIVE):** Fixed a critical bug where Codex combos returned `ALL_ACCOUNTS_INACTIVE` or empty content when the client sent `stream: false`. Root cause was triple: (1) `CodexExecutor.transformRequest()` mutated `body.stream` in-place to `true`, contaminating the combo's quality check which skipped validation thinking it was streaming; (2) the non-stream SSE parser used the wrong format (Chat Completions instead of Responses API) for Codex SSE output; (3) combo quality validation read the mutated `body.stream` instead of the client's original intent. Fixed by: cloning the body via `structuredClone()` in CodexExecutor, detecting Codex/Responses SSE format in the non-stream fallback path (with auto-translation back to Chat Completions), and capturing `clientRequestedStream` before the combo loop\n- **Gemini CLI Tool Schema Rejection:** Fixed 400 Bad Request errors from the Google API by strictly filtering non-standard vendor extensions (starting with `x-`) and `deprecated` fields from tool parameter schemas (#1206)\n- **SOCKS5 Proxy Interop (Node.js 22):** Resolved `invalid onRequestStart method` crashes caused by `undici` version mismatches between dispatchers and the built-in fetch. Hardened `proxyFetch.ts` to strictly use the library's fetch implementation for custom dispatchers (#1219)\n- **Search Cache Coalescing with TTL=0:** Fixed a bug where providers configured with `cacheTTLMs: 0` (caching explicitly disabled) still had concurrent requests coalesced and returned `{ cached: true }`. Now each call gets its own independent upstream fetch (#1178 — thanks @sjhddh)\n- **Antigravity Credit Cache Alignment (PR #1190):** Reconciled `accountId` derivation between `AntigravityExecutor.collectStreamToResponse` and `getAntigravityUsage` to use consistent cache keys (`email || sub || \"unknown\"`). Previously, SSE-parsed credit balances could be written under a different key than the one read by the usage dashboard, causing stale/missing credit badges\n- **Non-streaming reasoning_content Duplication:** Fixed clients rendering duplicated reasoning panels when both `reasoning_content` and visible `content` were present in non-streaming responses. `responseSanitizer` now strips `reasoning_content` from messages that already have visible text content, preserving it only for reasoning-only messages\n- **Streaming Regression Fix:** Hardened the `sanitize` TransformStream in the combo engine to strip both literal and JSON-escaped newline sequences, eliminating leading `\\n\\n` prefixes in assistant responses (#1211)\n- **Gemini Empty Choice Fix:** Ensured initial assistant deltas always include an empty `content: \"\"` string to satisfy strict OpenAI client requirements and prevent empty choice responses in tools (#1209)\n- **Gemini Tools Sanitizer Deduplication:** Extracted shared tool conversion logic into `buildGeminiTools()` helper (`geminiToolsSanitizer.ts`), eliminating duplicate implementations between `openai-to-gemini.ts` and `claude-to-gemini.ts`. The new helper correctly handles `web_search` / `web_search_preview` tool types by emitting `googleSearch` tools with priority over function declarations\n- **Qwen/Qoder Thinking+Tool_Choice Conflict:** Added `sanitizeQwenThinkingToolChoice()` to both `DefaultExecutor` (for Qwen provider) and `QoderExecutor` to prevent provider-side 400 errors when clients send `tool_choice` alongside thinking/reasoning parameters that are mutually exclusive upstream\n- **API Key Deletion Orphan Cleanup:** Deleting an API key now also removes associated `domain_budgets` and `domain_cost_history` rows, preventing orphan data accumulation\n- **CC-compatible test assertion:** Fixed pre-existing test that expected no `cache_control` on system blocks — the billing header system block now carries `cache_control: { type: \"ephemeral\" }` per PR #1188 design\n- **Codex Combo Smoke Test False Positives:** Fixed combo tests incorrectly reporting `ERROR` for valid Codex streaming responses when `response.output` is empty but text deltas were emitted. The summary now falls back to accumulated delta text (#1176 — thanks @rdself)\n- **Electron Builder Version Mismatch:** Fixed Electron desktop startup failures on Windows packaged builds caused by native modules (`better-sqlite3`) being under `app.asar.unpacked` while helpers were in `app/node_modules`. `resolveServerNodePath()` now merges both locations with deduplication and existence checks (#1172 — thanks @backryun)\n\n### 🔧 Internal Improvements\n\n- **SSE Parser: Responses API Non-Stream Conversion:** Added full `parseSSEToResponsesOutput()` implementation in `sseParser.ts` (255+ lines) — reconstructs complete Responses API objects from SSE event streams, handling `response.output_text.delta/done`, `response.reasoning_summary_text.delta/done`, `response.function_call_arguments.delta/done`, and terminal events. Used by the new chatCore non-stream fallback path for Codex\n- **Cursor Executor Version Sync:** Updated Cursor client User-Agent to `3.1.0` and centralized version constants (`CURSOR_CLIENT_VERSION`, `CURSOR_USER_AGENT`) for consistent fingerprinting across executor, usage fetcher, and OAuth flows\n- **Responses API Translator Parity:** `convertResponsesApiFormat()` now accepts credentials and passes them through to the translator, enabling store-aware field propagation. Round-trip preservation of `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields\n- **Provider Schema Validation:** Added `openaiStoreEnabled` boolean validation to `providerSpecificData` Zod schema\n- **Combo Error Response Normalization:** Empty combo targets now return 404 (`comboModelNotFoundResponse`) instead of generic 503, improving client-side error differentiation\n- **Dependency Updates:** Bumps `typescript-eslint` to `8.58.2` (dev), `axios` to `1.15.0` (prod), and `next` to `16.2.2` (prod) (#1224, #1225)\n\n### ⚠️ Breaking Changes\n\n- **`DELETE /api/settings/codex-service-tier` removed:** This endpoint no longer exists. Codex Service Tier configuration has moved to per-connection `providerSpecificData.requestDefaults`. Existing connections are migrated automatically on first startup after upgrade. Any external scripts or integrations that call this endpoint should be updated — use `PUT /api/providers/:id` with `providerSpecificData.requestDefaults.serviceTier` instead (#1176).\n- **CCH signing on CC-compatible providers:** All requests to `anthropic-compatible-cc-*` providers now include an xxHash64 integrity token (`cch=...`) in the billing header. Providers that do not validate CCH will ignore it (no behavioral change), but any custom middleware inspecting the billing header should expect a 5-character hex token instead of the `00000` placeholder\n\n---\n\n## [3.6.4] — 2026-04-12\n\n### ✨ New Features\n\n- **Combo Builder v2 (Wizard UI):** Completely redesigned the combo creation/editing interface as a multi-stage wizard with stages: Basics → Steps → Strategy → Review. The builder fetches provider, model, and connection metadata via a new `GET /api/combos/builder/options` endpoint, enabling precise provider/model/account selection with duplicate detection and automatic next-connection suggestion. Heavy UI components (`ModelSelectModal`, `ProxyConfigModal`, `ModelRoutingSection`) are now lazily loaded via `next/dynamic` for faster initial page render\n- **Combo Step Architecture (Schema v2):** Introduced a structured step model (`ComboModelStep`, `ComboRefStep`) replacing the legacy flat string/object combo entries. Steps carry explicit `id`, `kind`, `providerId`, `connectionId`, `weight`, and `label` fields, enabling pinned-account routing, cross-combo references, and per-step metrics. All combo CRUD operations normalize entries through the new `src/lib/combos/steps.ts` module. Zod schemas updated with `comboModelStepInputSchema` and `comboRefStepInputSchema` unions\n- **Composite Tiers System:** Added tiered model routing via `config.compositeTiers` — each tier maps a named stage to a specific combo step with optional fallback chains. Includes comprehensive validation (`src/lib/combos/compositeTiers.ts`) ensuring step existence, preventing circular fallback, and validating default tier references. Zod schema enforcement blocks composite tiers on global defaults (concrete combos only)\n- **Model Capabilities Registry:** Created `src/lib/modelCapabilities.ts` providing `getResolvedModelCapabilities()` — a unified resolver that merges static specs, provider registry data, and live-synced capabilities into a single `ResolvedModelCapabilities` object covering tool calling, reasoning, vision, context window, thinking budget, modalities, and model lifecycle metadata\n- **Observability Module:** Extracted health and telemetry payload construction into `src/lib/monitoring/observability.ts` with `buildHealthPayload()`, `buildTelemetryPayload()`, and `buildSessionsSummary()` builders. The health endpoint now returns session activity, quota monitor status, and per-provider breakdowns alongside existing system metrics\n- **Session & Quota Monitor Dashboard:** Added live Session Activity and Quota Monitors panels to the Health dashboard, showing active session counts, sticky-bound sessions, per-API-key breakdowns, and top session details alongside quota monitor alerting/exhausted/error status with per-provider drill-down\n- **Combo Health Per-Target Analytics:** The combo-health API now resolves per-target metrics using the new `resolveNestedComboTargets()` function, providing step-level success rates, latency, and historical usage breakdowns per execution key — enabling per-account, per-connection health visibility\n- **Auto-Combo → Combos Unification:** Merged the separate `/dashboard/auto-combo` page into the main `/dashboard/combos` page. Auto/LKGP combos are now managed alongside all other combos with a new strategy filter tabs system (All / Intelligent / Deterministic). The old auto-combo route redirects to `/dashboard/combos?filter=intelligent`. Removed the `auto-combo` sidebar entry, consolidating navigation into the single `Combos` item\n- **Intelligent Routing Panel (`IntelligentComboPanel`):** New inline panel (371 lines) within the combos page that shows real-time provider scores, 6-factor scoring breakdown (quota, health, cost, latency, task fitness, stability), mode pack selector, incident mode status, and excluded providers for `auto`/`lkgp` combos — replacing the former standalone auto-combo dashboard\n- **Builder Intelligent Step (`BuilderIntelligentStep`):** New conditional wizard step (280 lines) that appears in the Builder v2 flow only when `strategy=auto` or `strategy=lkgp` is selected. Exposes candidate pool selection, mode pack presets, router sub-strategy selector, exploration rate slider, budget cap, and collapsible advanced scoring weights configuration\n- **Intelligent Routing Module (`intelligentRouting.ts`):** Extracted strategy categorization and filtering logic into a dedicated shared module (210 lines) with `getStrategyCategory()`, `isIntelligentStrategy()`, `filterCombosByStrategyCategory()`, `normalizeIntelligentRoutingFilter()`, and `normalizeIntelligentRoutingConfig()` utility functions\n- **LKGP Standalone Strategy:** Implemented `lkgp` (Last Known Good Provider) as a fully functional standalone combo strategy. Previously, `lkgp` as a combo strategy silently fell through to `priority` ordering — the LKGP lookup only ran inside the `auto` engine. Now `strategy: \"lkgp\"` correctly queries the LKGP state, moves the last successful provider to the top of the target list, and saves the LKGP state after each successful request. Falls back to priority ordering when no LKGP state exists\n- **Unified Routing Rules & Model Aliases:** Consolidated the routing rules and model alias management controls into the Settings page, reducing fragmentation across the dashboard\n\n### ⚡ Performance\n\n- **Middleware Lazy Loading:** Refactored `src/proxy.ts` to lazy-import `apiAuth`, `db/settings`, and `modelSyncScheduler` modules, reducing middleware cold-start overhead. Added inline `isPublicApiRoute()` to avoid loading the full auth module for public routes\n- **E2E Auth Bypass:** Added `NEXT_PUBLIC_OMNIROUTE_E2E_MODE` environment flag to bypass authentication gates for dashboard and management API routes during Playwright E2E test runs\n\n### 🐛 Bug Fixes\n\n- **P2C Credential Selection:** Implemented Power-of-Two-Choices (P2C) connection scoring in `src/sse/services/auth.ts` with quota headroom awareness, error/recency penalties, and forced/excluded connection support. The new `getProviderCredentialsWithQuotaPreflight()` function integrates quota preflight checks directly into credential selection, eliminating the separate Codex-only preflight path\n- **Fixed-Account Combo Steps:** Combo steps with explicit `connectionId` now correctly bypass provider-level model cooldowns and circuit breakers, preventing a single account failure from blocking pinned-connection routing for the same model\n- **Combo Metrics Per-Target Tracking:** Extended `comboMetrics.ts` to track `byTarget` metrics keyed by execution path, recording per-step `provider`, `providerId`, `connectionId`, and `label` alongside existing per-model aggregates\n- **Call Logs Schema Expansion:** Added `requested_model`, `request_type`, `tokens_cache_read`, `tokens_cache_creation`, `tokens_reasoning`, `combo_step_id`, and `combo_execution_key` columns to `call_logs` with auto-migration. Added composite index `idx_cl_combo_target` for efficient per-target historical queries\n- **Quota Monitor Enrichment:** Expanded `quotaMonitor.ts` with full lifecycle state tracking (`status`, `startedAt`, `lastPolledAt`, `consecutiveFailures`, `totalPolls`, `totalAlerts`), ISO-formatted snapshots via `getQuotaMonitorSnapshots()`, and sorted summary via `getQuotaMonitorSummary()`\n- **Codex Quota Fetcher Hardening:** Improved `codexQuotaFetcher.ts` with safer connection registration and quota fetch error handling\n- **LKGP Save Refactored to Async/Await:** Replaced fire-and-forget `.then()` chain for LKGP persistence after successful combo routing with proper `async/await` + `try/catch`, preventing unhandled promise rejections and ensuring LKGP state is reliably saved before the response is returned\n- **Duplicate `auto` in Combo Strategy Schema:** Removed duplicate `\"auto\"` entry from `comboStrategySchema` (was listed on both line 104 and 108). Harmless to Zod runtime but cleaned up to avoid confusion. Schema now has exactly 13 unique strategy values\n- **Legacy Combo Refs Normalization:** Fixed combo step normalization to preserve legacy string combo references during CRUD operations, preventing data loss when editing combos created before the v2 step architecture\n\n### Sicherheit\n\n- **Auth Bypass on Backup Routes (Critical):** Added `isAuthenticated` guards to `/api/db-backups/exportAll` (full database export) and `/api/db-backups` (list, create, and restore backups) — both were previously accessible without authentication\n- **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency\n- **API Key Secret Hardening:** Removed the hardcoded `\"omniroute-default-insecure-api-key-secret\"` fallback from `apiKey.ts` — the function now fails fast if `API_KEY_SECRET` is unset, relying on the startup validator to auto-generate it\n- **NPM Tarball Leak Fix:** Added `app/.env*` to `.npmignore` to prevent the working `.env` file from being shipped inside the npm tarball distribution\n- **Electron Builder CVE Fix:** Bumped `electron-builder` to 26.8.1 to resolve `tar` CVEs in the desktop build pipeline\n\n### 🔧 Maintenance & Infrastructure\n\n- **DB Migration 021:** Added `combo_call_log_targets` migration for `combo_step_id` and `combo_execution_key` columns in call_logs\n- **Combo CRUD Normalization:** `db/combos.ts` now normalizes all stored combo entries through the step normalization pipeline on read, ensuring consistent step IDs and kind annotations regardless of when the combo was created\n- **Playwright Config:** Updated Playwright configuration and `run-next-playwright.mjs` script for improved E2E test orchestration\n- **Build Script:** Updated `build-next-isolated.mjs` with additional reliability improvements\n- **Auto-Combo UI Cleanup:** Deleted `AutoComboModal.tsx` (161 lines), replaced `auto-combo/page.tsx` (478→5 lines) with a server-side redirect to `/dashboard/combos?filter=intelligent`\n- **Sidebar Consolidation:** Removed `\"auto-combo\"` from `HIDEABLE_SIDEBAR_ITEM_IDS` and `PRIMARY_SIDEBAR_ITEMS` — `normalizeHiddenSidebarItems()` silently discards any stale `\"auto-combo\"` entries in user settings\n- **Schema Cleanup:** Removed obsolete `createAutoComboSchema` from `schemas.ts`. Exported `comboStrategySchema` for direct use in test and filter modules\n- **A2A Agent Card Update:** Renamed skill ID from `auto-combo` to `intelligent-routing` with updated description referencing the unified combos dashboard\n- **Builder Draft Refactor:** Extended `builderDraft.ts` with dynamic stage list generation via `getComboBuilderStages()` and `isIntelligentBuilderStrategy()`. Stage navigation (`getNextComboBuilderStage`, `getPreviousComboBuilderStage`, `canAccessComboBuilderStage`) now accepts options to conditionally include/skip the `intelligent` wizard step\n- **i18n Consolidation:** Removed the standalone `\"autoCombo\"` i18n block (22 keys) from all 30 language files. Migrated keys into the `\"combos\"` block with new additions for filter tabs, intelligent panel, and builder step labels\n\n### 🧪 Tests\n\n- **16 New Test Suites:** Added comprehensive test coverage including:\n - `combo-builder-draft.test.mjs` (186 lines) — Builder draft step construction and validation\n - `combo-builder-options-route.test.mjs` (228 lines) — Builder options API endpoint\n - `combo-health-route.test.mjs` (266 lines) — Combo health analytics with per-target metrics\n - `combo-routes-composite-tiers.test.mjs` (157 lines) — Composite tiers API integration\n - `composite-tiers-validation.test.mjs` (131 lines) — Composite tier validation rules\n - `db-combos-crud.test.mjs` — Combo CRUD with step normalization\n - `db-core-init.test.mjs` (129 lines) — DB initialization and column migrations\n - `model-capabilities-registry.test.mjs` (105 lines) — Model capabilities resolution\n - `observability-payloads.test.mjs` (165 lines) — Health/telemetry payload construction\n - `openapi-spec-route.test.mjs` — OpenAPI spec generation\n - `proxy-e2e-mode.test.mjs` (74 lines) — E2E mode auth bypass\n - `quota-monitor.test.mjs` — Quota monitor lifecycle state\n - `run-next-playwright.test.mjs` (119 lines) — Playwright runner script\n - `sse-auth.test.mjs` (154 lines) — P2C credential selection and quota preflight\n - `telemetry-summary-route.test.mjs` (35 lines) — Telemetry summary endpoint\n - Plus updates to 12 existing test files for compatibility with new step architecture\n- **Auto-Combo Unification Tests:**\n - `autocombo-unification.test.mjs` (156 lines) — Strategy categorization, schema deduplication, sidebar cleanup, and routing strategies metadata validation\n - `combo-unification.spec.ts` (189 lines) — Playwright E2E tests for filter tabs, intelligent panel rendering, redirect from old route, sidebar entry removal, and Builder v2 intelligent step flow\n - 3 new LKGP standalone tests in `combo-routing-engine.test.mjs` — Validates LKGP provider prioritization, fallback to priority when no state exists, and LKGP state persistence after successful requests\n - Updated `combo-builder-draft.test.mjs` with intelligent stage navigation tests\n - Updated `sidebar-visibility.test.mjs` to reflect `auto-combo` removal\n\n---\n\n## [3.6.3] — 2026-04-11\n\n### ✨ New Features\n\n- **OpenAI-Compatible Loose Validation:** Empty API keys can now be naturally submitted and saved for any `openai-compatible-*` providers (e.g. Pollinations, localized routes) directly in the UI instead of blocking save actions (#1152)\n- **Cloudflare Configuration:** Updated the provider schema and UI integration for Cloudflare AI to officially expose and support the backend `accountId` field securely without overrides (#1150)\n\n### 🐛 Bug Fixes\n\n- **Vertex JSON Validation Crash:** Prevented `invalid character in header` crashes inside the `/validate` endpoint by creating a native authentication parser that correctly handles Google Identity Service Account JSON flows prior to pinging endpoints (#1153)\n- **Extraneous Payload Rejection:** Globally prevented upstream `400 Bad Request` execution crashes by stripping the non-standard `prompt_cache_retention` attribute forcibly attached by Cursor/Cline IDE engines when targeting strict OpenAI/Anthropic routes (#1154)\n- **Reasoning Content Drop:** Prevented pure reasoning packets, common in advanced fallback models like DeepSeek, from being aborted mid-stream by explicitly adjusting the `Empty Content (502)` circuit breakers to acknowledge `reasoning_content` states as valid (#1155)\n- **Desktop Windows Build Crash:** Fixed `better_sqlite3.node is not a valid Win32 application` preventing OmniRoute Desktop from launching on Windows by properly removing the ABI-mismatched sqlite cache from Next.js standalone and falling back to the cross-compiled Electron equivalent during packager build steps (#1163)\n- **Login Visual Security:** Removed the raw fallback hash dump that artificially rendered underneath the login modal in Docker instances missing `OMNIROUTE_API_KEY_BASE64` flags (#1148)\n\n### 🔧 Maintenance & Dependencies\n\n- **Dependabot Updates:** Safely bumped GitHub Actions `docker/build-push-action` to v7 and `actions/download-artifact` to v8\n- **Electron Updates:** Upgraded desktop wrapper core to Electron `41.2.0` and `electron-builder` to `26.8.1`, incorporating essential V8/Chromium security patches\n- **NPM Package Groups:** Updated `production` and `development` NPM groups to securely handle minor audit warnings and keep toolchains modern\n- **CI/CD Reliability:** Fixed persistent `Snyk` token-absence failures on automated pull requests by appropriately bypassing on dependabot actions\n\n## [3.6.2] — 2026-04-11\n\n### ✨ New Features\n\n- **33 New API Key Providers:** Massive provider expansion adding DeepInfra, Vercel AI Gateway, Lambda AI, SambaNova, nScale, OVHcloud AI, Baseten, PublicAI, Moonshot AI, Meta Llama API, v0 (Vercel), Morph, Featherless AI, FriendliAI, LlamaGate, Galadriel, Weights & Biases Inference, Volcengine, AI21 Labs, Venice.ai, Codestral, Upstage, Maritalk, Xiaomi MiMo, Inference.net, NanoGPT, Predibase, Bytez, Heroku AI, Databricks, Snowflake Cortex, and GigaChat (Sber). OmniRoute now supports **100+ providers** (4 Free + 8 OAuth + 91 API Key + Custom compatible)\n- **Global Email Privacy Toggle:** Added a persistent eye-icon toggle button across all dashboard pages (Providers, Usage Limits, Playground) that reveals or hides masked email addresses. Toggle state is stored in localStorage and synced globally via Zustand store\n- **Documentation Refresh:** Updated README, ARCHITECTURE, FEATURES, AGENTS.md, and API_REFERENCE for v3.6.2 with accurate provider counts (100+), new executor list, and system API documentation\n- **Uninstall Guide:** Created comprehensive `docs/UNINSTALL.md` covering clean uninstallation for all deployment methods (npm, Docker, Electron, source)\n\n### 🐛 Bug Fixes\n\n- **PDF Attachments:** Unlocked deep string object parsing (`geminiHelper`) ensuring Gemini translation successfully passes complex PDF payloads from OpenAI-compatible streams without dropping them silently (#993)\n- **SkillsMP Engine:** Corrected object extraction path mappings inside the API router to fix UI marketplace rendering under Docker/Standalone Node isolated deployments (#988)\n\n---\n\n## [3.6.1] — 2026-04-10\n\n### ✨ New Features\n\n- **OAuth Env Repair Action:** Added a \"Repair env\" button to the OAuth Providers dashboard that detects and restores missing OAuth client IDs from `.env.example` — with timestamped backup and append-only safety. Includes full 33-language i18n support and sanitized API responses (#1116, by @yart)\n\n### 🐛 Bug Fixes\n\n- **i18n: Missing Provider Keys:** Added missing `filterModels`, `modelsActive`, `showModel`, `hideModel` keys across all 32 locale files, fixing runtime `MISSING_MESSAGE` errors in the providers UI. Also cleaned up duplicate keys in `en.json` (#1111, by @rilham97)\n- **GPT-5.4 Routing:** Added missing `targetFormat: \"openai-responses\"` to `gpt-5.4` and `gpt-5.4-mini` models in both the Codex and GitHub Copilot providers, fixing `[400]: model not accessible via /chat/completions` errors (#1114, by @ask33r)\n\n---\n\n## [3.6.0] — 2026-04-10\n\n### ✨ New Features & Analytics\n\n- **Combo Smoke Test:** Raised the default token budget to 2048 to prevent truncation of thinking models during preflight checks, and fully randomized the arithmetic probe prompt to bypass deterministic caching from upstream relays (#1105)\n\n### 🐛 Bug Fixes & Compliance\n\n- **DB Bloat / Row Limits:** Added `CALL_LOGS_TABLE_MAX_ROWS` and `PROXY_LOGS_TABLE_MAX_ROWS` (default: 100,000) to the backend DB compliance cleaner to prevent runaway SQLite growth. Limits are enforced automatically on the TTL cycle (#1104, fixes #1101)\n- **HTML Error Handling:** The router now correctly identifies unexpected HTML responses (e.g. ``) sent by upstream providers (like Azure/Copilot) instead of throwing obscure `Unexpected token '<'` JSON parse errors, bubbling up a clean 502 Bad Gateway (#1104, fixes #1066)\n- **Android/Termux SQLite Native Support:** `better-sqlite3` is now correctly built from source with cross-compilation flags in ARM64 local Termux deployments without failing on missing prebuilt binaries (#1107)\n\n---\n\n## [3.5.9] — 2026-04-09\n\n### ✨ New Features\n\n- **Persistent Combo Ordering:** Drag combo cards by handle to reorder them in the dashboard; order is persisted to SQLite via a new `sort_order` column and `POST /api/combos/reorder` endpoint. Includes DB migration `020_combo_sort_order.sql` and JSON import preservation (#1095)\n- **Sidebar Group Reorder:** Moved \"Logs\" before \"Health\" in the System section and \"Limits & Quotas\" after \"Cache\" in the Primary section for a more logical navigation flow (#1095)\n\n### 🐛 Bug Fixes\n\n- **Stream Failure Surfacing:** Upstream `response.failed` events (e.g. Codex rate-limit errors) are now properly surfaced as non-200 errors instead of being silently swallowed as empty 200 OK streams. Rate-limit failures return HTTP 429 (#1098, closes #1093)\n- **Upstream Model Preservation:** The Responses-to-OpenAI stream translator now preserves the actual upstream model (e.g. `gpt-5.4`) instead of hardcoding a `gpt-4` fallback (#1098, closes #1094)\n- **Docker EXDEV Fix:** `build-next-isolated.mjs` now falls back from `fs.rename()` to `cp/rm` when Docker buildx raises `EXDEV` (cross-device link), unblocking the Docker image publish workflow (#1097)\n- **macOS CLI Path Resolution:** `cliRuntime.ts` resolves symlink parents with `fs.realpath()` to handle macOS `/var` → `/private/var` chains, preventing false `symlink_escape` rejections (#1097)\n- **Request Log Token Layout:** Split token badges into separate Input (Total In, Cache Read, Cache Write) and Output (Total Out, Reasoning) groups for clearer readability; renamed \"Time\" label to \"Completed Time\" (#1096)\n\n---\n\n## [3.5.8] — 2026-04-09\n\n### ✨ New Features & Analytics\n\n- **Analytics Layout Redesign:** Replaced flat metrics with a responsive `CompactStatGrid`, grouping data visually across sections (#1089)\n\n### 🐛 Bug Fixes\n\n- **Build Core:** Force Turbopack cleanup via Prepbulish script to prevent Next.js 16 app/ routing conflicts on runtime.\n- **Provider Quarantine:** Introduces model/provider circuit-breakers with adaptive TTL exponential backoff for recurring upstream errors (#1090)\n- **Oauth Keep-Alive:** Safely protects authenticated active accounts against spontaneous dropping from router due to transient token refresh failures (#1085)\n\n### 🔒 Security & Maintenance\n\n- **Dependabot:** bumped axios from 1.14.0 to 1.15.0 addressing SSRF flags (#1088)\n\n---\n\n## [3.5.7] — 2026-04-09\n\n### 🐛 Bug Fixes & Security\n\n- **Turbopack Standalone Chunks:** Fixed a critical bug in `scripts/prepublish.mjs` where Turbopack chunks missing from the `.next/standalone` trace resulted in a `500 ChunkLoadError` (e.g., `_not-found` page crash) during production deployments via NPM or Docker. Standalone chunks are now explicitly copied and correctly stripped of Turbopack hashes.\n\n---\n\n## [3.5.6] — 2026-04-09\n\n### ✨ New Features\n\n- **Email Privacy Masking:** OAuth account emails are now masked in the provider dashboard (e.g. `di*****@g****.com`) to prevent accidental exposure when sharing screenshots. Full address visible on hover via `title` attribute (#1025).\n- **OpenRouter & GitHub in Embedding/Image Registries:** OpenRouter (3 embedding models, 4 image models) and GitHub Models (2 embedding models via Azure inference) are now first-class entries in the provider registries, enabling their use for `/v1/embeddings` and `/v1/images/generations` (#960).\n- **Model Visibility Toggle & Search Filter:** The provider page model list now includes a real-time search/filter bar and a per-model visibility toggle (👁 icon). Hidden models are grayed out and excluded from the `/v1/models` catalog. An active-count badge (`N/M active`) shows at a glance how many models are enabled (#750).\n- **Chinese Localization (zh-CN):** Added missing translations for Context Relay, Memory, LKGP, and Models.dev sync features, while standardizing terminology across the application (#1079).\n- **Environment Auto-Sync:** Added `sync-env.mjs` to auto-generate and append `.env` from `.env.example` during installation, automatically generating cryptographic secrets on first run.\n- **Source Mode Dashboard Update:** Fixed real-time Source (git-checkout) updating in the dashboard, enabling secure, real-time update pipelines for non-NPM installations.\n\n### 🐛 Bug Fixes & Security\n\n- **Hardcoded Secret Cleanup:** Removed 12 hardcoded OAuth credential fallbacks from the source code, forcing secure reliance on environment variables and resolving static analysis security alerts.\n- **Next.js Security Patch:** Bumped `next` from 16.2.2 to 16.2.3 to resolve critical RSC deserialization RCE vulnerability (SNYK-JS-NEXT-15954202).\n- **Memory/Cache UI Crash:** Added null-safety guards (`?? 0`) to `.toLocaleString()` calls in Memory and Cache dashboard pages, preventing `TypeError` crashes when database tables are empty or contain null numeric values (#1083).\n- **WebSearch tool_choice Translation:** Fixed OpenAI-to-Claude translator dropping `tool_choice` objects with `type: \"function\"` as-is, which Claude rejects. Now properly maps all OpenAI `tool_choice` variants (`function`, `required`, `none`) to Claude-compatible format (`tool`, `any`, `auto`), fixing \"Did 0 searches\" in Claude Code WebSearch (#1072).\n- **Provider Validation baseUrl Override:** Added `baseUrl` passthrough from frontend validation requests to the backend validation endpoint. Chinese-site users of Alibaba Coding Plan (bailian-coding-plan) can now validate API keys against their custom Base URL instead of always hitting the international endpoint (#1078).\n- **Minimax Auth Header:** Switched Minimax provider from `x-api-key` to `Authorization: Bearer` header format, matching the current API spec (#1076).\n- **Native Fetch Fallback:** Added graceful fallback to native `fetch` when the `undici` dispatcher fails, improving resilience in environments where undici is unavailable (#1054).\n- **EPIPE Flood Fix:** Added circuit-breaker logic to prevent EPIPE errors from creating a feedback loop that fills logs at GB/s (#1006).\n- **Qoder PAT Validation:** Improved Qoder Personal Access Token validation with actionable error messages that guide users to the correct token format (#966).\n- **CI/CD Pipeline:** Fixed `check:docs-sync` failure by syncing OpenAPI version to 3.5.6 and finalizing CHANGELOG release heading. Commented out `DATA_DIR` in `.env.example` to prevent E2E test failures in CI runners lacking root permissions.\n\n### 🌍 i18n\n\n- **Auto Language Generation (CI):** Added CI pipeline to auto-generate missing language files and strings via `feat(CI,i18n)` workflow, covering 30+ locales (#1071).\n\n---\n\n## [3.5.5] — 2026-04-08\n\n### ✨ New Features\n\n- **Node.js 24 Compatibility Warning:** Added a proactive version incompatibility warning on the login page to guide users to the stable Node.js 22 LTS, preventing native sqlite binding crashes.\n- **Context Relay Combo Strategy:** Added the new `context-relay` combo strategy with priority-style routing, structured handoff summary generation once quota usage reaches the warning threshold, and handoff injection after the next real account switch.\n- **Global Context Relay Defaults:** Added global Settings defaults plus combo-level configuration for `handoffThreshold`, `handoffModel`, and `handoffProviders`, so new or unconfigured combos can inherit the feature consistently.\n\n### 🐛 Bug Fixes\n\n- **Proxy Connection Healthchecks:** Applied proxy resolution per connection in the sweeping loop (`tokenHealthCheck.ts`) and global provider validation sweeps, resolving Node 22 bypass and improving proxy stability (#1051, #1056, #1061).\n- **Security Vulnerability Remediation:** Resolved multiple CodeQL scanning alerts including SSRF in model sync, insecure randomness in web crypto (`generateSessionId`), and incomplete URL sanitization.\n- **Context Relay Typing & Synchronization:** Reverted out-of-scope test breakages and resolved `handoffProvider` and response `input` extraction payload typing.\n- **Legacy OpenAI-Compatible Responses Routing:** Fixed legacy/imported OpenAI-compatible providers (for example `openai-compatible-sp-openai`) incorrectly routing Chat Completions traffic to `/chat/completions` when the real provider node was configured as `apiType: \"responses\"`. OmniRoute now treats `providerSpecificData.apiType` as authoritative across routing, executors, and translator tools, avoiding false empty-content failures during combo/provider smoke tests (#1069).\n- **Gemini PDF Attachment Integration:** Fixed payload generation and format for parsing `inline_data` and generic base64 sources for deep Gemini PDF routing (#993, #1021).\n- **Vercel AI SDK Fallbacks:** Mapped `max_output_tokens` to `max_tokens` for strict OpenAI-compatible providers, resolving errors from standard AI agents and frameworks (#994).\n- **External Auth & UI Reliability:** Handled null `state` failures in Cline OAuth exchange (#1016), added 3rd-party 400 error patterns to combo fallback (#1024), and resolved desktop sidebar layout and popover overflows (#1039, #1001).\n- **Context Relay In-Flight Deduplication:** Prevented duplicate handoff generation for the same session/combo while an earlier summary request is still in flight.\n- **Context Relay Provider Gating:** Aligned runtime behavior with configuration so explicit `handoffProviders` exclusions, including an empty array, now disable handoff generation as expected.\n\n### 🛠️ Maintenance & Dependabot\n\n- **Updated Sub-dependencies:** Bumped `hono` to `4.12.12` and `@hono/node-server` to `1.19.13` to patch critical security gaps (#1063, #1064, #1067, #1068).\n\n### Dokumentation\n\n- **Documentation Synchronization:** Updated system documentation (README, Architecture, Features, Tools, Troubleshooting) and synced `i18n` configurations to match the v3.5.5 context relay patterns and proxy troubleshooting steps.\n- **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance.\n\n---\n\n## [3.5.4] — 2026-04-07\n\n### ✨ New Features\n\n- **Detailed Token Tracking:** Added granular token breakdown columns (cache read, cache write, reasoning) to call logs with proper null vs zero distinction. Includes DB migration 018 and 5-label UI display per provider capability (#1017 — thanks @rdself).\n- **Legacy JSON Config Import/Export:** Restored JSON-based settings export and import for migration from legacy 9router configurations. Security-hardened with Zero-Trust redaction of passwords and `requireLogin` fields, and automatic pre-import database backups (#1012 — thanks @luandiasrj).\n- **Non-Stream Aliases:** Added API support for explicit non-streaming aliases (`non_stream`, `disable_stream`, `disable_streaming`, `streaming=false`), normalized at the boundary before provider translation (#1036 — thanks @wlfonseca).\n- **Russian Dashboard Localization:** Comprehensive Russian translation for the dashboard UI, including fixes for 2 Ukrainian locale keys (#1003 — thanks @mercs2910).\n\n### 🐛 Bug Fixes\n\n- **Anthropic Streaming Input Undercount:** Fixed a critical bug where Anthropic streaming `prompt_tokens` only reported non-cached tokens (e.g., `in=3` when actual total was 113,616). Cache tokens are now summed into prompt_tokens during streaming (#1017).\n- **Built-in Responses API Tool Types:** Preserved built-in Responses API tools (`web_search`, `file_search`, `computer`, `code_interpreter`, `image_generation`) from being silently stripped by the empty-name tool filter — these tools carry no `.name` field (#1014 — thanks @rdself).\n- **Cursor/Codex Responses Compatibility:** Fixed empty output in Cursor when using Codex models by hoisting system input items to `instructions`, sanitizing invalid tool names, and detecting Responses-format payloads on chat/completions endpoint (#1002 — thanks @mercs2910).\n- **OAuth Token Expiry Display:** Fixed OAuth connections showing \"expired\" badge even with valid tokens by reading `tokenExpiresAt` (updated on refresh) instead of `expiresAt` (original grant timestamp) (#1032 — thanks @tombii).\n- **Codex Fast-Tier Copy:** Corrected dashboard settings copy from `service_tier=fast` to `service_tier=priority`, matching the actual Codex wire format (#1045 — thanks @kfiramar).\n- **macOS Desktop App Startup:** Stabilized packaged macOS app launch by excluding desktop artifacts from the standalone bundle and improving launch path detection (#1004 — thanks @mercs2910).\n- **macOS Sidebar Layout:** Fixed macOS traffic light overlap, sidebar spacing, and button overflow in the Electron desktop app (#1001 — thanks @mercs2910).\n\n### ⚡ Performance\n\n- **Analytics Page Load:** Dramatically reduced analytics page load times (30s→1-2s for 50K entries) via date-filtered DB queries, parallel `Promise.all()` cost calculations, and merged 6 COUNT queries into a single CASE WHEN aggregate (#1038 — thanks @oyi77).\n\n### 🔒 Security & Dependencies\n\n- **Node Base Image:** Upgraded Docker base from `22-bookworm-slim` to `22.22.2-trixie-slim` (#1011 — Snyk).\n- **Production Dependencies:** Bumped 5 production dependencies (#1044 — Dependabot).\n- **Vite:** Bumped from 8.0.3 to 8.0.5 (#1031 — Dependabot).\n- **Development Dependencies:** Bumped 4 development dependencies (#1030 — Dependabot).\n\n### 🧪 Tests\n\n- **Token Accounting Tests:** Added 18 new unit tests covering detailed token breakdown, null vs zero semantics, per-provider token extraction, and Anthropic streaming input fix (#1017).\n- **Built-in Tool Tests:** Added 3 new test cases for built-in Responses API tool type preservation (#1014).\n- **ChatCore Sanitization:** Updated sanitization tests to accommodate Responses format detection (PR #1002) and built-in tool preservation (PR #1014).\n\n### 🛠️ Maintenance\n\n- **PR Workflow:** Updated `/review-prs` workflow to merge PRs into the release branch (`release/vX.Y.Z`) instead of directly into `main`, ensuring proper pre-release staging.\n\n### Coverage\n\n- **2537 tests, 2532 passing** — Statement coverage: 91.95%, Branch coverage: 78.79%, Function coverage: 93.19%\n\n## [3.5.3] - 2026-04-07\n\n### Sicherheit\n\n- **Vulnerabilities:** Fully remediated 12 High-Severity CodeQL vulnerabilities by migrating from Math.random to `crypto.randomUUID()`, wrapping SSE injection points with aggressive backslash escaping, sanitizing trailing HTTP fragments, and enforcing rigid SSRF HTTP verification schemes across internal routes.\n- **Dependencies:** Upgraded Next.js to `^16.2.2` and Vite to `>=8.0.5` resolving critical DoS, arbitrary file reads and CSRF vectors in the build/server environments.\n\n### Fixed\n\n- **E2E Stability:** Eliminated extreme CI unreliability and transient test timeouts (Playwright) by propagating internal standalone `_next/static` assets properly and refactoring deep UI interactions inside defensive `expect().toPass()` loops.\n- **Middleware:** Resolved infinite redirect loop on dashboard for fresh instances when requireLogin is disabled.\n- **Core Fallbacks:** Preserved primary failure contexts and enhanced Edge-case error handling pipelines across chat and fallback loops.\n- **Proxy/Hooks:** Optimized local git hooks, normalized token coverage endpoints into `/coverage`, and guarded GLM region lookups.\n\n### 🛠️ Maintenance\n\n- **CI/CD Stabilization:** Prevented random GitHub Runner freezes by decoupling sharded processes, adjusting test concurrencies, unref-ing active connections on server teardown, and strictly capping job timeout durations.\n\n### Dokumentation\n\n- **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned).\n\n### Coverage\n\n- **Testing:** Consolidated the workspace test coverage framework hitting 92.1% statement line coverage, with new rigid unit-tests matching API key policies and tool scopes.\n\n---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n- **Qoder API Native Integration:** Completely refactored the Qoder Executor to bypass the legacy COSY AES/RSA encryption algorithm, routing directly into the native DashScope OpenAi-compatible URL. Eliminates complex dependencies on Node `crypto` modules while improving stream fidelity.\n- **Resilience Engine Overhaul:** Integrated context overflow graceful fallbacks, proactive OAuth token detection, and empty-content emission prevention (#990).\n- **Context-Optimized Routing Strategy:** Added new intelligent routing capability to natively maximize context windows in automated combo deployments (#990).\n\n### 🐛 Bug Fixes\n\n- **Responses API Stream Corruption:** Fixed deep-cloning corruption where Anthropic/OpenAI translation boundaries stripped `response.` specific SSE prefixes from streaming boundaries (#992).\n- **Claude Cache Passthrough Alignment:** Aligned CC-Compatible cache markers consistently with upstream Client Pass-Through mode preserving prompt caching.\n- **Turbopack Memory Leak:** Pinned Next.js to strict `16.0.10` preventing memory leaks and build staleness from recent upstream Turbopack hashed module regressions (#987).\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **Models.dev Integration:** Integrated models.dev as the authoritative runtime source for model pricing, capabilities, and specifications, overriding hardcoded prices. Includes a settings UI to manage sync intervals, translation strings for all 30 languages, and robust test coverage.\n- **Provider Native Capabilities:** Added support for declaring and checking native API features (e.g. `systemInstructions_supported`) preventing failures by sanitizing invalid roles. Currently configured for Gemini Base and Antigravity OAuth providers.\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Sicherheit\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Funktionen\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Sicherheit\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicherheit\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicherheit\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Dokumentation\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Dokumentation\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funktionen\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funktionen\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funktionen\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicherheit\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funktionen\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funktionen\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funktionen\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funktionen\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funktionen\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funktionen\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funktionen\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funktionen\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicherheit\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\bany\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funktionen\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funktionen\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funktionen\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funktionen\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funktionen\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funktionen\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Dokumentation\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funktionen\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "fa886231d331109bf2fd260dcff72880fc2acca0": {"t": 1785765403.2953627, "n": 194029, "h": "28698e8c28bc1fa7", "c": "# Changelog (Deutsch)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.5.3] - 2026-04-05\n\n### Fixed\n\n-**Middleware:**Endlosumleitungsschleife im Dashboard für neue Instanzen behoben, wenn requireLogin deaktiviert ist.---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n-**Native Qoder API-Integration:**Der Qoder Executor wurde komplett überarbeitet, um den alten COSY AES/RSA-Verschlüsselungsalgorithmus zu umgehen und direkt in die native DashScope OpenAi-kompatible URL weiterzuleiten. Beseitigt komplexe Abhängigkeiten von Node-Kryptomodulen und verbessert gleichzeitig die Stream-Wiedergabetreue. -**Resilience Engine-Überarbeitung:**Integrierte kontextüberlauffreundliche Fallbacks, proaktive OAuth-Token-Erkennung und Verhinderung der Emission leerer Inhalte (#990). -**Kontextoptimierte Routing-Strategie:**Neue intelligente Routing-Funktion hinzugefügt, um Kontextfenster in automatisierten Kombinationsbereitstellungen nativ zu maximieren (#990).### 🐛 Bug Fixes\n\n-**Responses-API-Stream-Beschädigung:**Deep-Cloning-Beschädigung behoben, bei der Anthropic/OpenAI-Übersetzungsgrenzen „response.“-spezifische SSE-Präfixe von Streaming-Grenzen entfernt haben (#992). -**Claude-Cache-Passthrough-Ausrichtung:**CC-kompatible Cache-Marker wurden konsistent mit dem Upstream-Client-Passthrough-Modus ausgerichtet, um das Prompt-Caching beizubehalten. -**Turbopack-Speicherleck:**Next.js wurde an strikt „16.0.10“ angeheftet, um Speicherlecks und Build-Veraltung aufgrund der jüngsten Regressionen des Upstream-Turbopack-Hash-Moduls zu verhindern (#987).---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n-**Models.dev-Integration:**Integriert models.dev als maßgebliche Laufzeitquelle für Modellpreise, Funktionen und Spezifikationen und überschreibt fest codierte Preise. Enthält eine Benutzeroberfläche für Einstellungen zur Verwaltung von Synchronisierungsintervallen, Übersetzungszeichenfolgen für alle 30 Sprachen und eine robuste Testabdeckung. -**Native Funktionen des Anbieters:**Unterstützung für die Deklaration und Überprüfung nativer API-Funktionen (z. B. „systemInstructions_supported“) hinzugefügt, um Fehler durch Bereinigung ungültiger Rollen zu verhindern. Derzeit für Gemini Base- und Antigravity-OAuth-Anbieter konfiguriert. -**Erweiterte API-Provider-Einstellungen:**Benutzerdefinierte „User-Agent“-Überschreibungen pro Verbindung für API-Schlüssel-Provider-Verbindungen hinzugefügt. Die Überschreibung wird in „providerSpecificData.customUserAgent“ gespeichert und gilt jetzt für Validierungstests und Upstream-Ausführungsanforderungen.### 🐛 Bug Fixes\n\n-**Qwen OAuth-Zuverlässigkeit:**Es wurden eine Reihe von OAuth-Integrationsproblemen behoben, darunter ein 400-Bad-Request-Blocker für abgelaufene Token, eine Fallback-Generierung für das Parsen von OIDC-Access_token-Eigenschaften, wenn „id_token“ weggelassen wird, Modellkatalog-Erkennungsfehler und eine strikte Filterung von „X-Dashscope-\\*“-Headern, um eine 400-Ablehnung von OpenAI-kompatiblen Endpunkten zu vermeiden.## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n-**Auto-Combo & Routing:**Native CRUD-Lebenszyklusintegration für die erweiterte Auto-Combo-Engine abgeschlossen (#955). -**Kernoperationen:**Fehlende Übersetzungen für neue native Auto-Combos-Optionen behoben (#955). -**Sicherheitsvalidierung:**SQLite-Auto-Backup-Aufgaben wurden nativ während der CI-Ausführung des Komponententests deaktiviert, um hängende Speicherlecks in der Knoten-22-Ereignisschleife explizit zu beheben (#956). -**Ökosystem-Proxys:**Explizite Integrationszuordnungsmodell-Synchronisierungsplaner, OAuth-Zyklen und Token-Check-Aktualisierungen wurden sicher über die nativen System-Upstream-Proxys von OmniRoute abgeschlossen (#953). -**MCP-Erweiterbarkeit:**Das neue MCP-Framework-Tool „omniroute_web_search“ wurde aus der Betaphase in Produktionsschemata hinzugefügt und erfolgreich registriert (#951). -**Token-Pufferlogik:**Laufzeitkonfigurationsgrenzen hinzugefügt, die konfigurierbare Eingabe-/Ausgabe-Token-Puffer für präzise Nutzungsverfolgungsmetriken erweitern (#959).### 🐛 Bug Fixes\n\n-**CodeQL-Remediation:**Vollständig aufgelöste und gesicherte kritische String-Indizierungsvorgänge verhindern Server-Side Request Forgery (SSRF)-Arrays, die Heuristiken zusammen mit polynomialem algorithmischem Backtracking (ReDoS) in Deep-Proxy-Dispatcher-Modulen indizieren. -**Krypto-Hashes:**Schwache, nicht verifizierte Legacy-OAuth-1.0-Hashes wurden durch robuste HMAC-SHA-256-Standard-Validierungsprimitive ersetzt, um strenge Zugriffskontrollen zu gewährleisten. -**API-Grenzschutz:**Korrekt überprüfte und zugeordnete strukturelle Routenschutzmaßnahmen, die die strikte „isAuthenticated()“-Middleware-Logik durchsetzen, die neuere dynamische Endpunkte abdeckt und auf die Manipulation von Einstellungen und das Laden nativer Fähigkeiten abzielt. -**CLI-Ökosystemkompatibilität:**Defekte native Laufzeit-Parser-Bindungen behoben, die „where“-Umgebungsdetektoren ausschließlich über „.cmd/.exe“-Randfällen ordnungsgemäß zum Absturz brachten, für externe Plugins (#969). -**Cache-Architektur:**Das Caching der Layoutstruktur des Dashboards für genaue Analyse- und Systemeinstellungen wurde überarbeitet, um stabile Rehydrations-Persistenzzyklen aufrechtzuerhalten und visuelle, nicht ausgerichtete Zustandsblitze zu beheben (#952). -**Claude-Caching-Standards:**Normalisierte und genau strikt erhaltene kritische ephemere Blockmarkierungen „ephemere“ Caching-TTL-Aufträge für Downstream-Knoten, die eine saubere Zuordnung standardkompatibler CC-Anfragen ohne verlorene Metriken erzwingen (#948). -**Interne Aliase-Authentifizierung:**Vereinfachte interne Laufzeitzuordnungen, die Codex-Anmeldeinformations-Payload-Suchen innerhalb globaler Übersetzungsparameter normalisieren und 401 nicht authentifizierte Drops beheben (#958).### 🛠️ Maintenance\n\n-**UI-Erkennbarkeit:**Korrekt angepasste Layout-Kategorisierungen, die die Logik der Free-Tier-Anbieter explizit trennen und die UX-Sortierabläufe innerhalb der allgemeinen API-Registrierungsseiten verbessern (#950). -**Bereitstellungstopologie:**Einheitliche Docker-Bereitstellungsartefakte, die sicherstellen, dass das Stammverzeichnis „fly.toml“ sofort mit den erwarteten Cloud-Instanzparametern übereinstimmt und automatisch automatisierte Bereitstellungen ordnungsgemäß skaliert. -**Entwicklungstools:**Entkoppelte „LKGP“-Laufzeitparameter in explizite DB-Layer-Abstraktions-Caching-Dienstprogramme, um eine strikte Testisolationsabdeckung für Kern-Caching-Layer sicher zu gewährleisten.---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n-**Dashboard Auto-Combo Panel:**Die Benutzeroberfläche „/dashboard/auto-combo“ wurde komplett überarbeitet, um eine nahtlose Integration mit nativen Dashboard-Karten und standardisierten visuellen Auffüllungen/Kopfzeilen zu ermöglichen. Dynamische visuelle Fortschrittsbalken hinzugefügt, die die Gewichtungsmechanismen der Modellauswahl abbilden. -**Synchronisierung der Routing-Einstellungen:**Vollständig verfügbar gemachte erweiterte Routing-„Prioritäts“- und „gewichtete“ Schema-Ziele intern innerhalb der Fallback-Listen für globale Einstellungen.### Bug Fixes\n\n-**Memory & Skills Locale Nodes:**Leere Rendering-Tags für Memory- und Skills-Optionen direkt in globalen Einstellungsansichten behoben, indem alle „settings.\\*“-Zuordnungswerte intern mit „en.json“ verbunden wurden (auch implizit für Kreuzübersetzungstools zugeordnet).### Internal Integrations\n\n- Integrierter PR #946 – Fix: Claude-Code-Kompatibilität bei der Antwortkonvertierung beibehalten\n- Integrierte PR #944 – fix(gemini): Gedankensignaturen bei Antigravitations-Tool-Aufrufen beibehalten\n – Integrierter PR #943 – Fix: GitHub Copilot-Körper wiederherstellen\n- Integrierter PR #942 – CC-kompatible Cache-Marker reparieren\n – Integrierter PR #941 – Refactor(auth): NVIDIA-Alias-Suche verbessern + LKGP-Fehlerprotokollierung hinzufügen\n- Integrierter PR #939 – Wiederherstellung der Claude OAuth Localhost-Callback-Verarbeitung\n- _(Hinweis: PR #934 wurde im 3.4.9-Zyklus weggelassen, um Kernkonfliktregressionen zu verhindern)_---\n\n## [3.4.8] — 2026-04-03\n\n### Sicherheit\n\n- Alle ausstehenden Github Advanced Security (CodeQL)-Ergebnisse und Dependabot-Warnungen wurden vollständig behoben.\n – Behebung unsicherer Zufallsschwachstellen durch Migration von „Math.random“ zu „crypto.randomUUID()“.\n- Gesicherte Shell-Befehle in automatisierten Skripten durch String-Injection.\n – Anfällige, katastrophale Backtracking-RegEx-Parsingmuster in Chat-/Übersetzungspipelines wurden migriert.\n – Verbesserte Ausgabebereinigungskontrollen innerhalb der React-UI-Komponenten und der SSE-Tag-Injektion (Server Sent Events).---\n\n## [3.4.7] — 2026-04-03\n\n### Funktionen\n\n- Knoten „Kryptografie“ zu Überwachung und MCP-Gesundheitsprüfungen hinzugefügt (#798)\n- Gehärtete Modell-Katalog-Routenberechtigungszuordnung (`/models`) (#781)### Bug Fixes\n\n– Behoben: Claude OAuth-Token-Aktualisierungen führten dazu, dass Cache-Kontexte nicht erhalten blieben (#937)\n– Fehler bei CC-kompatiblen Anbietern behoben, die dazu führten, dass zwischengespeicherte Modelle nicht erreichbar waren (#937)\n– GitHub Executor-Fehler im Zusammenhang mit ungültigen Kontext-Arrays behoben (#937)\n– Fehler bei der Integritätsprüfung der NPM-installierten CLI-Tools unter Windows behoben (#935)\n– Problem behoben, bei dem bei der Payload-Übersetzung gültige Inhalte aufgrund ungültiger API-Felder verloren gingen (#927)\n– Laufzeitabsturz in Knoten 25 bezüglich der API-Schlüsselausführung behoben (#867)\n\n- MCP-Standalone-Modulauflösung („ERR_MODULE_NOT_FOUND“) über „esbuild“ behoben (#936)\n- Nicht übereinstimmende Alias-Auflösung für NVIDIA NIM-Routing-Anmeldeinformationen behoben (#931)### Sicherheit\n\n– Sicherer, strikter Schutz der Eingabegrenzen gegen rohe „Shell: True“-Remotecode-Ausführungsinjektionen hinzugefügt.---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n-**Anbieter:**Registrierte neue Bild-, Video- und Audio-Generierungsanbieter aus der von der Community angeforderten Liste (#926). -**Dashboard-Benutzeroberfläche:**Eigenständige Seitenleistennavigation für die neuen Module „Speicher“ und „Fähigkeiten“ hinzugefügt (#926). -**i18n:**Übersetzungszeichenfolgen und Layoutzuordnungen in 30 Sprachen für die Namespaces „Memory“ und „Skills“ hinzugefügt.### 🐛 Bug Fixes\n\n-**Belastbarkeit:**Es wurde verhindert, dass der Proxy-Leistungsschalter auf unbestimmte Zeit im OFFEN-Zustand hängen bleibt, indem direkte Übergänge in den GESCHLOSSEN-Zustand innerhalb von Fallback-Kombinationspfaden verarbeitet wurden (#930). -**Protokollübersetzung:**Der Streaming-Transformer wurde gepatcht, um Antwortblöcke basierend auf dem erwarteten _Quell_-Protokoll und nicht auf dem _Ziel_-Protokoll des Anbieters zu bereinigen. Dadurch wurde behoben, dass in OpenAI-Nutzlasten verpackte Anthropics-Modelle Claude Code abstürzen ließen (#929). -**API-Spezifikationen und Gemini:**Das Parsen von „thought_signature“ in den „openai-to-gemini“- und „claude-to-gemini“-Übersetzern wurde korrigiert, wodurch HTTP 400-Fehler bei allen Gemini 3 API-Toolaufrufen verhindert wurden. -**Anbieter:**Nicht OpenAI-kompatible Endpunkte wurden bereinigt, wodurch gültige Upstream-Verbindungen verhindert wurden (#926). -**Cache-Trends:**Eine ungültige Datenübereinstimmung bei der Eigenschaftszuordnung wurde behoben, die zum Absturz von Cache-Trends-UI-Diagrammen führte, und es wurden redundante Cache-Metrik-Widgets extrahiert (#926).---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n-**Integration des CLIProxyAPI-Ökosystems:**Der „cliproxyapi“-Executor mit integriertem Caching und Proxy-Routing auf Modulebene hinzugefügt. Einführung eines umfassenden Versionsmanager-Dienstes, um den Zustand automatisch zu testen, Binärdateien von GitHub herunterzuladen, isolierte Hintergrundprozesse zu erzeugen und den Lebenszyklus externer CLI-Tools direkt über die Benutzeroberfläche sauber zu verwalten. Enthält DB-Tabellen für die Proxy-Konfiguration, um das automatische SSRF-gesteuerte Cross-Routing externer OpenAI-Anfragen über die lokale CLI-Tool-Ebene zu ermöglichen (#914, #915, #916). -**Qoder PAT-Unterstützung:**Unterstützung für integrierte Personal Access Tokens (PAT) direkt über den lokalen „qodercli“-Transport anstelle von alten Remote-„.cn“-Browserkonfigurationen (#913). -**Gemini 3.1 Pro Preview (GitHub):**Unterstützung des kanonischen expliziten Modells „gemini-3.1-pro-preview“ nativ im GitHub Copilot-Anbieter hinzugefügt, während ältere Routing-Aliase erhalten bleiben (#924).### 🐛 Bug Fixes\n\n-**GitHub Copilot-Token-Stabilität:**Die Copilot-Token-Aktualisierungsschleife wurde repariert, in der veraltete Token nicht tief in die Datenbank eingebunden wurden, und „reasoning_text“-Felder wurden entfernt, die nachgelagerte Anthropic-Blockkonvertierungen für Multi-Turn-Chats schwerwiegend unterbrachen (#923). -**Globale Timeout-Matrix:**Zentralisierte und parametrisierte Anforderungs-Timeouts explizit von „REQUEST_TIMEOUT_MS“, um zu verhindern, dass versteckte (~300 s) Standard-Abrufpuffer vorzeitig langlebige SSE-Streaming-Antworten von Heavy Reasoning-Modellen abschneiden (#918). -**Cloudflare Quick Tunnels-Status:**Es wurde eine schwerwiegende Statusinkonsistenz behoben, bei der neu gestartete OmniRoute-Instanzen zerstörte Tunnel fälschlicherweise als aktiv anzeigten und das Cloudflared-Tunneling standardmäßig auf „HTTP/2“ setzte, um UDP-Empfangspufferprotokoll-Spam zu verhindern (#925). -**Überarbeitung der i18n-Übersetzung (Tschechisch und Hindi):**Hindi-Code von VERALTET „in.json“ in kanonisches „hi.json“ korrigiert, tschechische Textzuordnungen überarbeitet, „untranslatable-keys.json“ extrahiert, um CI/CD-Falsch-Positiv-Validierungen zu korrigieren, und umfassende „I18N.md“-Dokumente als Leitfaden für Übersetzer erstellt (#912). -**Wiederherstellung des Token-Anbieters:**Behoben, dass Qwen bestimmte „resourceUrl“-Endpunkte nach der automatischen Aktualisierung von Integritätsprüfungs-Token aufgrund fehlender DB-Deep-Merges verlor (#917). -**CC-kompatibles UX & Streaming:**Die Aktionen „CC/OpenAI/Anthropic-kompatibel hinzufügen“ rund um die Anthropic-UI-Behandlung wurden vereinheitlicht, CC-kompatible Upstream-Anfragen zur Verwendung von SSE gezwungen, während weiterhin Streaming- oder Nicht-Streaming-Antworten basierend auf der Client-Anfrage zurückgegeben wurden, die CC-Modelllistenkonfiguration/-importunterstützung wurde zugunsten eines expliziten Fehlers bei der Auflistung nicht unterstützter Modelle entfernt und CC-kompatible verfügbare Modelle wurden so gestaltet, dass sie die OAuth-Claude-Code-Registrierungsliste widerspiegeln (#921).---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n-**Responses API Token Reporting:**Gibt „response.completed“ mit korrekten „input_tokens“/„output_tokens“-Feldern für Codex-CLI-Clients aus, wodurch die Anzeige der Token-Nutzung korrigiert wird (#909 – danke @christopher-s). -**SQLite WAL-Prüfpunkt beim Herunterfahren:**Flush WAL-Änderungen in der primären Datenbankdatei während des ordnungsgemäßen Herunterfahrens/Neustarts, um Datenverlust beim Stoppen des Docker-Containers zu verhindern (#905 – danke @rdself). -**Graceful Shutdown Signal:**Die Routen „/api/restart“ und „/api/shutdown“ wurden von „process.exit(0)“ in „process.kill(SIGTERM)“ geändert, um sicherzustellen, dass der Shutdown-Handler vor dem Beenden ausgeführt wird. -**Docker Stop Grace Period:**„stop_grace_period: 40s“ zu Docker Compose-Dateien und „--stop-timeout 40“ zu Docker-Ausführungsbeispielen hinzugefügt.### 🛠️ Maintenance\n\n- 5 gelöste/keine Fehler behobene Probleme (Nr. 872, Nr. 814, Nr. 816, Nr. 890, Nr. 877).\n- 6 Probleme mit Bedarfsinformationsanfragen untersucht (Nr. 892, Nr. 887, Nr. 886, Nr. 865, Nr. 895, Nr. 870).\n – Auf das CLI-Erkennungs-Tracking-Problem (#863) mit Anleitung für Mitwirkende reagiert.---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n-**Antigravity Memory & Skills:**Remote-Speicher- und Skills-Injektion für den Antigravity-Anbieter auf Proxy-Netzwerkebene abgeschlossen. -**Claude Code-Kompatibilität:**Eine nativ versteckte Kompatibilitätsbrücke für Claude Code erstellt, die Tools und Formatierungen sauber weiterleitet. -**Web Search MCP:**Das Tool „omniroute_web_search“ mit dem Bereich „execute:search“ hinzugefügt. -**Cache-Komponenten:**Dynamische Cache-Komponenten mithilfe von TDD implementiert. -**Benutzeroberfläche und Anpassung:**Unterstützung für benutzerdefinierte Favicons, Registerkarten für das Erscheinungsbild, kabelgebundenes Whitelabeling in der Seitenleiste und hinzugefügte Windsurf-Anleitungsschritte in allen 33 Sprachen hinzugefügt. -**Protokollaufbewahrung:**Native einheitliche Aufbewahrung von Anforderungsprotokollen und Artefakten. -**Modellverbesserungen:**Explizite „contextLength“ für alle Opencode-Zen-Modelle hinzugefügt. -**i18n & Übersetzungen:**33 Sprachübersetzungen nativ integriert, einschließlich Platzhalter-CI-Validierungen und chinesischer Dokumentationsaktualisierungen (#873, #869).### 🐛 Bug Fixes\n\n-**Qwen OAuth-Zuordnung:**Die Abhängigkeit von „id_token“ wurde auf „access_token“ zurückgesetzt und die dynamische API-Endpunktinjektion „resource_url“ für ordnungsgemäßes regionales Routing aktiviert (#900). -**Modellsynchronisierungs-Engine:**Die strenge interne Anbieter-ID wurde in den Synchronisierungsroutinen „getCustomModels()“ anstelle des UI-Kanal-Alias-Formats gespeichert, um Fehler beim Einfügen des SQLite-Katalogs zu verhindern (#903). -**Claude Code & Codex:**Standardisierte Nicht-Streaming-Leerantworten auf Anthropic-formatierte „(leere Antwort)“, um CLI-Proxy-Abstürze zu verhindern (#866). -**CC-kompatibles Routing:**Doppelte „/v1“-Endpunktkollision während der Pfadverkettung für generische Claude-Code-Gateways behoben (#904). -**Antigravity-Dashboards:**Modelle mit unbegrenztem Kontingent wurden daran gehindert, sich fälschlicherweise als ausgeschöpfte „100 %-Nutzung“-Grenzzustände in der Benutzeroberfläche der Anbieternutzung zu registrieren (#857). -**Claude Image Passthrough:**Problem behoben, bei dem bei Claude-Modellen Bildblock-Passthroughs fehlten (#898). -**Gemini-CLI-Routing:**403-Autorisierungssperren und Probleme mit der Anhäufung von Inhalten wurden durch Aktualisieren der Projekt-ID über „loadCodeAssist“ behoben (#868). -**Antigravitationsstabilität:**Modellzugriffslisten korrigiert, 404-Sperrungen erzwungen, 429-Kaskaden behoben, die Standardverbindungen sperren, und „gemini-3.1-pro“-Ausgabetokens begrenzt (#885). -**Provider-Synchronisierungsrhythmus:**Der Provider begrenzt den Synchronisierungsrhythmus über den internen Planer (#888). -**Dashboard-Optimierung:**Das Einfrieren der Benutzeroberfläche „/dashboard/limits“ bei der Verarbeitung von mehr als 70 Konten über Chunk-Parallelisierung wurde behoben (#784). -**SSRF-Härtung:**Strenge SSRF-IP-Bereichsfilterung erzwungen und die Loopback-Schnittstelle „::1“ blockiert. -**MIME-Typen:**„mime_type“ wurde auf „snake_case“ standardisiert, um den Gemini-API-Spezifikationen zu entsprechen. -**CI-Stabilisierung:**Fehler bei Analyse-/Einstellungen-Playwright-Selektoren und Anforderungszusicherungen wurden behoben, sodass GitHub Actions E2E-Ausführungen zuverlässig über lokalisierte Benutzeroberflächen und schalterbasierte Steuerelemente laufen. -**Deterministische Tests:**Datumsabhängige Kontingentfixierungen wurden aus Copilot-Nutzungstests entfernt und Idempotenz-/Modellkatalogtests an das zusammengeführte Laufzeitverhalten angepasst. -**MCP-Typhärtung:**Explizite Null-Budget-Regressionen „beliebig“ aus dem MCP-Server-Tool-Registrierungspfad entfernt. -**Modellsynchronisierungs-Engine:**Destruktive „Ersetzen“-Überschreibungen wurden umgangen, wenn die automatische Synchronisierung des Anbieters eine leere Modellliste ergibt, wodurch die Stabilität für dynamische Kataloge gewahrt bleibt (#899).### 🛠️ Maintenance\n\n-**Pipeline-Protokollierung:**Pipeline-Protokollierungsartefakte verfeinert und Aufbewahrungsobergrenzen erzwungen (#880). -**AGENTS.md Überarbeitung:**Komprimiert von 297→153 Zeilen. Build-/Test-/Stilrichtlinien, Code-Workflows (Prettier, TypeScript, ESLint) und gekürzte ausführliche Tabellen hinzugefügt (#882). -**Release-Branch-Integration:**Konsolidierte die aktiven Feature-Branches in „Release/v3.4.2“ über dem aktuellen „Main“ und validierte den Branch mit Lint-, Unit-, Coverage-, Build- und CI-Modus-E2E-Läufen. -**Testen:**Vitest-Konfiguration für Komponententests und Playwright-Spezifikationen für das Umschalten von Einstellungen hinzugefügt. -**Dokumentaktualisierungen:**Root-Readmes erweitert, chinesische Dokumente nativ übersetzt und veraltete Dateien bereinigt.## [3.4.1] - 2026-03-31\n\n> [!WARNUNG]\n> **BRECHENDE ÄNDERUNG: Anforderungsprotokollierung, Aufbewahrung und Protokollierungsumgebungsvariablen wurden neu gestaltet.**\n> Beim ersten Start nach dem Upgrade archiviert OmniRoute Legacy-Anforderungsprotokolle aus „DATA_DIR/logs/“, Legacy „DATA_DIR/call_logs/“ und „DATA_DIR/log.txt“ in „DATA_DIR/log_archives/\\*.zip“, entfernt dann das veraltete Layout und wechselt zum neuen einheitlichen Artefaktformat unter „DATA_DIR/call_logs/“.### ✨ New Features\n\n-**.ENV-Migrationsdienstprogramm:**Enthält „scripts/migrate-env.mjs“, um „“ gebunden sind, wenn der eingeschränkte Zugriff aktiviert ist (#781) -**Qoder-Integration:**Native Integration für Qoder AI, die die alten iFlow-Plattformzuordnungen nativ ersetzt (#660) -**Prompt-Cache-Tracking:**Tracking-Funktionen und Frontend-Visualisierung (Statistikkarte) für semantisches und promptes Caching in der Dashboard-Benutzeroberfläche hinzugefügt### 🐛 Bug Fixes\n\n-**Cache-Dashboard-Größe:**Die UI-Layoutgrößen und Kontext-Header für die erweiterten Cache-Seiten wurden verbessert (#835) -**Sichtbarkeit der Debug-Seitenleiste:**Es wurde ein Problem behoben, bei dem der Debug-Schalter die Debug-Details der Seitenleiste nicht korrekt anzeigte/ausblendete (#834) -**Präfix des Gemini-Modells:**Der Namespace-Fallback wurde geändert, um ordnungsgemäß über „gemini-cli/“ statt „gc/“ weiterzuleiten, um die Upstream-Spezifikationen zu berücksichtigen (#831) -**OpenRouter-Synchronisierung:**Verbesserte Kompatibilitätssynchronisierung, um den verfügbaren Modellkatalog automatisch korrekt von OpenRouter zu übernehmen (#830) -**Zuordnung von Streaming-Nutzlasten:**Durch die Reserialisierung von Begründungsfeldern werden Konflikt-Aliaspfade nativ aufgelöst, wenn die Ausgabe an Edge-Geräte gestreamt wird---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n-**OpenCode Config:**Generierte „opencode.json“ wurde umstrukturiert, um das datensatzbasierte Schema „@ai-sdk/openai-kompatible“ mit „Optionen“ und „Modellen“ als Objektzuordnungen anstelle von flachen Arrays zu verwenden, wodurch Fehler bei der Konfigurationsvalidierung behoben wurden (#816) -**i18n Fehlende Schlüssel:**Fehlender Übersetzungsschlüssel „cloudflaredUrlNotice“ in allen 30 Sprachdateien hinzugefügt, um Konsolenfehler „MISSING_MESSAGE“ auf der Endpunktseite zu verhindern (#823)---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n-**Token-Buchhaltung:**Eingebundene Prompt-Cache-Tokens sicher in die Berechnungen der historischen Nutzungseingaben für korrekte Kontingentabzüge (PR #822) -**Combo-Test-Probes:**Fehlnegative Ergebnisse der Combo-Testlogik wurden behoben, indem das Parsing für Antworten, die nur auf Begründungen basieren, aufgelöst wurde, und eine massive Parallelisierung über Promise.all wurde ermöglicht (PR #828). -**Docker Quick Tunnels:**Eingebettete erforderliche CA-Zertifikate in den Basis-Laufzeitcontainer, um Cloudflared-TLS-Startfehler zu beheben und aufgetretene Standardausgabe-Netzwerkfehler zu ersetzen, die generische Exit-Codes ersetzen (PR #829)---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n-**Gemini-Kontingentverfolgung:**Gemini-CLI-Kontingentverfolgung in Echtzeit über die „retrieveUserQuota“-API hinzugefügt (PR #825) -**Cache-Dashboard:**Das Cache-Dashboard wurde erweitert, um sofortige Cache-Metriken, 24-Stunden-Trends und geschätzte Kosteneinsparungen anzuzeigen (PR #824)### 🐛 Bug Fixes\n\n-**Benutzererfahrung:**Aufdringliche, automatisch öffnende OAuth-Modalschleifen auf unfruchtbaren Anbieterdetailseiten entfernt (PR #820) -**Abhängigkeitsaktualisierungen:**Abhängigkeiten für Entwicklungs- und Produktionsbäume, einschließlich Next.js 16.2.1, Recharts und TailwindCSS 4.2.2, wurden verschoben und gesperrt (PR #826, #827)---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n-**A2A-Workflows:**Deterministischer FSM-Orchestrator für mehrstufige Agent-Workflows hinzugefügt. -**Graceful Degradation:**Ein neues mehrschichtiges Fallback-Framework hinzugefügt, um die Kernfunktionalität bei teilweisen Systemausfällen aufrechtzuerhalten. -**Config Audit:**Ein Audit-Trail mit Diff-Erkennung hinzugefügt, um Änderungen zu verfolgen und Konfigurations-Rollbacks zu ermöglichen. -**Anbieterstatus:**Anbieterablaufverfolgung mit proaktiven UI-Benachrichtigungen für ablaufende API-Schlüssel hinzugefügt. -**Adaptives Routing:**Ein adaptiver Volumen- und Komplexitätsdetektor wurde hinzugefügt, um Routing-Strategien dynamisch basierend auf der Auslastung zu überschreiben. -**Anbietervielfalt:**Anbieterdiversitätsbewertung über Shannon-Entropie implementiert, um die Lastverteilung zu verbessern. -**Grenzen für die automatische Deaktivierung:**Dem Resilienz-Dashboard wurde ein Einstellungsschalter für die automatische Deaktivierung gesperrter Konten hinzugefügt.### 🐛 Bug Fixes\n\n-**Codex- und Claude-Kompatibilität:**UI-Fallbacks behoben, Codex-Nicht-Streaming-Integrationsprobleme gepatcht und CLI-Laufzeiterkennung unter Windows behoben. -**Release-Automatisierung:**Erweiterte Berechtigungen für den Electron App-Build in GitHub Actions erforderlich. -**Cloudflare Runtime:**Korrekte Laufzeitisolations-Exit-Codes für Cloudflared-Tunnelkomponenten wurden behoben.### 🧪 Tests\n\n-**Updates der Testsuite:**Erweiterte Testabdeckung für Volumendetektoren, Anbietervielfalt, Konfigurationsprüfung und FSM.---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n-**CI/CD-Zuverlässigkeit:**GitHub-Aktionen wurden auf stabile Abhängigkeitsversionen („actions/checkout@v4“, „actions/upload-artifact@v4“) gepatcht, um unangekündigte veraltete Builder-Umgebungen abzumildern. -**Image-Fallbacks:**Beliebige Fallback-Ketten in „ProviderIcon.tsx“ wurden durch explizite Asset-Validierung ersetzt, um zu verhindern, dass die Benutzeroberfläche „“-Komponenten für nicht vorhandene Dateien lädt, wodurch „404“-Fehler in Dashboard-Konsolenprotokollen beseitigt wurden (#745). -**Admin Updater:**Dynamische Quellinstallationserkennung für den Dashboard-Updater. Deaktiviert sicher die Schaltfläche „Jetzt aktualisieren“, wenn OmniRoute lokal und nicht über npm erstellt wird, und fordert zu „git pull“ auf (#743). -**Eresolve-Fehler aktualisieren:**„package.json“-Überschreibungen für „react“/„react-dom“ eingefügt und „--legacy-peer-deps“ in den internen automatischen Updater-Skripten aktiviert, um störende Abhängigkeitsbaumkonflikte mit „@lobehub/ui“ zu lösen.---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n-**Cloudflare Tunnels:**Cloudflare Quick Tunnel-Integration mit Dashboard-Steuerelementen (PR #772). -**Diagnose:**Semantische Cache-Umgehung für kombinierte Live-Tests (PR #773).### 🐛 Bug Fixes\n\n-**Streaming-Stabilität:**Wenden Sie „FETCH_TIMEOUT_MS“ auf den ersten „fetch()“-Aufruf von Streaming-Anfragen an, um zu verhindern, dass ein Node.js-TCP-Timeout von 300 Sekunden zu Fehlern bei stillen Aufgaben führt (#769). -**i18n:**Fehlende „windsurf“- und „copilot“-Einträge zu „toolDescriptions“ in allen 33 Gebietsschemadateien hinzugefügt (#748). -**GLM-Coding-Audit:**Vollständige Anbieterprüfung zur Behebung von ReDoS-Schwachstellen, Kontextfenstergröße (128.000/16.000) und Modellregistrierungssynchronisierung (PR #778).---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n-**OpenAI-Codex:**Korrektur der Fallback-Verarbeitung für „type: „text““-Elemente mit Null- oder leeren Datensätzen, die eine 400-Zurückweisung verursachten (#742). -**Opencode:**Schemaausrichtung auf singulären „Anbieter“ aktualisieren, um der offiziellen Spezifikation zu entsprechen (#774). -**Gemini CLI:**Fügen Sie fehlende Endbenutzer-Kontingent-Header ein, um 403-Autorisierungssperren zu verhindern (#775). -**DB-Wiederherstellung:**Mehrteilige Nutzlastimporte in unformatierte binär gepufferte Arrays umgestalten, um die maximalen Body-Grenzwerte des Reverse-Proxys zu umgehen (#770).---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Release-Stabilisierung**– Finalisierte Version 3.2.9 (Combo-Diagnose, Quality Gates, Gemini-Tool-Korrektur) und fehlendes Git-Tag erstellt. Alle bereitgestellten Änderungen wurden in einem einzigen atomaren Release-Commit konsolidiert.### 🐛 Bug Fixes\n\n-**Auto-Update-Test**– Die Testzusicherung „buildDockerComposeUpdateScript“ wurde so korrigiert, dass sie mit nicht erweiterten Shell-Variablenreferenzen („$TARGET_TAG“, „${TARGET_TAG#v}“) im generierten Bereitstellungsskript übereinstimmt und mit der überarbeiteten Vorlage aus Version 3.2.8 übereinstimmt. -**Leistungsschaltertest**– „combo-Circuit-breaker.test.mjs“ wurde durch Einfügen von „maxRetries: 0“ gehärtet, um zu verhindern, dass die Wiederholungsinflation die Fehleranzahlzusicherungen während Leistungsschalterzustandsübergängen verzerrt.---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Combo-Diagnose**– Einführung eines Live-Test-Bypass-Flags („forceLiveComboTest“), das es Administratoren ermöglicht, echte Upstream-Gesundheitsprüfungen durchzuführen, die alle lokalen Leistungsschalter- und Cooldown-Statusmechanismen umgehen und so eine präzise Diagnose während der Einführung von Ausfällen ermöglichen (PR #759) -**Quality Gates**– Automatische Validierung der Antwortqualität für Combos hinzugefügt und offiziell integrierte „Claude-4.6“-Modellunterstützung in die Kern-Routing-Schemata (PR #762)### 🐛 Bug Fixes\n\n-**Tool-Definitionsvalidierung**– Die Gemini-API-Integration wurde durch Normalisierung von Enum-Typen innerhalb von Tool-Definitionen repariert, wodurch Upstream-HTTP-400-Parameterfehler verhindert wurden (PR #760)---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Docker Auto-Update UI**– Integriert einen separaten Hintergrundaktualisierungsprozess für Docker Compose-Bereitstellungen. Die Dashboard-Benutzeroberfläche verfolgt jetzt nahtlos Aktualisierungslebenszyklusereignisse und kombiniert JSON-REST-Antworten mit SSE-Streaming-Fortschrittsüberlagerungen für robuste umgebungsübergreifende Zuverlässigkeit. -**Cache-Analyse**– Die Null-Metrik-Visualisierungszuordnung wurde durch die direkte Migration von Semantic-Cache-Telemetrieprotokollen direkt in das zentralisierte Tracking-SQLite-Modul repariert.### 🐛 Bug Fixes\n\n-**Authentifizierungslogik**– Es wurde ein Fehler behoben, bei dem das Speichern von Dashboard-Einstellungen oder das Hinzufügen von Modellen mit dem Fehler 401 Unauthorized fehlschlug, wenn „requireLogin“ deaktiviert war. API-Endpunkte werten den globalen Authentifizierungsschalter jetzt korrekt aus. Die globale Umleitung wurde durch erneute Aktivierung von „src/middleware.ts“ behoben. -**CLI-Tool-Erkennung (Windows)**– Schwerwiegende Initialisierungsausnahmen während der CLI-Umgebungserkennung wurden verhindert, indem „Cross-Spawn“-ENOENT-Fehler korrekt abgefangen wurden. Fügt explizite Erkennungspfade für „\\AppData\\Local\\droid\\droid.exe“ hinzu. -**Codex Native Passthrough**– Normalisierte Modellübersetzungsparameter verhindern Kontextvergiftung im Proxy-Passthrough-Modus und erzwingen explizit generische „store: false“-Einschränkungen für alle von Codex stammenden Anforderungen. -**SSE-Token-Reporting**– Normalisierte Erkennung des Provider-Tool-Aufrufblocks „finish_reason“, Behebung von 0 % Nutzungsanalyse für reine Stream-Antworten, denen strenge „“-Indikatoren fehlen. -**DeepSeek -Tags**– Eine explizite „“-Extraktionszuordnung in „responsesHandler.ts“ implementiert, um sicherzustellen, dass DeepSeek-Argumentationsströme äquivalent zu nativen Anthropic-„“-Strukturen abgebildet werden.---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n-**Nahtlose UI-Updates**: Die Funktion „Jetzt aktualisieren“ im Dashboard bietet jetzt transparentes Live-Feedback mithilfe von Server-Sent Events (SSE). Es führt die Paketinstallation, die Neuerstellung nativer Module (better-sqlite3) und PM2-Neustarts zuverlässig durch und zeigt Echtzeit-Loader an, anstatt stillschweigend hängen zu bleiben.---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**API Key Reveal (#740)**– Im Api Manager wurde ein bereichsbezogener API-Schlüsselkopierablauf hinzugefügt, der durch die Umgebungsvariable „ALLOW_API_KEY_REVEAL“ geschützt ist. -**Sichtbarkeitskontrollen in der Seitenleiste (#739)**– Administratoren können jetzt alle Navigationslinks in der Seitenleiste über die Darstellungseinstellungen ausblenden, um die visuelle Unordnung zu reduzieren. -**Strenge Combo-Tests (#735)**– Der Combo-Health-Check-Endpunkt wurde gehärtet, um Live-Text-Antworten von Modellen statt nur weichen Erreichbarkeitssignalen zu erfordern. -**Gestreamte detaillierte Protokolle (#734)**– Die detaillierte Anforderungsprotokollierung für SSE-Streams wurde geändert, um die endgültige Nutzlast zu rekonstruieren, wodurch enorme Mengen an SQLite-Datenbankgröße eingespart und die Benutzeroberfläche erheblich bereinigt werden.### 🐛 Bug Fixes\n\n-**OpenCode Go MiniMax Auth (#733)**– Die Authentifizierungs-Header-Logik für „Minimax“-Modelle auf OpenCode Go wurde korrigiert, um „x-api-key“ anstelle von Standard-Bearer-Tokens im gesamten „/messages“-Protokoll zu verwenden.---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Void Linux Deployment Support (#732)**– Integrierte „xbps-src“-Paketvorlage und Anweisungen zum nativen Kompilieren und Installieren von OmniRoute mit „better-sqlite3“-Bindungen über ein Cross-Compilation-Ziel.## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Qoder AI-Migration (#660)**– Vollständige Migration des alten „iFlow“-Kernanbieters auf „Qoder AI“ unter Beibehaltung stabiler API-Routing-Funktionen.### 🐛 Bug Fixes\n\n-**Gemini Tools HTTP 400 Payload Ungültiges Argument (#731)**– Es wurde verhindert, dass „thoughtSignature“-Array-Injektionen in standardmäßige „functionCall“-Sequenzen von Gemini Agenten-Routing-Abläufe blockieren.---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n-**Benutzeroberfläche für Anbieterlimit-Kontingente (#728)**– Normalisierte Kontingentlimit-Logik und Datenbeschriftung innerhalb der Limits-Schnittstelle.### 🐛 Bug Fixes\n\n-**Kern-Routing-Schemas und -Lecks**– „comboStrategySchema“ wurde erweitert, um „Fill-First“- und „P2C“-Strategien nativ zu unterstützen und komplexe Combo-Bearbeitung nativ freizugeben. -**Thinking Tags Extraction (CLI)**– Umstrukturiertes CLI-Token-Antwort-Desinfektionsmittel RegEx erfasst Modellbegründungsstrukturen innerhalb von Streams und vermeidet fehlerhafte „“-Extraktionen, die das Antworttext-Ausgabeformat beeinträchtigen. -**Strenge Formatdurchsetzungen**– Gehärtete Ausführung der Pipeline-Bereinigung, sodass sie universell für Ziele im Übersetzungsmodus gilt.---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n-**Vierstufige Anforderungsprotokoll-Pipeline (#705)**– Die Protokollpersistenz wurde überarbeitet, um umfassende Nutzlasten in vier verschiedenen Pipeline-Stufen zu speichern: Client-Anfrage, übersetzte Anbieteranforderung, Anbieter-Antwort und übersetzte Client-Antwort. Einführung von „streamPayloadCollector“ für robuste SSE-Stream-Kürzung und Payload-Serialisierung.### 🐛 Bug Fixes\n\n-**Korrekturen für die mobile Benutzeroberfläche (#659)**– Es wurde verhindert, dass Tabellenkomponenten im Dashboard das Layout in schmalen Ansichtsfenstern unterbrechen, indem korrektes horizontales Scrollen und Überlaufeindämmung zu „DashboardLayout“ hinzugefügt wurden. -**Claude Prompt Cache Fixes (#708)**– Sichergestellt, dass „cache_control“-Blöcke in Claude-to-Claude-Fallback-Schleifen originalgetreu erhalten bleiben und sicher an Anthropic-Modelle zurückgegeben werden. -**Gemini-Tool-Definitionen (#725)**– Schemaübersetzungsfehler beim Deklarieren einfacher „Objekt“-Parametertypen für Gemini-Funktionsaufrufe behoben.## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n-**Globaler Fallback-Anbieter (#689)**– Wenn alle Combo-Modelle erschöpft sind (502/503), versucht OmniRoute nun ein konfigurierbares globales Fallback-Modell, bevor der Fehler zurückgegeben wird. Stellen Sie „globalFallbackModel“ in den Einstellungen ein, um es zu aktivieren.### 🐛 Bug Fixes\n\n-**Fix #721**– Die Umgehung der Kontextfixierung während der Antworten auf Toolaufrufe wurde behoben. Beim Nicht-Streaming-Tagging wurde der falsche JSON-Pfad verwendet („json.messages“ → „json.choices[0].message“). Die Streaming-Injektion wird jetzt auf „finish_reason“-Blöcken für Streams, die nur Tool-Aufrufe umfassen, ausgelöst. „injectModelTag()“ hängt jetzt synthetische Pin-Nachrichten für Nicht-String-Inhalte an. -**Fix #709**– Bestätigt, bereits behoben (v3.1.9) – „system-info.mjs“ erstellt Verzeichnisse rekursiv. Geschlossen. -**Fix #707**– Bestätigt, bereits behoben (v3.1.9) – Leere Tool-Namensbereinigung in „chatCore.ts“. Geschlossen.### 🧪 Tests\n\n– 6 Unit-Tests für Kontext-Pinning mit Tool-Call-Antworten hinzugefügt (Nullinhalt, Array-Inhalt, Roundtrip, Neuinjektion)## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n-**Cache-Management-UI**– Ein dediziertes semantisches Caching-Dashboard unter \\`/dashboard/cache\\` mit gezielter API-Invalidierung und 31-Sprachen-i18n-Unterstützung hinzugefügt (PR #701 von @oyi77) -**GLM-Kontingentverfolgung**– Echtzeit-Nutzungs- und Sitzungskontingentverfolgung für den GLM Coding (Z.AI)-Anbieter hinzugefügt (PR #698 von @christopher-s) -**Detaillierte Protokollnutzlasten**– Verdrahtete vollständige vierstufige Pipeline-Nutzlasterfassung (Original, übersetzt, Anbieter-Antwort, gestreamte Deltas) direkt in die Benutzeroberfläche (PR #705 von @rdself)### 🐛 Bug Fixes\n\n–**Fix #708**– Verhinderung von Token-Bleeding für Claude-Code-Benutzer, die über OmniRoute weiterleiten, indem native \\`cache_control\\`-Header während des Claude-zu-Claude-Passthrough korrekt beibehalten werden (PR #708 von @tombii) -**Fix #719**– Richten Sie interne Authentifizierungsgrenzen für „ModelSyncScheduler“ ein, um nicht authentifizierte Daemon-Fehler beim Start zu verhindern (PR #719 von @rdself) -**Fix #718**– Neu erstellte Badge-Darstellung in der Benutzeroberfläche für Anbieterlimits, um eine Überlappung fehlerhafter Kontingentgrenzen zu verhindern (PR #718 von @rdself) -**Fix #704**– Combo-Fallbacks, die bei HTTP 400-Inhaltsrichtlinienfehlern kaputt gingen und ein Dead-Routing bei der Modellrotation verhinderten, wurden behoben (PR #704 von @rdself)### 🔒 Security & Dependencies\n\n- „Path-to-regexp“ wurde auf „8.4.0“ verschoben, um Abhängigkeits-Schwachstellen zu beheben (PR #715)## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n-**Fix #706**– Symbol-Fallback-Rendering behoben, das durch Tailwind V4 „font-sans“-Überschreibung durch Anwenden von „!important“ auf „.material-symbols-outlined“ verursacht wurde. -**Fix #703**– Defekte GitHub Copilot-Streams wurden behoben, indem „Antworten“ auf die „openai“-Formatübersetzung für alle benutzerdefinierten Modelle aktiviert wurden, die „apiFormat: „responses““ nutzen. -**Fix Nr. 702**– Flatrate-Nutzungsverfolgung durch genaue DB-Preisberechnungen für Streaming- und Nicht-Streaming-Antworten ersetzt. -**Fix #716**– Claude-Tool-Call-Übersetzungsstatus bereinigt, Streaming-Argumente korrekt analysiert und verhindert, dass OpenAI-„tool_calls“-Chunks das „id“-Feld wiederholen.## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n-**Schema-Zwang**– Zwingt string-codierte numerische JSON-Schema-Einschränkungen (z. B. „Minimum“: „1“) automatisch in die richtigen Typen um und verhindert so 400-Fehler von Cursor, Cline und anderen Clients, die fehlerhafte Tool-Schemata senden. -**Bereinigung von Werkzeugbeschreibungen**– Stellen Sie sicher, dass Werkzeugbeschreibungen immer Zeichenfolgen sind; Konvertiert „null“, „undefiniert“ oder numerische Beschreibungen in leere Zeichenfolgen, bevor es an Anbieter gesendet wird. -**Schaltfläche „Alle Modelle löschen“**– i18n-Übersetzungen für die Anbieteraktion „Alle Modelle löschen“ in allen 30 Sprachen hinzugefügt. -**Codex Auth-Export**– Codex „auth.json“-Export- und Apply-Local-Schaltflächen für eine nahtlose CLI-Integration hinzugefügt. -**Windsurf BYOK-Hinweise**– Der Windsurf CLI-Toolkarte wurden offizielle Einschränkungswarnungen hinzugefügt, die BYOK-Einschränkungen dokumentieren.### 🐛 Bug Fixes\n\n-**Fix #709**– „system-info.mjs“ stürzt nicht mehr ab, wenn das Ausgabeverzeichnis nicht existiert (hinzugefügt „mkdirSync“ mit rekursivem Flag). -**Fix #710**– A2A „TaskManager“-Singleton verwendet jetzt „globalThis“, um Statusverluste bei Next.js-API-Routen-Neukompilierungen im Entwicklungsmodus zu verhindern. E2E-Testsuite wurde aktualisiert, um 401 ordnungsgemäß zu verarbeiten. -**Fix #711**– Anbieterspezifische Durchsetzung der Obergrenze „max*tokens“ für Upstream-Anfragen hinzugefügt. -**Fix #605 / #592**– Entfernen Sie das Präfix „proxy*“ aus den Toolnamen in Nicht-Streaming-Claude-Antworten; Die LongCat-Validierungs-URL wurde korrigiert. -**Max. Obergrenze für Anrufprotokolle**– „getMaxCallLogs()“ wurde mit Caching-Ebene, Unterstützung für Umgebungsvariablen („CALL_LOGS_MAX“) und Integration von DB-Einstellungen aktualisiert.### 🧪 Tests\n\n- Testsuite von 964 auf 1027 Tests erweitert (63 neue Tests)\n- „schema-coercion.test.mjs“ hinzugefügt – 9 Tests für numerische Feldumsetzung und Tool-Beschreibungsbereinigung\n- „t40-opencode-cli-tools-integration.test.mjs“ hinzugefügt – OpenCode/Windsurf CLI-Integrationstests\n- Erweiterter Feature-Tests-Zweig mit umfassenden Abdeckungstools### 📁 New Files\n\n| Datei | Zweck |\n| -------------------------------------------------------- | -------------------------------------------------------------------- | ---------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Dienstprogramme zur Schema-Zwangs- und Tool-Beschreibungsbereinigung |\n| `tests/unit/schema-coercion.test.mjs` | Unit-Tests für Schemazwang |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI-Tool-Integrationstests |\n| `COVERAGE_PLAN.md` | Planungsdokument zur Testabdeckung | ### 🐛 Bug Fixes |\n\n-**Claude Prompt Caching Passthrough**– Das Entfernen von Cache_Control-Markern im Claude-Passthrough-Modus (Claude → OmniRoute → Claude) wurde behoben, was dazu führte, dass Claude Code-Benutzer ihr Anthropic API-Kontingent 5-10x schneller erschöpften als bei direkten Verbindungen. OmniRoute behält jetzt die „cache_control“-Marker des Clients bei, wenn „sourceFormat“ und „targetFormat“ beide „Claude“ sind. Dadurch wird sichergestellt, dass das Prompt-Caching korrekt funktioniert und der Tokenverbrauch drastisch reduziert wird.## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n-**Plattformkern:**Globale Statusbehandlung für versteckte Modelle und Kombinationen implementiert, um zu verhindern, dass sie den Katalog überladen oder in verbundene MCP-Agenten eindringen (#681). -**Stabilität:**Gepatchte Streaming-Abstürze im Zusammenhang mit der fehlgeschlagenen Integration des nativen Antigravity-Anbieters aufgrund nicht behandelter undefinierter Zustands-Arrays (#684). -**Lokalisierungssynchronisierung:**Ein vollständig überarbeiteter „i18n“-Synchronizer wurde bereitgestellt, der fehlende verschachtelte JSON-Eigenschaften erkennt und 30 Gebietsschemata nacheinander nachrüstet (#685).## [3.1.7] – 27.03.2026### 🐛 Bug Fixes\n\n-**Streaming-Stabilität:**Problem behoben, bei dem „hasValuableContent“ „undefiniert“ für leere Blöcke in SSE-Streams zurückgab (#676). -**Tool-Aufruf:**Es wurde ein Problem in „sseParser.ts“ behoben, bei dem bei nicht gestreamten Claude-Antworten mit mehreren Tool-Aufrufen die „id“ nachfolgender Tool-Aufrufe aufgrund einer falschen indexbasierten Deduplizierung verloren gingen (#671).---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n-**Wiederherstellung des nativen Tool-Namens von Claude**– Tool-Namen wie „TodoWrite“ wird in Claude-Passthrough-Antworten (sowohl Streaming als auch Nicht-Streaming) nicht mehr das Präfix „proxy\\_“ vorangestellt. Beinhaltet Unit-Test-Abdeckung (PR #663 von @coobabm) -**Bereinigung des Aliasnamens „Alle Modelle löschen“**– Die Schaltfläche „Alle Modelle löschen“ entfernt jetzt auch zugehörige Modellaliase und verhindert so Geistermodelle in der Benutzeroberfläche (PR #664 von @rdself)---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n-**Backoff Auto-Decay**– Konten mit eingeschränkter Rate werden jetzt automatisch wiederhergestellt, wenn ihr Abklingzeitfenster abläuft. Dadurch wird ein Deadlock behoben, bei dem ein hohes „BackoffLevel“ Konten dauerhaft depriorisierte (PR #657 von @brendandebeasi)### 🌍 i18n\n\n-**Überarbeitung der chinesischen Übersetzung**– Umfassende Neufassung von „zh-CN.json“ mit verbesserter Genauigkeit (PR #658 von @only4copilot)---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n-**Streaming Override Fix**– Explizites „stream: true“ im Anfragetext hat jetzt Priorität vor dem Header „Accept: application/json“. Clients, die beide senden, erhalten korrekt SSE-Streaming-Antworten (#656)### 🌍 i18n\n\n-**Verbesserungen der tschechischen Zeichenfolge**– Verfeinerte Terminologie in „cs.json“ (PR #655 von @zen0bit)---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n-**~70 fehlende Übersetzungsschlüssel**zu „en.json“ und 12 Sprachen hinzugefügt (PR #652 von @zen0bit) -**Tschechische Dokumentation aktualisiert**– CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT-Anleitungen (PR #652) -**Übersetzungsvalidierungsskripts**– „check_translations.py“ und „validate_translation.py“ für CI/QA (PR #651 von @zen0bit)---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n-**Kritisch: Tool-Aufruf-Regression**– „proxy*Bash“-Fehler wurden behoben, indem das Präfix „proxy*“-Toolnamen im Claude-Passthrough-Pfad deaktiviert wurde. Tools wie „Bash“, „Read“, „Write“ wurden in „proxy_Bash“, „proxy_Read“ usw. umbenannt, was dazu führte, dass Claude sie ablehnte (#618) -**Kiro-Kontosperrungsdokumentation**– Dokumentiert als falsch positives Upstream-AWS-Anti-Betrugs-Ereignis, kein OmniRoute-Problem (#649)### 🧪 Tests\n\n-**936 Tests, 0 Fehler**---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n-**Metadaten zur Visionsfähigkeit**: „capabilities.vision“, „input_modalities“ und „output_modalities“ zu „/v1/models“-Einträgen für visionfähige Modelle hinzugefügt (PR #646) -**Gemini 3.1-Modelle**: „gemini-3.1-pro-preview“ und „gemini-3.1-flash-lite-preview“ zum Antigravity-Anbieter hinzugefügt (#645)### 🐛 Bug Fixes\n\n-**Ollama Cloud 401-Fehler**: Falsche API-Basis-URL behoben – geändert von „api.ollama.com“ in offiziell „ollama.com/v1/chat/completions“ (#643) -**Wiederholung abgelaufener Token**: Begrenzter Wiederholungsversuch mit exponentiellem Backoff (5→10→20 Minuten) für abgelaufene OAuth-Verbindungen hinzugefügt, anstatt sie dauerhaft zu überspringen (PR #647)### 🧪 Tests\n\n-**936 Tests, 0 Fehler**---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n-**GitHub-Problemvorlagen**: Standardisierte Fehlerberichts-, Funktionsanfrage- und Konfigurations-/Proxy-Problemvorlagen hinzugefügt (#641) -**Alle Modelle löschen**: Schaltfläche „Alle Modelle löschen“ zur Anbieterdetailseite mit i18n-Unterstützung in 29 Sprachen hinzugefügt (#634)### 🐛 Bug Fixes\n\n-**Gebietsschemakonflikt (`in.json`)**: Die Hindi-Gebietsschemadatei wurde von „in.json“ (indonesischer ISO-Code) in „hi.json“ umbenannt, um Übersetzungskonflikte in Weblate zu beheben (#642) -**Codex Empty Tool Names**: Die Bereinigung von Toolnamen wurde vor dem nativen Codex-Passthrough verschoben, wodurch 400 Fehler von Upstream-Anbietern behoben wurden, wenn Tools leere Namen hatten (#637) -**Streaming von Newline-Artefakten**: „collapseExcessiveNewlines“ wurde zur Antwortbereinigung hinzugefügt, wodurch Läufe von mehr als 3 aufeinanderfolgenden Newline-Artefakten aus Denkmodellen in einen standardmäßigen doppelten Newline-Vorgang reduziert werden (#638) -**Claude Reasoning Effort**: OpenAI-Parameter „reasoning_effort“ in Claudes nativen „Thinking“-Budgetblock über alle Anforderungspfade hinweg konvertiert, einschließlich automatischer „max_tokens“-Anpassung (#627) -**Qwen-Token-Aktualisierung**: Proaktive OAuth-Token-Aktualisierungen vor Ablauf (5-Minuten-Puffer) implementiert, um zu verhindern, dass Anfragen fehlschlagen, wenn kurzlebige Token verwendet werden (#631)### 🧪 Tests\n\n-**936 Tests, 0 Fehler**(+10 Tests seit 3.0.9)---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n-**NaN-Tokens in Claude Code / Client-Antworten (#617):**\n\n- „sanitizeUsage()“ ordnet jetzt „input_tokens“ → „prompt_tokens“ und „output_tokens“ → „completion_tokens“ vor dem Whitelist-Filter übergreifend zu und korrigiert Antworten, die NaN/0-Token-Zählungen anzeigen, wenn Anbieter Verwendungsfeldnamen im Claude-Stil zurückgeben### Sicherheit\n\n– Aktualisiertes „yaml“-Paket zur Behebung der Stapelüberlauf-Schwachstelle (GHSA-48c2-rrv3-qjmp)### 📋 Issue Triage\n\n- Geschlossen Nr. 613 (Codestral – mit Problemumgehung für benutzerdefinierte Anbieter behoben)\n – Kommentiert zu #615 (OpenCode Dual-Endpoint – Problemumgehung bereitgestellt, als Funktionsanfrage verfolgt)\n- Kommentiert zu #618 (Sichtbarkeit von Toolaufrufen – Anforderung von v3.0.9-Test)\n- Kommentiert zu #627 (Aufwandsgrad – bereits unterstützt)---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n-**Übersetzungsfehler für OpenAI-Format-Anbieter in Claude CLI (#632):**\n\n- Behandelt das Array-Format „reasoning_details[]“ von StepFun/OpenRouter – konvertiert in „reasoning_content“.\n- Behandeln Sie den Feldalias „reasoning“ einiger Anbieter → normalisiert auf „reasoning_content“.\n- Feldnamen für kartenübergreifende Verwendung: „input_tokens“↔„prompt_tokens“, „output_tokens“↔„completion_tokens“ in „filterUsageForFormat“.\n- Korrigieren Sie „extractUsage“, um sowohl „input_tokens“/„output_tokens“ als auch „prompt_tokens“/„completion_tokens“ als gültige Nutzungsfelder zu akzeptieren\n – Wird sowohl auf Streaming- („sanitizeStreamingChunk“, „openai-to-claude.ts“-Übersetzer) als auch auf Nicht-Streaming- („sanitizeMessage“) Pfade angewendet---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n-**Antigravity-Token-Aktualisierung:**Fehler „client_secret fehlt“ für npm-installierte Benutzer behoben – „clientSecretDefault“ war in der ProviderRegistry leer, was dazu führte, dass Google Token-Aktualisierungsanfragen ablehnte (#588) -**OpenCode Zen-Modelle:**„modelsUrl“ zum OpenCode Zen-Registrierungseintrag hinzugefügt, damit „Importieren aus /models“ korrekt funktioniert (#612) -**Streaming-Artefakte:**Überschüssige Zeilenumbrüche in Antworten nach dem Entfernen der Thinking-Tag-Signatur behoben (#626) -**Proxy-Fallback:**Automatischer Wiederholungsversuch ohne Proxy hinzugefügt, wenn das SOCKS5-Relay fehlschlägt -**Proxy-Test:**Der Testendpunkt löst jetzt echte Anmeldeinformationen aus der Datenbank über die Proxy-ID auf### ✨ New Features\n\n-**Playground-Konto-/Schlüsselauswahl:**Permanentes, immer sichtbares Dropdown-Menü zur Auswahl bestimmter Anbieterkonten/Schlüssel zum Testen – ruft alle Verbindungen beim Start ab und filtert nach ausgewähltem Anbieter -**Dynamische Modelle der CLI-Tools:**Die Modellauswahl wird jetzt dynamisch von der API „/v1/models“ abgerufen – Anbieter wie Kiro zeigen jetzt ihren vollständigen Modellkatalog an -**Antigravity-Modellliste:**Aktualisiert mit Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; „passthroughModels“ für dynamischen Modellzugriff aktiviert (#628)### 🔧 Maintenance\n\n- Zusammengeführte PR Nr. 625 – Anbieter schränkt die Hintergrundkorrektur im Lichtmodus ein---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n-**Limits/Proxy:**Das Abrufen des Codex-Limits für Konten hinter SOCKS5-Proxys wurde korrigiert – die Token-Aktualisierung wird jetzt im Proxy-Kontext ausgeführt -**CI:**Fehler bei der Assertion des Integrationstests „v1/models“ in CI-Umgebungen ohne Anbieterverbindungen behoben -**Einstellungen:**Die Schaltfläche „Proxy-Test“ zeigt nun sofort Erfolgs-/Fehlerergebnisse an (bisher hinter Gesundheitsdaten verborgen)### ✨ New Features\n\n-**Playground:**Dropdown-Liste zur Kontoauswahl hinzugefügt – testen Sie bestimmte Verbindungen einzeln, wenn ein Anbieter über mehrere Konten verfügt### 🔧 Maintenance\n\n- Zusammengeführte PR #623 – Korrektur des Basis-URL-Pfads der LongCat-API---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n-**Einschränkungen der Benutzeroberfläche:**Tag-Gruppierungsfunktion zum Verbindungs-Dashboard hinzugefügt, um die visuelle Organisation für Konten mit benutzerdefinierten Tags zu verbessern.---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n-**Streaming:**Die Statusbeschädigung von „TextDecoder“ in der Combo „sanitize“ TransformStream wurde behoben, was zu einer verstümmelten SSE-Ausgabe führte, die mit Multibyte-Zeichen übereinstimmte (PR #614) -**Anbieter-Benutzeroberfläche:**Rendern Sie HTML-Tags sicher in den Tooltips für Anbieterverbindungsfehler mit „dangerouslySetInnerHTML“. -**Proxy-Einstellungen:**Fehlende Payload-Körpereigenschaften „Benutzername“ und „Passwort“ hinzugefügt, sodass authentifizierte Proxys erfolgreich über das Dashboard überprüft werden können. -**Anbieter-API:**Die gebundene Soft-Ausnahme kehrt zu „getCodexUsage“ zurück und verhindert API-HTTP-500-Fehler, wenn der Token-Abruf fehlschlägt---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n-**Auto-Sync-Modelle:**Ein UI-Schalter und ein „Sync-Models“-Endpunkt hinzugefügt, um Modelllisten pro Anbieter mithilfe eines geplanten Intervallplaners automatisch zu synchronisieren (PR #597)### 🐛 Bug Fixes\n\n-**Zeitüberschreitungen:**Die Standard-Proxys „FETCH_TIMEOUT_MS“ und „STREAM_IDLE_TIMEOUT_MS“ wurden auf 10 Minuten erhöht, um Deep Reasoning-Modelle (wie o1) ordnungsgemäß zu unterstützen, ohne dass Anfragen abgebrochen werden müssen (Fixes #609) -**CLI-Tool-Erkennung:**Verbesserte plattformübergreifende Erkennung bei der Verarbeitung von NVM-Pfaden, Windows „PATHEXT“ (verhindert Probleme mit „.cmd“-Wrappern) und benutzerdefinierten NPM-Präfixen (PR #598) -**Streaming-Protokolle:**Delta-Akkumulation von „tool_calls“ in Streaming-Antwortprotokollen implementiert, damit Funktionsaufrufe genau verfolgt und in der Datenbank gespeichert werden (PR #603) -**Modellkatalog:**Authentifizierungsausnahme entfernt, wodurch die Modelle „comfyui“ und „sdwebui“ ordnungsgemäß ausgeblendet werden, wenn kein Anbieter explizit konfiguriert ist (PR #599)### 🌐 Translations\n\n-**cs:**Verbesserte tschechische Übersetzungszeichenfolgen in der gesamten App (PR #601)## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n– Ein Tag-/Gruppenfeld zu „EditConnectionModal“ hinzugefügt (gespeichert in „providerSpecificData.tag“), ohne dass DB-Schemamigrationen erforderlich sind.\n– Verbindungen in der Anbieteransicht werden jetzt dynamisch nach Tag mit visuellen Trennlinien gruppiert.\n\n- Nicht getaggte Verbindungen erscheinen zuerst ohne Kopfzeile, gefolgt von getaggten Gruppen in alphabetischer Reihenfolge.\n – Die Tag-Gruppierung gilt automatisch für den Abschnitt „Codex/Copilot/Antigravity Limits“, da in den Verbindungszeilen Umschalter vorhanden sind.### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n-**Fehlende Abzeichen auf Verbindungskarten:**Behoben durch die Verwendung von „resolveProxyForConnection()“ anstelle der statischen Zuordnung. -**Testverbindung im gespeicherten Modus deaktiviert:**Die Schaltfläche „Testen“ wurde durch Auflösen der Proxy-Konfiguration aus der gespeicherten Liste aktiviert. -**Modales Einfrieren der Konfiguration:**„onClose()“-Aufrufe nach dem Speichern/Löschen hinzugefügt, um ein Einfrieren der Benutzeroberfläche zu verhindern. -**Doppelte Nutzungszählung:**„ProxyRegistryManager“ lädt die Nutzung jetzt eifrig beim Mounten mit Deduplizierung durch „scope“ + „scopeId“. Nutzungszählungen wurden durch eine Testschaltfläche ersetzt, die IP/Latenz inline anzeigt.#### fix(translator): `function_call` prefix stripping\n\n– Es wurde ein unvollständiger Fix von PR #607 repariert, bei dem nur „tool*use“-Blöcke Claudes „proxy*“-Tool-Präfix entfernten. Jetzt erhalten Clients, die das OpenAI Responses API-Format verwenden, auch korrekt Tool-Tools ohne das Präfix „proxy\\_“.---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nDrei kritische Regressionen, die von Benutzern nach dem Start von v3.0.0 gemeldet wurden, wurden behoben.#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nDas von Claude OAuth hinzugefügte Präfix „proxy\\_“ wurde nur aus**Streaming**-Antworten entfernt. Im**Nicht-Streaming**-Modus hatte „translateNonStreamingResponse“ keinen Zugriff auf die „toolNameMap“, was dazu führte, dass Clients entstellte Toolnamen wie „proxy_read_file“ anstelle von „read_file“ erhielten.\n\n**Fix:**Optionaler Parameter „toolNameMap“ zu „translateNonStreamingResponse“ hinzugefügt und Präfixentfernung im Claude-Blockhandler „tool_use“ angewendet. „chatCore.ts“ leitet nun die Karte weiter.#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI stellt „GET /v1/models“ nicht zur Verfügung. Der generische „validateOpenAICompatibleProvider“-Validator fiel nur dann auf einen Chat-Completions-Fallback durch, wenn „validationModelId“ festgelegt war, was LongCat nicht konfiguriert. Dies führte dazu, dass die Anbietervalidierung mit einem irreführenden Fehler beim Hinzufügen/Speichern fehlschlug.\n\n**Fix:**„Longcat“ zur Karte der Spezialvalidatoren hinzugefügt, um „/chat/completions“ direkt zu prüfen und jede nicht authentifizierte Antwort als bestanden zu behandeln.#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP-Tools (z. B. „pencil“, „computer_use“) leiten Tooldefinitionen mit „{type:“object“}“ weiter, jedoch ohne ein „properties“-Feld. Die API von Anthropic lehnt diese mit „Objektschema fehlende Eigenschaften“ ab.\n\n**Fix:**Fügen Sie in „openai-to-claude.ts“ „properties: {}“ als sicheren Standard ein, wenn „type“ „object“ ist und „properties“ fehlt.---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Autor | Zusammenfassung |\n| -------- | ------- | -------------------------------------------------------------------------------- | --- |\n| **#589** | @flobo3 | docs(i18n): Korrigieren Sie die russische Übersetzung für Playground und Testbed |\n| **#591** | @rdself | fix(ui): Provider Limits-Lichtmoduskontrast und Planstufenanzeige verbessern | --- |\n\n### ✅ Issues Resolved\n\n„#592“ „#595“ „#605“.---\n\n### 🧪 Tests\n\n-**926 Tests, 0 Fehler**(unverändert gegenüber v3.0.0)---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **Die größte Veröffentlichung aller Zeiten.**Von 36 Anbietern in Version 2.9.5 auf**67+ Anbieter**in Version 3.0.0 – mit MCP-Server, A2A-Protokoll, Auto-Combo-Engine, Anbietersymbolen, API für registrierte Schlüssel, 926 Tests und Beiträgen von**12 Community-Mitgliedern**in**10 zusammengeführten PRs**.\n>\n> Konsolidiert von v3.0.0-rc.1 bis rc.17 (17 Release-Kandidaten in 3 Tagen intensiver Entwicklung).---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Anbieter | Alias ​​ | Stufe | Notizen |\n| ---------------------------------- | --------------- | -------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |\n| **OpenCode Zen** | `opencode-zen` | Kostenlos | 3 Modelle über `opencode.ai/zen/v1` (PR #530 von @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Bezahlt | 4 Modelle über `opencode.ai/zen/go/v1` (PR #530 von @kang-heewon) |\n| **LongCat AI** | `lc` | Kostenlos | 50 Mio. Token/Tag (Flash-Lite) + 500.000/Tag (Chat/Thinking) während der öffentlichen Beta |\n| **Bestäubungs-KI** | `pol` | Kostenlos | Kein API-Schlüssel erforderlich – GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 Anforderung/15 Sek.) |\n| **Cloudflare Workers AI** | `cf` | Kostenlos | 10.000 Neuronen/Tag – ~150 LLM-Antworten oder 500 Sekunden Whisper-Audio, Kanteninferenz |\n| **Scaleway AI** | `scw` | Kostenlos | 1 Million kostenlose Token für neue Konten – EU/DSGVO-konform (Paris) |\n| **AI/ML-API** | `aiml` | Kostenlos | 0,025 $/Tag kostenloses Guthaben – 200+ Modelle über einen einzigen Endpunkt |\n| **Computer-KI** | `pu` | Kostenlos | Über 500 Modelle (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Bezahlt | Internationale + China-Endpunkte über `alicode`/`alicode-intl` |\n| **Alibaba-Codierungsplan** | `bcp` | Bezahlt | Alibaba Model Studio mit Anthropic-kompatibler API |\n| **Kimi-Codierung (API-Schlüssel)** | `kmca` | Bezahlt | Dedizierter Kimi-Zugriff auf API-Schlüsselbasis (getrennt von OAuth) |\n| **MiniMax-Codierung** | `minimax` | Bezahlt | Internationaler Endpunkt |\n| **MiniMax (China)** | `minimax-cn` | Bezahlt | China-spezifischer Endpunkt |\n| **Z.AI (GLM-5)** | `zai` | Bezahlt | Zhipu AI GLM-Modelle der nächsten Generation |\n| **Vertex AI** | `Scheitelpunkt` | Bezahlt | Google Cloud – Dienstkonto JSON oder OAuth access_token |\n| **Ollama-Wolke** | `ollamacloud` | Bezahlt | Ollamas gehosteter API-Dienst |\n| **Synthetisch** | „synthetisch“ | Bezahlt | Gateway für Passthrough-Modelle |\n| **Kilo-Gateway** | `kg` | Bezahlt | Gateway für Passthrough-Modelle |\n| **Perplexitätssuche** | `pplx-search` | Bezahlt | Dedizierter suchbasierter Endpunkt |\n| **Serper-Suche** | `serper-search` | Bezahlt | Websuche-API-Integration |\n| **Mutige Suche** | `brave-search` | Bezahlt | Brave Search API-Integration |\n| **Exa-Suche** | `exa-suche` | Bezahlt | Integration der neuronalen Such-API |\n| **Tavily-Suche** | `tavily-search` | Bezahlt | AI-Such-API-Integration |\n| **NanoBanane** | `nb` | Bezahlt | Bildgenerierungs-API |\n| **ElevenLabs** | `el` | Bezahlt | Text-zu-Sprache-Sprachsynthese |\n| **Kartesia** | „Kartesie“ | Bezahlt | Ultraschnelle TTS-Sprachsynthese |\n| **PlayHT** | `playht` | Bezahlt | Sprachklonen und TTS |\n| **Inworld** | `inworld` | Bezahlt | KI-Charakter-Voice-Chat |\n| **SD-WebUI** | `sdwebui` | Selbstgehostet | Lokale Bilderzeugung mit stabiler Diffusion |\n| **ComfyUI** | `comfyui` | Selbstgehostet | ComfyUI lokale Workflow-Knoten-basierte Generierung |\n| **GLM-Codierung** | `glm` | Bezahlt | BigModel/Zhipu-codierungsspezifischer Endpunkt | **Gesamt: 67+ Anbieter**(4 kostenlos, 8 OAuth, 55 API-Schlüssel) + unbegrenzte OpenAI/Anthropic-kompatible benutzerdefinierte Anbieter.--- |\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAutomatische Generierung und Ausgabe von OmniRoute-API-Schlüsseln programmgesteuert mit Kontingentdurchsetzung pro Anbieter und pro Konto.\n\n| Endpunkt | Methode | Beschreibung |\n| ------------------------------- | ------------ | ---------------------------------------------------------------------------------- | ------ |\n| `/api/v1/registered-keys` | `POST` | Geben Sie einen neuen Schlüssel aus – Rohschlüssel wird**nur einmal**zurückgegeben |\n| `/api/v1/registered-keys` | `GET` | Registrierte Schlüssel auflisten (maskiert) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Metadaten abrufen / widerrufen |\n| `/api/v1/quotas/check` | `GET` | Kontingent vor der Ausstellung vorab validieren |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Konfigurieren Sie die Ausgabelimits pro Anbieter |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Konfigurieren Sie die Ausgabelimits pro Konto |\n| `/api/v1/issues/report` | `POST` | Kontingentereignisse an GitHub Issues | melden |\n\n**Sicherheit:**Schlüssel werden als SHA-256-Hashes gespeichert. Der Rohschlüssel wird bei der Erstellung einmal angezeigt und ist nie wieder abrufbar.#### 🎨 Provider Icons via @lobehub/icons (#529)\n\nÜber 130 Anbieterlogos mit „@lobehub/icons“ React-Komponenten (SVG). Fallback-Kette:**Lobehub SVG → vorhandenes PNG → generisches Symbol**. Wird auf Dashboard-, Anbieter- und Agentenseiten mit der standardisierten „ProviderIcon“-Komponente angewendet.#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAktualisiert die Modelllisten für verbundene Anbieter automatisch alle**24 Stunden**. Wird beim Serverstart ausgeführt. Konfigurierbar über „MODEL_SYNC_INTERVAL_HOURS“.#### 🔀 Per-Model Combo Routing (#563)\n\nOrdnen Sie Modellnamensmuster (Glob) bestimmten Kombinationen für die automatische Weiterleitung zu:\n\n- `claude-sonnet*` → Code-Combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- Neue „model_combo_mappings“-Tabelle mit Glob-zu-Regex-Abgleich\n- Abschnitt der Dashboard-Benutzeroberfläche: „Modell-Routing-Regeln“ mit Inline-Hinzufügen/Bearbeiten/Umschalten/Löschen#### 🧭 API Endpoints Dashboard\n\nInteraktiver Katalog, Webhooks-Verwaltung, OpenAPI-Viewer – alles auf einer Seite mit Registerkarten unter „/dashboard/endpoint“.#### 🔍 Web Search Providers\n\n5 neue Suchanbieter-Integrationen:**Perplexity Search**,**Serper**,**Brave Search**,**Exa**,**Tavily**– ermöglichen fundierte KI-Antworten mit Echtzeit-Webdaten.#### 📊 Search Analytics\n\nNeuer Tab in „/dashboard/analytics“ – Anbieteraufschlüsselung, Cache-Trefferquote, Kostenverfolgung. API: `GET /api/v1/search/analytics`.#### 🛡️ Per-API-Key Rate Limits (#452)\n\nSpalten „max_requests_per_day“ und „max_requests_per_minute“ mit In-Memory-Slide-Window-Erzwingung, die HTTP 429 zurückgibt.#### 🎵 Media Playground\n\nVollständiger Spielplatz zur Mediengenerierung unter „/dashboard/media“: Bildgenerierung, Video, Musik, Audiotranskription (Upload-Limit 2 GB) und Text-to-Speech.---\n\n### 🔒 Security & CI/CD\n\n-**CodeQL-Remediation**– Über 10 Warnungen behoben: 6 Polynom-Wiederholungen, 1 unsichere Zufälligkeit (`Math.random()` → `crypto.randomUUID()`), 1 Shell-Befehlsinjektion -**Routenvalidierung**– Zod-Schemas + „validateBody()“ auf**176/176 API-Routen**– CI erzwungen\n–**CVE-Fix**– dompurify XSS-Schwachstelle (GHSA-v2wj-7wpq-c8vv) über NPM-Überschreibungen behoben -**Abgeflacht**– Beulen 3.3.3 → 3.4.2 (CWE-1321-Prototypverschmutzung) -**Docker**– „docker/setup-buildx-action“ v3 → v4 aktualisiert---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n-**#537**– Gemini CLI OAuth: Umsetzbarer Fehler löschen, wenn „GEMINI_OAUTH_CLIENT_SECRET“ in Docker fehlt -**#549**– CLI-Einstellungsrouten lösen jetzt echten API-Schlüssel aus „keyId“ auf (keine maskierten Zeichenfolgen) -**#574**– Die Anmeldung friert nicht mehr ein, nachdem die Passworteinrichtung des Assistenten übersprungen wurde -**#506**– Plattformübergreifende „machineId“ neu geschrieben (Windows REG.exe → macOS ioreg → Linux → Hostname-Fallback)#### Providers & Routing\n\n-**#536**– LongCat AI: „baseUrl“ und „authHeader“ korrigiert -**#535**– Überschreibung des angehefteten Modells: „body.model“ wurde korrekt auf „pinnedModel“ gesetzt -**#570**– Claude-Modelle ohne Präfix werden jetzt zum Anthropic-Anbieter aufgelöst -**#585**– Interne Tags „“ werden im SSE-Streaming nicht mehr an Clients weitergegeben -**#493**– Die Benennung benutzerdefinierter Anbietermodelle wird nicht mehr durch das Entfernen von Präfixen beeinträchtigt -**#490**– Streaming + Kontext-Cache-Schutz über „TransformStream“-Injection -**#511**– „“-Tag in den ersten Inhaltsblock eingefügt (nicht nach „[FERTIG]“)#### CLI & Tools\n\n-**#527**– Claude Code + Codex-Schleife: „tool_result“-Blöcke werden jetzt in Text umgewandelt -**#524**– OpenCode-Konfiguration korrekt gespeichert (XDG_CONFIG_HOME, TOML-Format) -**#522**– API Manager: Die irreführende Schaltfläche „Maskierten Schlüssel kopieren“ wurde entfernt -**#546**– „--version“ gibt unter Windows „unbekannt“ zurück (PR von @k0valik) -**#544**– Sichere CLI-Tool-Erkennung über bekannte Installationspfade (PR von @k0valik) -**#510**– Windows MSYS2/Git-Bash-Pfade werden automatisch normalisiert -**#492**– CLI erkennt einen von „mise“/„nvm“ verwalteten Knoten, wenn „app/server.js“ fehlt#### Streaming & SSE\n\n-**PR #587**– „resolveDataDir“-Import in ResponsesTransformer für Cloudflare Workers-Kompatibilität zurücksetzen (@k0valik)\n–**PR #495**– Engpass 429, unendliches Warten: Wartende Jobs bei Ratenbegrenzung abbrechen (@xandr0s) -**#483**– Schluss mit „data: null“ nach dem „[DONE]“-Signal -**#473**– Zombie-SSE-Streams: Timeout auf 300 → 120 Sekunden reduziert, um einen schnelleren Fallback zu ermöglichen#### Media & Transcription\n\n-**Transkription**– Deepgram „video/mp4“ → „audio/mp4“ MIME-Zuordnung, automatische Spracherkennung, Zeichensetzung -**TTS**– Fehleranzeige „[object Object]“ für verschachtelte Fehler im ElevenLabs-Stil behoben -**Upload-Limits**– Medientranskription auf 2 GB erhöht (nginx „client_max_body_size 2g“ + „maxDuration=300“)---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n-**T01**– Spalte „requested_model“ in Anrufprotokollen (Migration 009) -**T02**– Leere Textblöcke aus verschachtelten „tool_result.content“ entfernen -**T03**– Kontingent-Header „x-codex-5h-_“ / „x-codex-7d-_“ analysieren -**T04**– „X-Session-Id“-Header für externes Sticky-Routing -**T05**– Ratenbegrenzte DB-Persistenz mit dedizierter API -**T06**– Konto deaktiviert → permanente Sperre (1 Jahr Abklingzeit) -**T07**– X-Forwarded-For IP-Validierung (`extractClientIp()`) -**T08**– Sitzungslimits pro API-Schlüssel mit Sliding-Window-Erzwingung -**T09**– Codex vs. Spark-Ratenbegrenzungsbereiche (separate Pools) -**T10**– Credits erschöpft → deutlicher 1-stündiger Abklingzeit-Fallback -**T11**– „maximaler“ Argumentationsaufwand → 131072 Budget-Tokens -**T12**– Preisangaben für MiniMax M2.7 -**T13**– Fehlerbehebung bei der Anzeige veralteter Kontingente (Fenstererkennung zurücksetzen) -**T14**– Proxy-Fast-Fail-TCP-Prüfung (≤2 s, zwischengespeichert 30 s) -**T15**– Array-Inhaltsnormalisierung für Anthropic -**T23**– Intelligenter Quoten-Reset-Fallback (Header-Extraktion) -**T24**– Abklingzeit „503“ + Zuordnung „406“. -**T25**– Anbietervalidierungs-Fallback -**T29**– JWT-Authentifizierung des Vertex AI-Dienstkontos -**T33**– Umrechnung von Denkebene in Budget -**T36**– Fehlerklassifizierung „403“ vs. „429“. -**T38**– Zentralisierte Modellspezifikationen („modelSpecs.ts“) -**T39**– Endpunkt-Fallback für „fetchAvailableModels“. -**T41**– Automatische Umleitung von Hintergrundaufgaben auf Flash-Modelle -**T42**– Zuordnung des Seitenverhältnisses zur Bildgenerierung#### Other Improvements\n\n-**Benutzerdefinierte Upstream-Header pro Modell**– über die Konfigurations-Benutzeroberfläche (PR #575 von @zhangqiang8vip) -**Modellkontextlänge**– konfigurierbar in Modellmetadaten (PR #578 von @hijak)\n–**Entfernen des Modellpräfixes**– Option zum Entfernen des Anbieterpräfixes aus Modellnamen (PR #582 von @jay77721)\n–**Gemini-CLI-Veraltung**– als veraltet markiert, mit Google-OAuth-Einschränkungswarnung -**YAML-Parser**– benutzerdefinierter Parser durch „js-yaml“ für korrektes Parsen der OpenAPI-Spezifikation ersetzt -**ZWS v5**– HMR-Leck-Fix (485 DB-Verbindungen → 1, Speicher 2,4 GB → 195 MB) -**Protokollexport**– Neue JSON-Exportschaltfläche im Dashboard mit Dropdown-Liste für den Zeitraum -**Update-Benachrichtigungsbanner**– Auf der Dashboard-Startseite wird angezeigt, wenn neue Versionen verfügbar sind---\n\n### 🌐 i18n & Documentation\n\n-**30 Sprachen**bei 100 % Parität – 2.788 fehlende Schlüssel synchronisiert -**Tschechisch**– Vollständige Übersetzung: 22 Dokumente, 2.606 UI-Strings (PR von @zen0bit) -**Chinesisch (zh-CN)**– Vollständige Neuübersetzung (PR von @only4copilot) -**VM-Bereitstellungshandbuch**– Als Quelldokument ins Englische übersetzt -**API-Referenz**– Endpunkte „/v1/embeddings“ und „/v1/audio/speech“ hinzugefügt -**Anzahl der Anbieter**– Aktualisiert von 36+/40+/44+ auf**67+**in der gesamten README-Datei und allen 30 i18n-READMEs---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Autor | Zusammenfassung |\n| -------- | --------------- | ---------------------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): ResolveDataDir-Import für Cloudflare Workers-Kompatibilität zurücksetzen |\n| **#582** | @jay77721 | feat(proxy): Option zum Entfernen des Modellnamenpräfixes |\n| **#581** | @jay77721 | fix(npm): Elektronenfreigabe mit npm-publish-Workflow verknüpfen |\n| **#578** | @hijak | feat: konfigurierbare Kontextlänge in Modellmetadaten |\n| **#575** | @zhangqiang8vip | feat: Upstream-Header pro Modell, kompatibler PATCH, Chat-Ausrichtung |\n| **#562** | @coobabm | Fix: MCP-Sitzungsverwaltung, Claude-Passthrough, discoverFormat |\n| **#561** | @zen0bit | fix(i18n): Korrekturen der tschechischen Übersetzung |\n| **#555** | @k0valik | fix(sse): zentralisiertes „resolveDataDir()“ für die Pfadauflösung |\n| **#546** | @k0valik | fix(cli): „--version“ gibt unter Windows „unbekannt“ zurück |\n| **#544** | @k0valik | fix(cli): sichere CLI-Tool-Erkennung über Installationspfade |\n| **#542** | @rdself | fix(ui): CSS-Designvariablen für den Kontrast im Lichtmodus |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go-Anbieter mit „OpencodeExecutor“ |\n| **#512** | @zhangqiang8vip | feat: Pro-Protokoll-Modellkompatibilität (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | Fix: HMR-Ressourcenlecks im Entwicklungsmodus (ZWS v5) |\n| **#495** | @xandr0s | Fix: Engpass 429 unendliches Warten (wartende Jobs löschen) |\n| **#494** | @zhangqiang8vip | feat: MiniMax-Entwickler→Systemrollenkorrektur |\n| **#480** | @prakersh | Fix: Extraktion der Stream-Flush-Nutzung |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 und Anthropic-Preiseinträge |\n| **#475** | @only4copilot | feat(i18n): verbesserte chinesische Übersetzung |\n\n**Vielen Dank an alle Mitwirkenden!**🙏---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`---\n\n### 🧪 Tests\n\n-**926 Tests, 0 Fehler**(von 821 in Version 2.9.5)\n\n- +105 neue Tests, die Folgendes abdecken: Modell-Kombinationszuordnungen, registrierte Schlüssel, OpencodeExecutor, Bailian-Anbieter, Routenvalidierung, Fehlerklassifizierung, Seitenverhältniszuordnung und mehr---\n\n### 📦 Database Migrations\n\n| Migration | Beschreibung |\n| --------- | ----------------------------------------------------------------------- | --- |\n| **008** | Tabellen „registered_keys“, „provider_key_limits“, „account_key_limits“ |\n| **009** | Spalte „requested_model“ in „call_logs“ |\n| **010** | „model_combo_mappings“-Tabelle für modellspezifisches Combo-Routing | --- |\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Wichtige Änderungen:**Keine. Alle vorhandenen Konfigurationen, Kombinationen und API-Schlüssel bleiben erhalten.\n> Datenbankmigrationen 008-010 werden beim Start automatisch ausgeführt.---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n-**CodeQL-Korrektur**– Über 10 Warnungen behoben:\n\n- 6 Polynom-Redos in „provider.ts“ / „chatCore.ts“ (alternierende Muster „(?:^|/)“ durch segmentbasiertes Matching ersetzt)\n- 1 unsichere Zufälligkeit in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n- 1 Shell-Befehlsinjektion in „prepublish.mjs“ (Pfad-Escape von „JSON.stringify()“) -**Routenvalidierung**– Zod-Schemas + „validateBody()“ zu 5 Routen ohne Validierung hinzugefügt:\n- „model-combo-mappings“ (POST, PUT), „webhooks“ (POST, PUT), „openapi/try“ (POST)\n- CI „check:route-validation:t06“ besteht jetzt Folgendes:**176/176 Routen validiert**### 🐛 Bug Fixes\n\n-**#585**– Interne Tags „“ werden in SSE-Antworten nicht mehr an Clients weitergegeben. Ausgehende Bereinigung „TransformStream“ in „combo.ts“ hinzugefügt### ⚙️ Infrastructure\n\n-**Docker**– „docker/setup-buildx-action“ von v3 → v4 aktualisiert (Node.js 20-Veraltungskorrektur) -**CI-Bereinigung**– Über 150 fehlgeschlagene/abgebrochene Workflow-Ausführungen wurden gelöscht### 🧪 Tests\n\n- Testsuite:**926 Tests, 0 Fehler**(+3 neu)---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Erhöhte Medientranskriptionslimits\n – Modellkontextlänge zu Registrierungsmetadaten hinzugefügt\n – Über die Konfigurations-Benutzeroberfläche wurden benutzerdefinierte Upstream-Header pro Modell hinzugefügt\n- Mehrere Fehler behoben, Zod-Validierung für Patches durchgeführt und verschiedene Community-Probleme behoben.## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n-**#563**– Combo-Routing pro Modell: Ordnen Sie Modellnamensmuster (Glob) bestimmten Combos für automatisches Routing zu\n– Neue Tabelle „model_combo_mappings“ (Migration 010) mit Muster, Combo_ID, Priorität, aktiviert\n\n- „resolveComboForModel()“ DB-Funktion mit Glob-zu-Regex-Abgleich (Groß-/Kleinschreibung wird nicht beachtet, „\\*“- und „?“-Platzhalter)\n- „getComboForModel()“ in „model.ts“: erweitert „getCombo()“ um einen Modellmuster-Fallback\n- „chat.ts“: Die Routing-Entscheidung prüft jetzt Modell-Kombinationszuordnungen vor der Verarbeitung einzelner Modelle\n- API: „GET/POST /api/model-combo-mappings“, „GET/PUT/DELETE /api/model-combo-mappings/:id“.\n- Dashboard: Abschnitt „Modell-Routing-Regeln“ zur Combos-Seite mit Inline-Hinzufügen/Bearbeiten/Umschalten/Löschen hinzugefügt\n- Beispiele: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo### 🌐 i18n\n\n-**Vollständige i18n-Synchronisierung**: 2.788 fehlende Schlüssel in 30 Sprachdateien hinzugefügt – alle Sprachen jetzt bei 100 % Parität mit „en.json“. -**Agentenseite i18n**: Abschnitt „OpenCode-Integration“ vollständig internationalisiert (Titel, Beschreibung, Scannen, Download-Labels) -**6 neue Schlüssel**zum Namespace „agents“ für den OpenCode-Abschnitt hinzugefügt### 🎨 UI/UX\n\n-**Anbietersymbole**: 16 fehlende Anbietersymbole hinzugefügt (3 kopiert, 2 heruntergeladen, 11 SVG erstellt) -**SVG-Fallback**: „ProviderIcon“-Komponente mit 4-Stufen-Strategie aktualisiert: Lobehub → PNG → SVG → Generisches Symbol -**Fingerabdrücke von Agenten**: Synchronisiert mit CLI-Tools – Droid, Openclaw, Copilot, Opencode zur Fingerabdruckliste hinzugefügt (insgesamt 14)### Sicherheit\n\n-**CVE-Fix**: Die dompurify XSS-Schwachstelle (GHSA-v2wj-7wpq-c8vv) über npm-Überschreibungen, die „dompurify@^3.3.2“ erzwingen, wurde behoben\n\n- „npm audit“ meldet jetzt**0 Schwachstellen**### 🧪 Tests\n\n- Testsuite:**923 Tests, 0 Fehler**(+15 neue Modell-Combo-Mapping-Tests)---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Autor | Zusammenfassung |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------ | ------------ |\n| **#562** | @coobabm | fix(ux): MCP-Sitzungsverwaltung, Claude-Passthrough-Normalisierung, OAuth-Modal, discoverFormat |\n| **#561** | @zen0bit | fix(i18n): Korrekturen der tschechischen Übersetzung – HTTP-Methodennamen und Dokumentationsaktualisierungen | ### 🧪 Tests |\n\n- Testsuite:**908 Tests, 0 Fehler**---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n-**config:**echten API-Schlüssel aus „keyId“ in CLI-Einstellungsrouten („codex-settings“, „droid-settings“, „kilo-settings“) auflösen, um das Schreiben maskierter Zeichenfolgen zu verhindern (#549)---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Autor | Zusammenfassung |\n| -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |\n| **#546** | @k0valik | fix(cli): „--version“ gibt „unknown“ unter Windows zurück – verwenden Sie „JSON.parse(readFileSync)“ anstelle von ESM import |\n| **#555** | @k0valik | fix(sse): zentralisiertes „resolveDataDir()“ für die Pfadauflösung in Anmeldeinformationen, AutoCombo, Antwort-Logger und Anforderungs-Logger |\n| **#544** | @k0valik | fix(cli): sichere CLI-Tool-Erkennung über bekannte Installationspfade (8 Tools) mit Symlink-Validierung, Dateitypprüfungen, Größenbeschränkungen, minimaler Umgebung im Healthcheck |\n| **#542** | @rdself | fix(ui): Kontrast im Hellmodus verbessern – fehlende CSS-Designvariablen („bg-primary“, „bg-subtle“, „text-primary“) hinzufügen und nur dunkle Farben in den Protokolldetails korrigieren | ### 🔧 Bug Fixes |\n\n-**TDZ-Korrektur in „cliRuntime.ts“**– „validateEnvPath“ wurde vor der Initialisierung beim Modulstart durch „getExpectedParentPaths()“ verwendet. Neugeordnete Deklarationen, um „ReferenceError“ zu beheben. -**Build-Korrekturen**– „Pino“ und „Pino-pretty“ zu „serverExternalPackages“ hinzugefügt, um zu verhindern, dass Turbopack Pinos internes Worker-Laden unterbricht.### 🧪 Tests\n\n- Testsuite:**905 Tests, 0 Fehler**---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n-**#509 / #508**– Electron-Build-Regression: Next.js wurde von „16.1.x“ auf „16.0.10“ heruntergestuft, um die Instabilität des Turbopack-Modul-Hashings zu beseitigen, die zu leeren Bildschirmen im Electron-Desktop-Bundle führte. -**Unit-Test-Korrekturen**– Zwei veraltete Testaussagen („Nanobanana-Image-Handler“-Seitenverhältnis/-Auflösung, „Thinking-Budget“-Gemini-Feldzuordnung „ThinkingConfig“), die nach kürzlichen Implementierungsänderungen abgedriftet waren, wurden korrigiert. -**#541**– Auf Benutzerfeedback zur Installationskomplexität reagiert; Keine Codeänderungen erforderlich.---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n-**T29**– Vertex AI SA JSON Executor: implementiert unter Verwendung der „jose“-Bibliothek zur Verwaltung der JWT-/Dienstkonto-Authentifizierung, zusammen mit konfigurierbaren Regionen in der Benutzeroberfläche und automatischer Partnermodell-URL-Erstellung. -**T42**– Bildgenerierungs-Seitenverhältniszuordnung: „sizeMapper“-Logik für generische OpenAI-Formate („Größe“) erstellt, native „imagen3“-Verarbeitung hinzugefügt und NanoBanana-Endpunkte aktualisiert, um zugeordnete Seitenverhältnisse automatisch zu verwenden. -**T38**– Zentralisierte Modellspezifikationen: „modelSpecs.ts“ wurde für Grenzwerte und Parameter pro Modell erstellt.### 🔧 Improvements\n\n-**T40**– Integration der OpenCode CLI-Tools: native „Opencode-zen“- und „Opencode-go“-Integration in früherer PR abgeschlossen.---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n-**T24**– „503“-Abklingzeit wartet auf Korrektur + „406“-Zuordnung: „406 nicht akzeptabel“ wurde auf „503-Dienst nicht verfügbar“ mit korrekten Abklingzeitintervallen abgebildet. -**T25**– Anbietervalidierungs-Fallback: eleganter Fallback auf Standardvalidierungsmodelle, wenn eine bestimmte „validationModelId“ nicht vorhanden ist. -**T36**– Verfeinerung der Anbieterhandhabung „403“ vs. „429“: Extrahiert in „errorClassifier.ts“, um harte Berechtigungsfehler („403“) ordnungsgemäß von Ratenbegrenzungen („429“) zu trennen. -**T39**– Endpoint-Fallback für „fetchAvailableModels“: Implementierung eines dreistufigen Mechanismus („/models“ -> „/v1/models“ -> lokaler generischer Katalog) + „list_models_catalog“ MCP-Tool-Updates, um „Quelle“ und „Warnung“ widerzuspiegeln. -**T33**– Umrechnung von Denkebene in Budget: Übersetzt qualitative Denkebenen in präzise Budgetzuweisungen. -**T41**– Automatische Umleitung von Hintergrundaufgaben: Leitet umfangreiche Hintergrundauswertungsaufgaben automatisch an Flash-/effiziente Modelle weiter. -**T23**– Intelligenter Quoten-Reset-Fallback: Extrahiert präzise „x-ratelimit-reset“-/„retry-after“-Header-Werte oder ordnet statische Abklingzeiten zu.---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade von v2.9.5:**16 Probleme behoben · 2 Community-PRs zusammengeführt · 2 neue Anbieter · 7 neue API-Endpunkte · 3 neue Funktionen · DB-Migration 008+009 · 832 Tests bestanden · 15 Sub2API-Lückenverbesserungen (T01–T15 abgeschlossen).### 🆕 New Providers\n\n| Anbieter | Alias ​​ | Stufe | Notizen |\n| ---------------- | -------------- | --------- | ----------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Kostenlos | 3 Modelle über `opencode.ai/zen/v1` (PR #530 von @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Bezahlt | 4 Modelle über `opencode.ai/zen/go/v1` (PR #530 von @kang-heewon) |\n\nBeide Anbieter nutzen den neuen „OpencodeExecutor“ mit Multiformat-Routing („/chat/completions“, „/messages“, „/responses“, „/models/{model}:generateContent“).---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAutomatische Generierung und Ausgabe von OmniRoute-API-Schlüsseln programmgesteuert mit Kontingentdurchsetzung pro Anbieter und pro Konto.\n\n| Endpunkt | Methode | Beschreibung |\n| ------------------------------------- | --------- | ---------------------------------------------------------------------------------- | ------ |\n| `/api/v1/registered-keys` | `POST` | Geben Sie einen neuen Schlüssel aus – Rohschlüssel wird**nur einmal**zurückgegeben |\n| `/api/v1/registered-keys` | `GET` | Registrierte Schlüssel auflisten (maskiert) |\n| `/api/v1/registered-keys/{id}` | `GET` | Schlüsselmetadaten abrufen |\n| `/api/v1/registered-keys/{id}` | „LÖSCHEN“ | Einen Schlüssel widerrufen |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Widerrufen (für Clients ohne DELETE-Unterstützung) |\n| `/api/v1/quotas/check` | `GET` | Kontingent vor der Ausstellung vorab validieren |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Konfigurieren Sie die Ausgabelimits pro Anbieter |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Konfigurieren Sie die Ausgabelimits pro Konto |\n| `/api/v1/issues/report` | `POST` | Kontingentereignisse an GitHub Issues | melden |\n\n**DB – Migration 008:**Drei neue Tabellen: „registered_keys“, „provider_key_limits“, „account_key_limits“.\n**Sicherheit:**Schlüssel werden als SHA-256-Hashes gespeichert. Der Rohschlüssel wird bei der Erstellung einmal angezeigt und ist nie wieder abrufbar.\n**Kontingenttypen:**„maxActiveKeys“, „dailyIssueLimit“, „hourlyIssueLimit“ pro Anbieter und pro Konto.\n**Idempotency:**Das Feld „idempotency_key“ verhindert die doppelte Ausgabe. Gibt „409 IDEMPOTENCY_CONFLICT“ zurück, wenn der Schlüssel bereits verwendet wurde.\n**Budget pro Schlüssel:**„dailyBudget“ / „hourlyBudget“ – begrenzt, wie viele Anfragen ein Schlüssel pro Fenster weiterleiten kann.\n**GitHub-Berichterstellung:**Optional. Legen Sie „GITHUB_ISSUES_REPO“ + „GITHUB_ISSUES_TOKEN“ fest, um bei Kontingentüberschreitung oder Ausgabefehlern automatisch GitHub-Probleme zu erstellen.#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAlle Anbietersymbole im Dashboard verwenden jetzt „@lobehub/icons“ React-Komponenten (über 130 Anbieter mit SVG).\nFallback-Kette:**Lobehub SVG → vorhandenes „/providers/{id}.png“ → generisches Symbol**. Verwendet ein geeignetes React-„ErrorBoundary“-Muster.#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute aktualisiert jetzt automatisch alle**24 Stunden**die Modelllisten für verbundene Anbieter.\n\n– Wird beim Serverstart über den vorhandenen Hook „/api/sync/initialize“ ausgeführt\n\n- Konfigurierbar über die Umgebungsvariable „MODEL_SYNC_INTERVAL_HOURS“.\n- Deckt 16 große Anbieter ab\n- Zeichnet die letzte Synchronisierungszeit in der Einstellungsdatenbank auf---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n-**#537 – Gemini CLI OAuth:**Umsetzbarer Fehler löschen, wenn „GEMINI_OAUTH_CLIENT_SECRET“ in Docker-/selbstgehosteten Bereitstellungen fehlt. Zuvor wurde bei Google der kryptische Hinweis „client_secret fehlt“ angezeigt. Bietet jetzt spezifische Anweisungen für „docker-compose.yml“ und „~/.omniroute/.env“.#### Providers & Routing\n\n-**#536 – LongCat AI:**`baseUrl` (`api.longcat.chat/openai`) und `authHeader` (`Authorization: Bearer`) korrigiert. -**#535 – Überschreibung des angehefteten Modells:**„body.model“ ist jetzt korrekt auf „pinnedModel“ gesetzt, wenn der Kontext-Cache-Schutz aktiv ist. -**#532 – OpenCode Go-Schlüsselvalidierung:**Verwendet jetzt den „zen/v1“-Testendpunkt („testKeyBaseUrl“) – der gleiche Schlüssel funktioniert für beide Ebenen.#### CLI & Tools\n\n-**#527 – Claude Code + Codex-Schleife:**„tool_result“-Blöcke werden jetzt in Text konvertiert statt gelöscht, wodurch endlose Tool-Ergebnisschleifen gestoppt werden. -**#524 – OpenCode-Konfiguration speichern:**`saveOpenCodeConfig()`-Handler hinzugefügt (XDG_CONFIG_HOME-fähig, schreibt TOML). -**#521 – Anmeldung bleibt hängen:**Die Anmeldung friert nicht mehr ein, nachdem die Passworteinrichtung übersprungen wurde – leitet korrekt zum Onboarding weiter. -**#522 – API Manager:**Die irreführende Schaltfläche „Maskierten Schlüssel kopieren“ wurde entfernt (ersetzt durch einen Tooltip mit einem Schlosssymbol). -**#532 – OpenCode Go-Konfiguration:**Der Guide-Einstellungshandler verarbeitet jetzt die „Opencode“-ToolId.#### Developer Experience\n\n-**#489 – Antigravity:**Das Fehlen von „googleProjectId“ gibt einen strukturierten 422-Fehler mit Anleitung zum erneuten Verbinden anstelle eines kryptischen Absturzes zurück. -**#510 – Windows-Pfade:**MSYS2/Git-Bash-Pfade („/c/Program Files/...“) werden jetzt automatisch auf „C:\\Program Files\\...“ normalisiert. -**#492 – CLI-Start:**Die „omniroute“-CLI erkennt jetzt den von „mise“/„nvm“ verwalteten Knoten, wenn „app/server.js“ fehlt, und zeigt gezielte Korrekturanweisungen an.---\n\n### 📖 Documentation Updates\n\n-**#513**– Zurücksetzen des Docker-Passworts: „INITIAL_PASSWORD“ env var Workaround dokumentiert -**#520**– pnpm: Schritt „pnpm genehmigt-builds-besser-sqlite3“ dokumentiert---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`---\n\n### 🔀 Community PRs Merged\n\n| PR | Autor | Zusammenfassung |\n| -------- | ------------ | ------------------------------------------------------------------------ | --- |\n| **#530** | @kang-heewon | OpenCode Zen + Go-Anbieter mit „OpencodeExecutor“ und verbesserten Tests | --- |\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n-**T05**– Ratenlimit-DB-Persistenz: „setConnectionRateLimitUntil()“, „isConnectionRateLimited()“, „getRateLimitedConnections()“ in „providers.ts“. Die vorhandene Spalte „rate_limited_until“ wird jetzt als dedizierte API bereitgestellt – die Aktualisierung des OAuth-Tokens darf dieses Feld NICHT berühren, um Ratenbegrenzungsschleifen zu verhindern. -**T08**– Sitzungslimit pro API-Schlüssel: „max_sessions INTEGER DEFAULT 0“ wurde über automatische Migration zu „api_keys“ hinzugefügt. „sessionManager.ts“ erhält „registerKeySession()“, „unregisterKeySession()“, „checkSessionLimit()“ und „getActiveSessionCountForKey()“. Aufrufer in „chatCore.js“ können das Limit erzwingen und bei „req.close“ verringern. -**T09**– Codex vs. Spark-Ratenbegrenzungsbereiche: „getCodexModelScope()“ und „getCodexRateLimitKey()“ in „codex.ts“. Standardmodelle („gpt-5.x-codex“, „codex-mini“) erhalten den Gültigkeitsbereich „codex“; Spark-Modelle („codex-spark\\*“) erhalten den Gültigkeitsbereich „spark“. Ratenbegrenzungsschlüssel sollten „${accountId}:${scope}“ lauten, damit die Erschöpfung eines Pools nicht den anderen blockiert. -**T13**– Fehlerbehebung bei der Anzeige veralteter Kontingente: „getEffectiveQuotaUsage(used, resetAt)“ gibt „0“ zurück, wenn das Rücksetzfenster verstrichen ist; „formatResetCountdown(resetAt)“ gibt eine für Menschen lesbare Countdown-Zeichenfolge zurück (z. B. „2h 35m“). Beide wurden aus „providers.ts“ + „localDb.ts“ für die Dashboard-Nutzung exportiert. -**T14**– Proxy-Fast-Fail: neues „src/lib/proxyHealth.ts“ mit „isProxyReachable(proxyUrl, timeoutMs=2000)“ (TCP-Prüfung, ≤2s statt 30s Timeout), „getCachedProxyHealth()“, „invalidateProxyHealth()“ und „getAllProxyHealthStatuses()“. Ergebnisse werden standardmäßig 30 Sekunden lang zwischengespeichert; konfigurierbar über „PROXY_FAST_FAIL_TIMEOUT_MS“ / „PROXY_HEALTH_CACHE_TTL_MS“.### 🧪 Tests\n\n- Testsuite:**832 Tests, 0 Fehler**---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n-**T01**– Spalte „requested_model“ in „call_logs“ (Migration 009): Verfolgen Sie, welches Modell der Client ursprünglich angefordert hat, im Vergleich zum tatsächlich gerouteten Modell. Ermöglicht die Analyse der Fallback-Rate. -**T02**– Leere Textblöcke aus verschachtelten „tool_result.content“ entfernen: verhindert Anthropic 400-Fehler („Textinhaltsblöcke dürfen nicht leer sein“), wenn Claude Code Toolergebnisse verkettet. -**T03**– „x-codex-5h-_“ / „x-codex-7d-_“-Header analysieren: „parseCodexQuotaHeaders()“ + „getCodexResetTime()“ extrahieren Codex-Kontingentfenster für eine präzise Abklingzeitplanung anstelle eines generischen 5-Minuten-Fallbacks. -**T04**– „X-Session-Id“-Header für externes Sticky-Routing: „extractExternalSessionId()“ in „sessionManager.ts“ liest „x-session-id“-/„x-omniroute-session“-Header mit „ext:“-Präfix, um Kollisionen mit internen SHA-256-Sitzungs-IDs zu vermeiden. Nginx-kompatibel (Kopfzeile mit Bindestrich). -**T06**– Konto deaktiviert → dauerhafte Sperre: „isAccountDeactivated()“ in „accountFallback.ts“ erkennt 401-Deaktivierungssignale und wendet eine Abklingzeit von einem Jahr an, um zu verhindern, dass dauerhaft deaktivierte Konten erneut versucht werden. -**T07**– X-Forwarded-For IP-Validierung: neues „src/lib/ipUtils.ts“ mit „extractClientIp()“ und „getClientIpFromRequest()“ – überspringt „unbekannte“/Nicht-IP-Einträge in „X-Forwarded-For“-Ketten (über Nginx/Proxy weitergeleitete Anfragen). -**T10**– Credits erschöpft → deutlicher Fallback: „isCreditsExhausted()“ in „accountFallback.ts“ gibt 1 Stunde Abklingzeit mit „creditsExhausted“-Flag zurück, anders als die generische 429-Ratenbegrenzung. -**T11**– „maximaler“ Argumentationsaufwand → 131072 Budget-Tokens: „EFFORT_BUDGETS“ und „THINKING_LEVEL_MAP“ aktualisiert; Die umgekehrte Zuordnung gibt jetzt „max“ für Antworten mit vollem Budget zurück. Unit-Test aktualisiert. -**T12**– Preiseinträge für MiniMax M2.7 hinzugefügt: „minimax-m2.7“, „MiniMax-M2.7“, „minimax-m2.7-highspeed“ zur Preistabelle hinzugefügt (sub2api PR #1120). Die Preise für M2.5/GLM-4.7/GLM-5/Kimi waren bereits vorhanden. -**T15**– Array-Inhaltsnormalisierung: Der Helfer „normalizeContentToString()“ in „openai-to-claude.ts“ fasst Array-formatierte System-/Tool-Nachrichten korrekt zu einem String zusammen, bevor er an Anthropic gesendet wird.### 🧪 Tests\n\n- Testsuite:**832 Tests, 0 Fehler**(unverändert gegenüber rc.5)---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n-**#464**– API zur Bereitstellung registrierter Schlüssel: Automatische Ausgabe von API-Schlüsseln mit Kontingentdurchsetzung pro Anbieter und pro Konto\n\n- „POST /api/v1/registered-keys“ – Schlüssel mit Idempotenzunterstützung ausgeben\n- „GET /api/v1/registered-keys“ – (maskierte) registrierte Schlüssel auflisten\n- „GET /api/v1/registered-keys/{id}“ – Schlüsselmetadaten abrufen\n- „DELETE /api/v1/registered-keys/{id}“ / „POST ../{id}/revoke“ – Schlüssel widerrufen\n- „GET /api/v1/quotas/check“ – vor der Ausgabe vorab validieren\n- „PUT /api/v1/providers/{id}/limits“ – Provider-Ausgabelimits festlegen\n- „PUT /api/v1/accounts/{id}/limits“ – Kontoausstellungslimits festlegen\n- „POST /api/v1/issues/report“ – optionale GitHub-Problemberichterstattung\n- DB-Migration 008: Tabellen „registered_keys“, „provider_key_limits“, „account_key_limits“.---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n-**#530 (PR)**– OpenCode Zen- und OpenCode Go-Anbieter hinzugefügt (von @kang-heewon)\n\n- Neuer „OpencodeExecutor“ mit Multiformat-Routing („/chat/completions“, „/messages“, „/responses“)\n- 7 Modelle auf beiden Ebenen---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n-**#529**– Anbietersymbole verwenden jetzt [@lobehub/icons](https://github.com/lobehub/lobe-icons) mit elegantem PNG-Fallback und einer „ProviderIcon“-Komponente (mehr als 130 Anbieter werden unterstützt) -**#488**– Modelllisten automatisch alle 24 Stunden über „modelSyncScheduler“ aktualisieren (konfigurierbar über „MODEL_SYNC_INTERVAL_HOURS“)### 🔧 Bug Fixes\n\n-**#537**– Gemini CLI OAuth: Zeigt jetzt einen klar umsetzbaren Fehler an, wenn „GEMINI_OAUTH_CLIENT_SECRET“ in Docker-/selbstgehosteten Bereitstellungen fehlt---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n-**#536**– LongCat AI-Schlüsselvalidierung: baseUrl (`api.longcat.chat/openai`) und authHeader (`Authorization: Bearer`) korrigiert -**#535**– Überschreibung des angehefteten Modells: „body.model“ wird jetzt auf „pinnedModel“ gesetzt, wenn der Kontext-Cache-Schutz ein angeheftetes Modell erkennt -**#524**– OpenCode-Konfiguration jetzt korrekt gespeichert: `saveOpenCodeConfig()`-Handler hinzugefügt (XDG_CONFIG_HOME-bewusst, schreibt TOML)---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n-**#521**– Die Anmeldung bleibt nicht mehr hängen, nachdem die Passworteinrichtung übersprungen wurde (Weiterleitung zum Onboarding) -**#522**– API Manager: Irreführende Schaltfläche „Maskierten Schlüssel kopieren“ entfernt (ersetzt durch Tooltip mit Schlosssymbol) -**#527**– Claude Code + Codex Superpowers-Schleife: „tool_result“-Blöcke werden jetzt in Text umgewandelt, anstatt gelöscht zu werden -**#532**– Die OpenCode GO API-Schlüsselvalidierung verwendet jetzt den richtigen „zen/v1“-Endpunkt („testKeyBaseUrl“) -**#489**– Antigravity: Fehlende „googleProjectId“ gibt einen strukturierten 422-Fehler mit Anleitung zum erneuten Verbinden zurück -**#510**– Windows: MSYS2/Git-Bash-Pfade (`/c/Program Files/...`) werden jetzt auf `C:\\Program Files\\...` normalisiert -**#492**– „Omniroute“-CLI erkennt jetzt „mise“/„nvm“, wenn „app/server.js“ fehlt, und zeigt die gezielte Korrektur an### Dokumentation\n\n-**#513**– Zurücksetzen des Docker-Passworts: „INITIAL_PASSWORD“ env var Workaround dokumentiert -**#520**– pnpm: „pnpm genehmigt-builds-besser-sqlite3“ dokumentiert### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: Neue OpenCode-Anbieter, Korrektur der Einbettung von Anmeldeinformationen, CLI-maskierter Schlüsselfehler, Korrektur von CACHE_TAG_PATTERN.### 🐛 Bug Fixes\n\n-**CLI-Tools speichern maskierte API-Schlüssel in Konfigurationsdateien**– POST-Routen „claude-settings“, „cline-settings“ und „openclaw-settings“ akzeptieren jetzt einen „keyId“-Parameter und lösen den echten API-Schlüssel aus der Datenbank auf, bevor er auf die Festplatte geschrieben wird. „ClaudeToolCard“ wurde aktualisiert, um „keyId“ anstelle der maskierten Anzeigezeichenfolge zu senden. Behebt #523, #526. -**Benutzerdefinierte Einbettungsanbieter: Fehler „Keine Anmeldeinformationen“**– „/v1/embeddings“ verfolgt „credentialsProviderId“ jetzt getrennt vom Routing-Präfix, sodass Anmeldeinformationen von der passenden Anbieterknoten-ID und nicht von der öffentlichen Präfixzeichenfolge abgerufen werden. Behebt eine Regression, bei der „google/gemini-embedding-001“ und ähnliche benutzerdefinierte Anbietermodelle immer mit einem Anmeldeinformationsfehler fehlschlugen. Behebt Fehler im Zusammenhang mit #532. (PR #528 von @jacob2826) -**Kontext-Cache-Schutz-Regex fehlt `\n` Präfix**– `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` aktualisiert, damit es mit beiden Literalen übereinstimmt `\n` (Backslash-n) und tatsächlicher Zeilenumbruch U+000A, den „combo.ts“-Streaming nach Fix Nr. 515 um das „“-Tag herum einfügt. Behebt #531.### ✨ New Providers\n\n-**OpenCode Zen**– Kostenloses Tier-Gateway unter „opencode.ai/zen/v1“ mit 3 Modellen: „minimax-m2.5-free“, „big-pickle“, „gpt-5-nano“. -**OpenCode Go**– Abonnementdienst unter „opencode.ai/zen/go/v1“ mit 4 Modellen: „glm-5“, „kimi-k2.5“, „minimax-m2.7“ (Claude-Format), „minimax-m2.5“ (Claude-Format)\n\n- Beide Anbieter verwenden den neuen „OpencodeExecutor“, der basierend auf dem angeforderten Modell dynamisch an „/chat/completions“, „/messages“, „/responses“ oder „/models/{model}:generateContent“ weiterleitet. (PR #530 von @kang-heewon)---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Fehlerbehebungen – Codex-Eingabeaufforderungs-Cache-Schlüssel beibehalten, tagContent-JSON-Escape behoben, abgelaufener Token-Status mit DB synchronisieren.### 🐛 Bug Fixes\n\n-**fix(translator)**: „prompt_cache_key“ in der Antwort-API → Chat-Abschlüsse-Übersetzung beibehalten (#517)\n– Das Feld ist ein Cache-Affinitätssignal, das von Codex verwendet wird; Durch das Entfernen wurden sofortige Cache-Treffer verhindert.\nIn „openai-responses.ts“ und „responsesApiHelper.ts“ behoben.\n\n-**fix(combo)**: Escape `\n` in `tagContent`, sodass die eingefügte JSON-Zeichenfolge gültig ist (#515)\n– Zeilenumbrüche im Vorlagenliteral (U+000A) sind ohne Escapezeichen innerhalb von JSON-Zeichenfolgenwerten nicht zulässig.\nErsetzt durch „\\n“-Literalsequenzen in „open-sse/services/combo.ts“.\n\n-**Fix(Nutzung)**: Synchronisieren Sie den Status des abgelaufenen Tokens bei einem Live-Authentifizierungsfehler wieder mit der Datenbank (#491)\n— Wenn die Live-Überprüfung der Grenzwerte und Kontingente 401/403 zurückgibt, wird die Verbindung „testStatus“ jetzt aktualisiert\nin der Datenbank auf „abgelaufen“ gesetzt, sodass auf der Anbieterseite derselbe verschlechterte Status angezeigt wird.\nBehoben in „src/app/api/usage/[connectionId]/route.ts“.---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Fügen Sie 5 neue kostenlose KI-Anbieter hinzu – LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.### ✨ New Providers\n\n-**feat(providers/longcat)**: LongCat AI (`lc/`) hinzufügen – 50 Mio. Token/Tag kostenlos (Flash-Lite) + 500.000/Tag (Chat/Thinking) während der öffentlichen Beta. OpenAI-kompatibel, Standard-Bearer-Authentifizierung. -**feat(providers/pollinations)**: Pollinations AI („pol/“) hinzufügen – kein API-Schlüssel erforderlich. Proxys GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 Anforderung/15 Sek. kostenlos). Der benutzerdefinierte Executor übernimmt die optionale Authentifizierung. -**feat(providers/cloudflare-ai)**: Cloudflare Workers AI hinzufügen (`cf/`) – 10.000 Neuronen/Tag kostenlos (~150 LLM-Antworten oder 500 Sekunden Whisper-Audio). Über 50 Modelle am globalen Rand. Der benutzerdefinierte Executor erstellt aus den Anmeldeinformationen eine dynamische URL mit „accountId“. -**feat(providers/scaleway)**: Scaleway Generative APIs hinzufügen („scw/“) – 1 Million kostenlose Token für neue Konten. EU/DSGVO-konform (Paris). Qwen3 235B, Lama 3.1 70B, Mistral Small 3.2. -**feat(providers/aimlapi)**: KI/ML-API hinzufügen („aiml/“) – 0,025 $/Tag kostenloses Guthaben, 200+ Modelle (GPT-4o, Claude, Gemini, Llama) über einen einzigen Aggregator-Endpunkt.### 🔄 Provider Updates\n\n-**feat(providers/together)**: „hasFree: true“ + 3 dauerhaft kostenlose Modell-IDs hinzufügen: „Llama-3.3-70B-Instruct-Turbo-Free“, „Llama-Vision-Free“, „DeepSeek-R1-Distill-Llama-70B-Free“. -**feat(providers/gemini)**: „hasFree: true“ + „freeNote“ hinzufügen (1.500 req/Tag, keine Kreditkarte erforderlich, aistudio.google.com) -**chore(providers/gemini)**: Benennen Sie den Anzeigenamen aus Gründen der Übersichtlichkeit in „Gemini (Google AI Studio)“ um### ⚙️ Infrastructure\n\n-**feat(executors/pollinations)**: Neuer „PollinationsExecutor“ – lässt den „Authorization“-Header weg, wenn kein API-Schlüssel bereitgestellt wird -**feat(executors/cloudflare-ai)**: Neuer „CloudflareAIExecutor“ – dynamische URL-Konstruktion erfordert „accountId“ in den Provider-Anmeldeinformationen -**feat(executors)**: Registrieren Sie die Executor-Zuordnungen „pollinations“, „pol“, „cloudflare-ai“ und „cf“.### Dokumentation\n\n-**docs(readme)**: Kostenloser Combo-Stack auf 11 Anbieter erweitert (für immer 0 $) -**docs(readme)**: 4 neue kostenlose Anbieterabschnitte (LongCat, Pollinations, Cloudflare AI, Scaleway) mit Modelltabellen hinzugefügt -**docs(readme)**: Aktualisierte Preistabelle mit 4 neuen Zeilen für kostenlose Kontingente -**docs(i18n/pt-BR)**: Aktualisierte Preistabelle + Abschnitte „LongCat/Pollinations/Cloudflare AI/Scaleway“ auf Portugiesisch hinzugefügt -**docs(new-features/ai)**: 10 Aufgabenspezifikationsdateien + Master-Implementierungsplan in „docs/new-features/ai/“.### 🧪 Tests\n\n- Testsuite:**821 Tests, 0 Fehler**(unverändert)---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Medientranskription (Deepgram/HuggingFace Content-Type, Spracherkennung) und TTS-Fehleranzeige behoben.### 🐛 Bug Fixes\n\n-**Fix(Transkription)**: Die Audiotranskription von Deepgram und HuggingFace ordnet jetzt „video/mp4“ → „audio/mp4“ und andere Medien-MIME-Typen über den neuen „resolveAudioContentType()“-Helfer korrekt zu. Bisher wurde beim Hochladen von „.mp4“-Dateien immer die Meldung „Keine Sprache erkannt“ zurückgegeben, da Deepgram „Content-Type: video/mp4“ empfing. -**Fix(Transkription)**: „detect_lingual=true“ zu Deepgram-Anfragen hinzugefügt – erkennt automatisch die Audiosprache (Portugiesisch, Spanisch usw.), anstatt standardmäßig Englisch zu verwenden. Behebt, dass nicht-englische Transkriptionen leere oder fehlerhafte Ergebnisse zurückgeben. -**fix(transcription)**: „punctuate=true“ zu Deepgram-Anfragen hinzugefügt, um eine qualitativ hochwertigere Transkriptionsausgabe mit korrekter Interpunktion zu ermöglichen. -**fix(tts)**: Fehleranzeige „[object Object]“ in Text-to-Speech-Antworten sowohl in „audioSpeech.ts“ als auch in „audioTranscription.ts“ behoben. Die Funktion „upstreamErrorResponse()“ extrahiert jetzt korrekt verschachtelte Zeichenfolgenmeldungen von Anbietern wie ElevenLabs, die „{ error: { message: „...“, status_code: 401 } }“ anstelle einer flachen Fehlerzeichenfolge zurückgeben.### 🧪 Tests\n\n- Testsuite:**821 Tests, 0 Fehler**(unverändert)### Triaged Issues\n\n-**#508**– Regression des Tool-Aufrufformats: angeforderte Proxy-Protokolle und Provider-Chain-Informationen („needs-info“) -**#510**– Windows CLI-Integritätsprüfungspfad: angeforderte Shell-/Knotenversionsinformationen („needs-info“) -**#485**– Kiro MCP-Tool-Aufrufe: als externes Kiro-Problem geschlossen (nicht OmniRoute) -**#442**– Baseten /models-Endpunkt: geschlossen (dokumentierte manuelle Problemumgehung) -**#464**– Schlüsselbereitstellungs-API: als Roadmap-Element anerkannt---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: SSE-OmniModel-Datenverlust beheben, protokollspezifische Modellkompatibilität zusammenführen.### Bug Fixes\n\n-**#511**– Kritisch: Das Tag „“ wurde nach „finish_reason:stop“ in SSE-Streams gesendet, was zu Datenverlust führte. Das Tag wird jetzt in den ersten nicht leeren Inhaltsblock eingefügt und garantiert so die Zustellung, bevor SDKs die Verbindung schließen.### Merged PRs\n\n-**PR #512**(@zhangqiang8vip): Pro-Protokoll-Modellkompatibilität – „normalizeToolCallId“ und „preserveOpenAIDeveloperRole“ können jetzt pro Client-Protokoll konfiguriert werden (OpenAI, Claude, Responses API). Neues Feld „compatByProtocol“ in der Modellkonfiguration mit Zod-Validierung.### Triaged Issues\n\n-**#510**– Windows CLI healthcheck_failed: PATH/Versionsinformationen angefordert -**#509**– Turbopack Electron-Regression: Upstream-Next.js-Fehler, dokumentierte Problemumgehungen -**#508**– macOS schwarzer Bildschirm: vorgeschlagene Problemumgehung „--disable-gpu“.---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Plattformübergreifender MachineId-Fix, Ratenbegrenzungen pro API-Schlüssel, Streaming-Kontext-Cache, Alibaba DashScope, Suchanalyse, ZWS v5 und 8 Probleme behoben.### ✨ New Features\n\n-**feat(search)**: Registerkarte „Suchanalyse“ in „/dashboard/analytics“ – Anbieteraufschlüsselung, Cache-Trefferquote, Kostenverfolgung. Neue API: `GET /api/v1/search/analytics` (#feat/search-provider-routing) -**feat(provider)**: Alibaba Cloud DashScope mit benutzerdefinierter Endpunktpfadvalidierung hinzugefügt – konfigurierbarer „chatPath“ und „modelsPath“ pro Knoten (#feat/custom-endpoint-paths) -**feat(api)**: Grenzwerte für die Anforderungsanzahl pro API-Schlüssel – Spalten „max_requests_per_day“ und „max_requests_per_minute“ mit In-Memory-Slide-Window-Erzwingung, die HTTP 429 zurückgibt (#452) -**feat(dev)**: ZWS v5 – HMR-Leck-Fix (485 DB-Verbindungen → 1), Speicher 2,4 GB → 195 MB, „globalThis“-Singletons, Edge Runtime-Warnungsfix (@zhangqiang8vip)### 🐛 Bug Fixes\n\n-**fix(#506)**: Plattformübergreifende „machineId“ – „getMachineIdRaw()“ mit Try/Catch-Wasserfall neu geschrieben (Windows REG.exe → macOS ioreg → Linux-Datei lesen → Hostname → „os.hostname()“). Beseitigt die „process.platform“-Verzweigung, die durch den Dead-Code des Next.js-Bundlers eliminiert wurde, und behebt, dass „head“ unter Windows nicht erkannt wird. Behebt auch #466. -**Fix(#493)**: Benutzerdefinierte Benennung von Anbietermodellen – falsche Präfixentfernung in „DefaultExecutor.transformRequest()“ entfernt, die organisationsbezogene Modell-IDs wie „zai-org/GLM-5-FP8“ verstümmelte. -**fix(#490)**: Streaming + Kontext-Cache-Schutz – „TransformStream“ fängt SSE ab, um das Tag „“ vor der Markierung „[DONE]“ einzufügen, wodurch der Kontext-Cache-Schutz für Streaming-Antworten aktiviert wird. -**fix(#458)**: Kombinierte Schemavalidierung – Die Felder „system_message“, „tool_filter_regex“, „context_cache_protection“ bestehen jetzt beim Speichern die Zod-Validierung. -**fix(#487)**: Bereinigung der KIRO MITM-Karte – ZWS_README entfernt, „AntigravityToolCard“ generiert, um dynamische Werkzeugmetadaten zu verwenden.### 🧪 Tests\n\n- Filtereinheitstests für Tools im Anthropic-Format hinzugefügt (PR #397) – 8 Regressionstests für „tool.name“ ohne „.function“-Wrapper\n- Testsuite:**821 Tests, 0 Fehler**(von 813)### 📋 Issues Closed (8)\n\n-**#506**– Windows-Maschinen-ID „head“ nicht erkannt (behoben) -**#493**– Benutzerdefinierte Benennung des Anbietermodells (behoben) -**#490**– Streaming-Kontext-Cache (behoben) -**#452**– Anforderungslimits pro API-Schlüssel (implementiert) -**#466**– Windows-Anmeldefehler (gleiche Grundursache wie #506) -**#504**– MITM inaktiv (erwartetes Verhalten) -**#462**– Gemini CLI PSA (behoben) -**#434**– Absturz der Electron-App (Duplikat von #402)## [2.8.9] — 2026-03-20\n\n> Sprint: Community-PRs zusammenführen, KIRO MITM-Karte reparieren, Abhängigkeitsaktualisierungen.### Merged PRs\n\n-**PR #498**(@Sajid11194): Absturz der Windows-Maschinen-ID behoben (`undefiniert\\REG.exe`). Ersetzt „node-machine-id“ durch native Betriebssystem-Registrierungsabfragen.**Schließt #486.** -**PR #497**(@zhangqiang8vip): Behebung von HMR-Ressourcenlecks im Entwicklungsmodus – 485 geleakte DB-Verbindungen → 1, Speicher 2,4 GB → 195 MB. „globalThis“-Singletons, Edge Runtime-Warnungskorrektur, Windows-Teststabilität. (+1168/-338 über 22 Dateien) -**PRs #499-503**(Dependabot): GitHub Actions-Updates – „docker/build-push-action@7“, „actions/checkout@6“, „peter-evans/dockerhub-description@5“, „docker/setup-qemu-action@4“, „docker/login-action@4“.### Bug Fixes\n\n-**#505**– Die KIRO MITM-Karte zeigt jetzt werkzeugspezifische Anweisungen („api.anthropic.com“) anstelle von Antigravity-spezifischem Text an.\n–**#504**– Antwort mit UX-Klarstellung (MITM „Inaktiv“ ist das erwartete Verhalten, wenn der Proxy nicht ausgeführt wird).---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Absturz des OAuth-Batch-Tests behoben, Schaltfläche „Alle testen“ zu einzelnen Anbieterseiten hinzugefügt.### Bug Fixes\n\n-**OAuth-Batch-Test-Absturz**(ERR_CONNECTION_REFUSED): Sequentielle For-Schleife durch 5-Verbindungs-Parallelitätsbeschränkung + 30 Sekunden Zeitüberschreitung pro Verbindung über „Promise.race()“ + „Promise.allSettled()“ ersetzt. Verhindert Serverabstürze beim Testen großer OAuth-Anbietergruppen (ca. 30+ Verbindungen).### Funktionen\n\n-**Schaltfläche „Alle testen“ auf Anbieterseiten**: Auf einzelnen Anbieterseiten (z. B. „/providers/codex“) wird jetzt die Schaltfläche „Alle testen“ in der Kopfzeile „Verbindungen“ angezeigt, wenn mehr als zwei Verbindungen vorhanden sind. Verwendet „POST /api/providers/test-batch“ mit „{mode: „provider“,providerId}“. Die Ergebnisse werden modal mit Gut/Schlecht-Zusammenfassung und Diagnose pro Verbindung angezeigt.---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: PR Nr. 495 zusammenführen (Flaschenhals 429 fallen lassen), Nr. 496 beheben (Anbieter benutzerdefinierter Einbettung), Triage-Funktionen.### Bug Fixes\n\n-**Engpass 429 unendliches Warten**(PR #495 von @xandr0s): Bei 429 schlägt `limiter.stop({ dropWaitingJobs: true })` alle in der Warteschlange befindlichen Anfragen sofort fehl, sodass Upstream-Aufrufer einen Fallback auslösen können. Der Limiter wird aus der Karte gelöscht, sodass bei der nächsten Anfrage eine neue Instanz erstellt wird. -**Benutzerdefinierte Einbettungsmodelle nicht auflösbar**(#496): „POST /v1/embeddings“ löst jetzt benutzerdefinierte Einbettungsmodelle von ALLEN Anbieterknoten auf (nicht nur von localhost). Ermöglicht das Hinzufügen von Modellen wie „google/gemini-embedding-001“ über das Dashboard.### Issues Responded\n\n-**#452**– Grenzwerte für die Anzahl der Anfragen pro API-Schlüssel (bestätigt, auf Roadmap) -**#464**– Automatische Ausgabe von API-Schlüsseln mit Anbieter-/Kontobeschränkungen (benötigt weitere Details) -**#488**– Modelllisten automatisch aktualisieren (bestätigt, auf Roadmap) -**#496**– Benutzerdefinierte Auflösung des Einbettungsanbieters (behoben)---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: PR #494 zusammenführen (MiniMax-Rollenkorrektur), KIRO MITM-Dashboard reparieren, 8 Probleme prüfen.### Funktionen\n\n-**MiniMax-Entwickler→Systemrollenkorrektur**(PR #494 von @zhangqiang8vip): Umschalten zwischen „preserveDeveloperRole“ pro Modell. Fügt die Benutzeroberfläche „Kompatibilität“ auf der Anbieterseite hinzu. Behebt 422 „Rollenparam-Fehler“ für MiniMax und ähnliche Gateways. -**roleNormalizer**: „normalizeDeveloperRole()“ akzeptiert jetzt den Parameter „preserveDeveloperRole“ mit Tri-State-Verhalten (undefiniert=behalten, wahr=behalten, falsch=konvertieren). -**DB**: Neues „getModelPreserveOpenAIDeveloperRole()“ und „mergeModelCompatOverride()“ in „models.ts“.### Bug Fixes\n\n-**KIRO MITM-Dashboard**(#481/#487): „CLIToolsPageClient“ leitet jetzt jedes „configType: „mitm““-Tool an „AntigravityToolCard“ weiter (MITM-Start-/Stopp-Steuerelemente). Bisher war nur Antigravity fest codiert. -**AntigravityToolCard generisch**: Verwendet „tool.image“, „tool.description“, „tool.id“ anstelle von fest codierten Antigravity-Werten. Schützt vor fehlenden „defaultModels“.### Cleanup\n\n- „ZWS_README_V2.md“ entfernt (nur Entwicklungsdokumente aus PR #494).### Issues Triaged (8)\n\n-**#487**– Geschlossen (KIRO MITM in dieser Version behoben) -**#486**– Needs-Info (Windows REG.exe PATH-Problem) -**#489**– Needs-Info (Antigravity-Projekt-ID fehlt, OAuth-Neuverbindung erforderlich) -**#492**– Needs-Info (app/server.js fehlt auf schlecht verwaltetem Knoten) -**#490**– Bestätigt (Streaming + Kontext-Cache-Blockierung, Korrektur geplant) -**#491**– Bestätigt (Inkonsistenz des Codex-Authentifizierungsstatus) -**#493**– Bestätigt (Präfix für den Modellnamen des modalen Anbieters, Problemumgehung bereitgestellt) -**#488**– Rückstand bei Funktionsanfragen (Modelllisten automatisch aktualisieren)---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Behebung von Zombie-SSE-Streams, Kontext-Cache-First-Turn, KIRO MITM und Triage 5 externer Probleme.### Bug Fixes\n\n-**Zombie SSE Streams**(#473): Reduzieren Sie „STREAM_IDLE_TIMEOUT_MS“ von 300 → 120 Sekunden für einen schnelleren Combo-Fallback, wenn Anbieter mitten im Stream hängen bleiben. Konfigurierbar über env var. -**Context-Cache-Tag**(#474): „injectModelTag()“ wurde korrigiert, um First-Turn-Anfragen zu verarbeiten (keine Assistentenmeldungen) – der Kontext-Cache-Schutz funktioniert jetzt ab der allerersten Antwort. -**KIRO MITM**(#481): KIRO `configType` von `guide` → `mitm` ändern, damit das Dashboard MITM-Start/Stopp-Steuerelemente darstellt. -**E2E-Test**(CI): Korrigieren Sie „providers-bailian-coding-plan.spec.ts“ – schließen Sie die bereits vorhandene modale Überlagerung, bevor Sie auf die Schaltfläche „API-Schlüssel hinzufügen“ klicken.### Closed Issues\n\n- #473 – Zombie-SSE-Streams umgehen Combo-Fallback\n- #474 – Kontext-Cache-Tag „“ fehlt beim ersten Durchgang\n- #481 – MITM für KIRO kann nicht über das Dashboard aktiviert werden\n- #468 – Gemini-CLI-Remoteserver (ersetzt durch #462 veraltet)\n- #438 – Claude kann keine Dateien schreiben (externes CLI-Problem)\n- #439 – AppImage funktioniert nicht (dokumentierte Problemumgehung für libfuse2)\n- #402 – ARM64 DMG „beschädigt“ (dokumentierte xattr -cr Problemumgehung)\n- #460 – CLI kann unter Windows nicht ausgeführt werden (dokumentierter PATH-Fix)---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Abschaffung der Gemini-CLI, Korrektur des VM-Leitfadens i18n, Korrektur der Abhängigkeitssicherheit, Erweiterung des Anbieterschemas.### Funktionen\n\n-**Gemini CLI-Veraltung**(#462): Markieren Sie den Anbieter „gemini-cli“ als veraltet mit Warnung – Google schränkt die OAuth-Nutzung durch Drittanbieter ab März 2026 ein -**Anbieterschema**(#462): Erweitern Sie die Zod-Validierung mit den optionalen Feldern „deprecated“, „deprecationReason“, „hasFree“, „freeNote“, „authHint“, „apiHint“.### Bug Fixes\n\n-**VM Guide i18n**(#471): „VM_DEPLOYMENT_GUIDE.md“ zur i18n-Übersetzungspipeline hinzufügen, alle 30 Gebietsschemaübersetzungen aus der englischen Quelle neu generieren (blieben auf Portugiesisch hängen)### Sicherheit\n\n-**deps**: Bump „abgeflacht“ 3.3.3 → 3.4.2 – behebt CWE-1321-Prototypverschmutzung (#484, @dependabot)### Closed Issues\n\n- #472 – Modell-Aliase-Regression (behoben in Version 2.8.2)\n- #471 – Übersetzungen des VM-Leitfadens fehlerhaft\n- #483 – Nachgestelltes „data: null“ nach „[DONE]“ (behoben in v2.8.3)### Merged PRs\n\n- #484 – deps: Beule von 3.3.3 auf 3.4.2 abgeflacht (@dependabot)---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Tschechisch i18n, Korrektur des SSE-Protokolls, Übersetzung des VM-Leitfadens.### Funktionen\n\n-**Tschechische Sprache**(#482): Vollständiges Tschechisch (cs) i18n – 22 Dokumente, 2606 UI-Strings, Sprachumschalter-Updates (@zen0bit) -**VM-Bereitstellungshandbuch**: Vom Portugiesischen ins Englische als Quelldokument übersetzt (@zen0bit)### Bug Fixes\n\n-**SSE-Protokoll**(#483): Nach dem Signal „[DONE]“ kein nachgestelltes „data: null“ senden – behebt „AI_TypeValidationError“ in strikten AI SDK-Clients (Zod-basierte Validatoren)### Merged PRs\n\n- #482 – Tschechische Sprache hinzufügen + VM_DEPLOYMENT_GUIDE.md englische Quelle korrigieren (@zen0bit)---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 zusammengeführte PRs, Korrektur des Modell-Aliase-Routings, Protokollexport und Problemtriage.### Funktionen\n\n-**Protokollexport**: Neue Schaltfläche „Exportieren“ unter „/dashboard/logs“ mit Dropdown-Liste für den Zeitbereich (1 Std., 6 Std., 12 Std., 24 Std.). Lädt JSON von Anfrage-/Proxy-/Anrufprotokollen über die API „/api/logs/export“ herunter (#user-request)### Bug Fixes\n\n-**Modell-Aliase-Routing**(#472): Einstellungen → Modell-Aliase wirken sich jetzt korrekt auf das Provider-Routing aus, nicht nur auf die Formaterkennung. Bisher wurde die Ausgabe von „resolveModelAlias()“ nur für „getModelTargetFormat()“ verwendet, aber die ursprüngliche Modell-ID wurde an den Anbieter gesendet -**Stream-Flush-Nutzung**(#480): Nutzungsdaten vom letzten SSE-Ereignis im Puffer werden jetzt während des Stream-Flush korrekt extrahiert (zusammengeführt von @prakersh)### Merged PRs\n\n- #480 – Nutzung aus verbleibendem Puffer im Flush-Handler extrahieren (@prakersh)\n- #479 – Fehlende Preiseinträge für Codex 5.3/5.4 und Anthropic-Modell-ID hinzufügen (@prakersh)---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Fünf Community-PRs – Fehlerbehebungen für Streaming-Anrufprotokolle, Kiro-Kompatibilität, Cache-Token-Analyse, chinesische Übersetzung und konfigurierbare Tool-Anruf-IDs.### Funktionen\n\n-**feat(logs)**: Anrufprotokoll-Antwortinhalte werden jetzt vor der Übersetzung korrekt aus rohen Anbieterblöcken (OpenAI/Claude/Gemini) akkumuliert, wodurch leere Antwortnutzlasten im Streaming-Modus behoben werden (#470, @zhangqiang8vip) -**feat(providers)**: Pro Modell konfigurierbare 9-Zeichen-Tool-Aufruf-ID-Normalisierung (Mistral-Stil) – nur Modelle mit aktivierter Option erhalten abgeschnittene IDs (#470) -**feat(api)**: Schlüssel-PATCH-API erweitert, um die Felder „allowedConnections“, „name“, „autoResolve“, „isActive“ und „accessSchedule“ zu unterstützen (#470) -**feat(dashboard)**: Response-First-Layout in der Benutzeroberfläche für Anforderungsprotokolldetails (#470) -**feat(i18n)**: Verbesserte chinesische (zh-CN) Übersetzung – vollständige Neuübersetzung (#475, @only4copilot)### 🐛 Bug Fixes\n\n-**fix(kiro)**: Eingefügtes „Modell“-Feld aus Anforderungstext entfernen – Kiro-API lehnt unbekannte Felder der obersten Ebene ab (#478, @prakersh) -**Fix(Nutzung)**: Beziehen Sie Cache-Lese- und Cache-Erstellungs-Tokens in die Eingabesummen des Nutzungsverlaufs ein, um eine genaue Analyse zu ermöglichen (#477, @prakersh) -**fix(callLogs)**: Unterstützt Claude-Format-Nutzungsfelder („input_tokens“/„output_tokens“) neben dem OpenAI-Format und schließt alle Cache-Token-Varianten ein (#476, @prakersh)---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan-Anbieter mit bearbeitbaren Basis-URLs sowie Community-Beiträgen für Alibaba Cloud und Kimi Coding.### Funktionen\n\n-**feat(providers)**: Bailian Coding Plan („bailian-coding-plan“) hinzugefügt – Alibaba Model Studio mit Anthropic-kompatibler API. Statischer Katalog mit 8 Modellen, darunter Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5 und Kimi K2.5. Beinhaltet eine benutzerdefinierte Authentifizierungsvalidierung (400=gültig, 401/403=ungültig) (#467, @Mind-Dragon) -**feat(admin)**: Bearbeitbare Standard-URL im Provider Admin zum Erstellen/Bearbeiten von Flows – Benutzer können benutzerdefinierte Basis-URLs pro Verbindung konfigurieren. Bleibt in „providerSpecificData.baseUrl“ bestehen, wobei die Zod-Schemavalidierung Nicht-http(s)-Schemata ablehnt (#467)### 🧪 Tests\n\n– Über 30 Unit-Tests und 2 E2E-Szenarien für den Bailian Coding Plan-Anbieter hinzugefügt, die Authentifizierungsvalidierung, Schema-Härtung, Verhalten auf Routenebene und schichtübergreifende Integration abdecken---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Zwei neue von der Community bereitgestellte Anbieter (Alibaba Cloud Coding, Kimi Coding API-Key) und Docker-Pino-Fix.### Funktionen\n\n-**feat(providers)**: Unterstützung für Alibaba Cloud Coding Plan mit zwei OpenAI-kompatiblen Endpunkten hinzugefügt – „alicode“ (China) und „alicode-intl“ (International), jeweils mit 8 Modellen (#465, @dtk1985) -**feat(providers)**: Dedizierter Anbieterpfad „kimi-coding-apikey“ hinzugefügt – API-schlüsselbasierter Kimi-Coding-Zugriff wird nicht mehr über die reine OAuth-Route „kimi-coding“ erzwungen. Beinhaltet Registrierung, Konstanten, Modell-API, Konfiguration und Validierungstest (#463, @Mind-Dragon)### 🐛 Bug Fixes\n\n-**fix(docker)**: Fehlende „split2“-Abhängigkeit zum Docker-Image hinzugefügt – „pino-abstract-transport“ benötigt sie zur Laufzeit, wurde aber nicht in den eigenständigen Container kopiert, was zu Abstürzen mit „Modul „split2“ kann nicht gefunden werden“ führt (#459)---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Subpfad-Passthrough für Codex-Antworten wird nativ unterstützt, Windows MITM-Absturz behoben und Combos-Agent-Schemata angepasst.### Funktionen\n\n-**feat(codex)**: Subpath-Passthrough für native Antworten für Codex – leitet „POST /v1/responses/compact“ nativ an den Codex-Upstream weiter, wobei die Claude-Code-Kompatibilität gewahrt bleibt, ohne das Suffix „/compact“ zu entfernen (#457)### 🐛 Bug Fixes\n\n-**fix(combos)**: Zod-Schemas („updateComboSchema“ und „createComboSchema“) enthalten jetzt „system_message“, „tool_filter_regex“ und „context_cache_protection“. Behebt einen Fehler, bei dem agentenspezifische Einstellungen, die über das Dashboard erstellt wurden, stillschweigend von der Backend-Validierungsschicht verworfen wurden (#458) -**fix(mitm)**: Absturz des Kiro MITM-Profils unter Windows behoben – „node-machine-id“ schlug aufgrund fehlender „REG.exe“-Umgebung fehl und der Fallback löste einen schwerwiegenden „Krypto ist nicht definiert“-Fehler aus. Fallback importiert Krypto jetzt sicher und korrekt (#456)---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budgetsparfehler + Combo-Agent-Funktionen UI + OmniModel-Tag-Sicherheitskorrektur.### 🐛 Bug Fixes\n\n-**fix(budget)**: „Save Limits“ gibt nicht mehr 422 zurück – „warningThreshold“ wird jetzt korrekt als Bruch (0–1) statt als Prozentsatz (0–100) gesendet (#451) -**fix(combos)**: Das interne Cache-Tag „“ wird jetzt entfernt, bevor Anfragen an Anbieter weitergeleitet werden, wodurch Cache-Sitzungsunterbrechungen verhindert werden (#454)### Funktionen\n\n-**feat(combos)**: Abschnitt „Agent-Funktionen“ zum Combo-Erstellungs-/Bearbeitungsmodal hinzugefügt – „system_message“-Override, „tool_filter_regex“ und „context_cache_protection“ direkt über das Dashboard verfügbar machen (#454)---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker-Pino-Absturz, Codex-CLI-Antwort-Worker-Fix, Paketsperrsynchronisierung.### 🐛 Bug Fixes\n\n-**fix(docker)**: „pino-abstract-transport“ und „pino-pretty“ werden jetzt explizit in der Docker-Runner-Phase kopiert – Next.js Standalone-Trace verfehlt diese Peer-Deps, was beim Start zum Absturz „Modul pino-abstract-transport kann nicht gefunden werden“ führt (#449) -**fix(responses)**: „initTranslators()“ aus der Route „/v1/responses“ entfernen – stürzte den Next.js-Worker mit der uncaughtException „der Worker wurde beendet“ bei Codex-CLI-Anfragen ab (#450)### 🔧 Maintenance\n\n-**chore(deps)**: „package-lock.json“ wird jetzt bei jeder Versionserhöhung festgeschrieben, um sicherzustellen, dass Docker „npm ci“ genaue Abhängigkeitsversionen verwendet---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX-Verbesserungen und Fehlerbehebung bei der Windows CLI-Gesundheitsprüfung.### 🐛 Bug Fixes\n\n-**fix(ux)**: Hinweis zum Standardpasswort auf der Anmeldeseite anzeigen – neue Benutzer sehen jetzt „Standardpasswort: 123456“ unter der Passworteingabe (#437) -**fix(cli)**: Claude CLI und andere von npm installierte Tools werden jetzt korrekt als ausführbar unter Windows erkannt – Spawn verwendet „shell:true“, um „.cmd“-Wrapper über PATHEXT aufzulösen (#447)---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Suchtools-Dashboard, i18n-Korrekturen, Copilot-Grenzwerte, Serper-Validierungskorrektur.### Funktionen\n\n-**feat(search)**: Search Playground hinzufügen (10. Endpunkt), Suchtools-Seite mit Anbieter vergleichen/Reranking-Pipeline/Suchverlauf, lokales Reranking-Routing, Auth Guards auf der Such-API (#443 von @Regis-RCR)\n\n- Neue Route: „/dashboard/search-tools“.\n – Seitenleisteneintrag im Abschnitt „Debuggen“.\n- „GET /api/search/providers“ und „GET /api/search/stats“ mit Authentifizierungsschutz\n- Lokales Provider_Nodes-Routing für „/v1/rerank“.\n- Über 30 i18n-Schlüssel im Such-Namespace### 🐛 Bug Fixes\n\n-**fix(search)**: Brave News Normalizer reparieren (gab 0 Ergebnisse zurück), max_results-Kürzung nach der Normalisierung erzwingen, Endpoints-Seitenabruf-URL korrigieren (#443 von @Regis-RCR) -**fix(analytics)**: Analysetags-/Datumsbezeichnungen lokalisieren – hartcodierte portugiesische Zeichenfolgen durch „Intl.DateTimeFormat(locale)“ ersetzen (#444 von @hijak) -**fix(copilot)**: Korrekte Anzeige des GitHub Copilot-Kontotyps, irreführende unbegrenzte Kontingentzeilen aus dem Limits-Dashboard filtern (#445 von @hijak) -**Fix(Anbieter)**: Keine gültigen Serper-API-Schlüssel mehr ablehnen – Nicht-4xx-Antworten als gültige Authentifizierung behandeln (#446 von @hijak)---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex Direct API-Kontingent-Fallback-Fix.### 🐛 Bug Fixes\n\n-**fix(codex)**: Wöchentlich erschöpfte Konten im direkten API-Fallback blockieren (#440)\n\n- „resolveQuotaWindow()“-Präfixübereinstimmung: „weekly“ stimmt jetzt mit „weekly (7d)“-Cache-Schlüsseln überein\n- „applyCodexWindowPolicy()“ erzwingt die korrekte Umschaltung von „useWeekly“/„use5h“.\n- 4 neue Regressionstests (insgesamt 766)---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Korrekturen des UI-Kontrasts im Lichtmodus.### 🐛 Bug Fixes\n\n-**fix(logs)**: Kontrast des Lichtmodus in den Filterschaltflächen und dem Combo-Badge für Anforderungsprotokolle korrigiert (#378)\n\n- Die Filterschaltflächen „Fehler/Erfolg/Kombination“ sind jetzt im Lichtmodus lesbar\n- Das Combo-Reihenabzeichen verwendet im Lichtmodus ein stärkeres Violett---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Einheitliches Websuchrouting (POST /v1/search) mit 5 Anbietern + Next.js 16.1.7-Sicherheitsfixes (6 CVEs).### ✨ New Features\n\n-**feat(search)**: Einheitliches Web-Suchrouting – „POST /v1/search“ mit 5 Anbietern (Serper, Brave, Perplexity, Exa, Tavily)\n\n- Automatisches Failover zwischen Anbietern, über 6.500 kostenlose Suchvorgänge pro Monat\n- In-Memory-Cache mit Anforderungszusammenführung (konfigurierbare TTL)\n- Dashboard: Registerkarte „Suchanalyse“ in „/dashboard/analytics“ mit Anbieteraufschlüsselung, Cache-Trefferquote und Kostenverfolgung\n- Neue API: `GET /api/v1/search/analytics` für Suchanfragenstatistiken\n- DB-Migration: Spalte „request_type“ in „call_logs“ für die Verfolgung von Nicht-Chat-Anfragen\n- Zod-Validierung (`v1SearchSchema`), authentifiziert, Kosten erfasst über `recordCost()`### Sicherheit\n\n-**deps**: Next.js 16.1.6 → 16.1.7 – behebt 6 CVEs: -**Kritisch**: CVE-2026-29057 (Schmuggel von HTTP-Anfragen über http-Proxy) -**Hoch**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Serveraktionen) -**Mittel**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7### 📁 New Files\n\n| Datei | Zweck |\n| ---------------------------------------------------------------- | ------------------------------------------------------------------ | --- |\n| `open-sse/handlers/search.ts` | Suchhandler mit 5-Provider-Routing |\n| `open-sse/config/searchRegistry.ts` | Anbieterregistrierung (Authentifizierung, Kosten, Kontingent, TTL) |\n| `open-sse/services/searchCache.ts` | In-Memory-Cache mit Anforderungszusammenführung |\n| `src/app/api/v1/search/route.ts` | Next.js-Route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Suchstatistik-API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Registerkarte „Analyse-Dashboard“ |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB-Migration |\n| `tests/unit/search-registry.test.mjs` | 277 Zeilen Unit-Tests | --- |\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: Von ClawRouter inspirierte Funktionen – ToolCalling-Flag, mehrsprachige Absichtserkennung, Benchmark-gesteuerter Fallback, Anforderungsdeduplizierung, steckbare RouterStrategy, Preise für Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5.### ✨ New Models & Pricing\n\n-**Feature(Preise)**: xAI Grok-4 Fast – „0,20 $/0,50 $ pro 1 Mio. Token“, 1143 ms p50-Latenz, Tool-Aufruf unterstützt -**Leistung(Preis)**: xAI Grok-4 (Standard) – „0,20 $/1,50 $ pro 1 Mio. Token“, logisches Flaggschiff -**feat(pricing)**: GLM-5 über Z.AI – „0,5 $/1 Mio.“, 128.000 Ausgabekontext -**Leistung(Preise)**: MiniMax M2.5 – „Eingabe von 0,30 $/1 Mio.“, Argumentation + Agentenaufgaben -**feat(pricing)**: DeepSeek V3.2 – aktualisierter Preis „0,27 $/1,10 $ pro 1 Mio.“ -**Feature(Preise)**: Kimi K2.5 über Moonshot API – direkter Moonshot API-Zugriff -**feat(providers)**: Z.AI-Anbieter hinzugefügt (`zai`-Alias) – GLM-5-Familie mit 128K-Ausgabe### 🧠 Routing Intelligence\n\n-**feat(registry)**: „toolCalling“-Flag pro Modell in der Provider-Registrierung – Combos können jetzt Modelle bevorzugen/erfordern, die Tool-Calling-fähig sind -**feat(scoring)**: Mehrsprachige Absichtserkennung für AutoCombo-Scoring – PT/ZH/ES/AR-Skript-/Sprachmuster beeinflussen die Modellauswahl pro Anforderungskontext -**feat(fallback)**: Benchmark-gesteuerte Fallback-Ketten – echte Latenzdaten (S. 50 von „comboMetrics“), die zur dynamischen Neuordnung der Fallback-Priorität verwendet werden -**feat(dedup)**: Deduplizierung über Content-Hash anfordern – 5-Sekunden-Idempotenzfenster verhindert, dass doppelte Anbieteraufrufe Clients erneut versuchen -**feat(router)**: Pluggable „RouterStrategy“-Schnittstelle in „autoCombo/routerStrategy.ts“ – benutzerdefinierte Routing-Logik kann ohne Änderung des Kerns eingefügt werden### 🔧 MCP Server Improvements\n\n-**feat(mcp)**: 2 neue erweiterte Tool-Schemata: „omniroute_get_provider_metrics“ (p50/p95/p99 pro Anbieter) und „omniroute_explain_route“ (Erklärung der Routing-Entscheidung)\n–**feat(mcp)**: MCP-Tool-Authentifizierungsbereiche aktualisiert – „metrics:read“-Bereich für Anbietermetrik-Tools hinzugefügt -**feat(mcp)**: „omniroute_best_combo_for_task“ akzeptiert jetzt den Parameter „LanguageHint“ für mehrsprachiges Routing### 📊 Observability\n\n-**feat(metrics)**: „comboMetrics.ts“ erweitert um Echtzeit-Latenzperzentilverfolgung pro Anbieter/Konto -**feat(health)**: Die Health-API („/api/monitoring/health“) gibt jetzt die Felder „p50Latency“ und „errorRate“ pro Anbieter zurück -**feat(usage)**: Migration des Nutzungsverlaufs für die Latenzverfolgung pro Modell### 🗄️ DB Migrations\n\n-**feat(migrations)**: Neue Spalte „latency_p50“ in der Tabelle „combo_metrics“ – null-brechend, sicher für bestehende Benutzer### 🐛 Bug Fixes / Closures\n\n-**close(#411)**: bessere Auflösung des SQLite3-Hash-Moduls unter Windows – behoben in v2.6.10 (f02c5b5) -**close(#409)**: GitHub Copilot-Chat-Abschlüsse schlagen mit Claude-Modellen fehl, wenn Dateien angehängt werden – behoben in v2.6.9 (838f1d6) -**close(#405)**: Duplikat von #411 – behoben## [2.6.10] — 2026-03-17\n\n> Windows-Fix: Better-SQLite3 vorgefertigter Download ohne Node-Gyp/Python/MSVC (#426).### 🐛 Bug Fixes\n\n-**fix(install/#426)**: Unter Windows schlug „npm install -g omniroute“ mit „better_sqlite3.node ist keine gültige Win32-Anwendung“ fehl, da die gebündelte native Binärdatei für Linux kompiliert wurde. Fügt**Strategie 1.5**zu „scripts/postinstall.mjs“ hinzu: verwendet „@mapbox/node-pre-gyp install --fallback-to-build=false“ (gebündelt in „better-sqlite3“), um die richtige vorgefertigte Binärdatei für das aktuelle Betriebssystem/Arch herunterzuladen, ohne dass Build-Tools erforderlich sind (kein Node-Gyp, kein Python, kein MSVC). Fällt nur dann auf „npm rebuild“ zurück, wenn der Download fehlschlägt. Fügt plattformspezifische Fehlermeldungen mit klaren Anweisungen zur manuellen Fehlerbehebung hinzu.---\n\n## [2.6.9] — 2026-03-17\n\n> CI-Korrekturen (t11 Any-Budget), Bugfix #409 (Dateianhänge über Copilot+Claude), Korrektur des Release-Workflows.### 🐛 Bug Fixes\n\n-**fix(ci)**: Wort „any“ aus Kommentaren in „openai-responses.ts“ und „chatCore.ts“ entfernen, die die t11-Budgetüberprüfung „any“ nicht bestanden haben (falsch positiv aus Kommentaren zur Regex-Zählung) -**fix(chatCore)**: Nicht unterstützte Inhaltsteiltypen vor der Weiterleitung an Anbieter normalisieren (#409 – Cursor sendet „{type:“file“}`, wenn „.md“-Dateien angehängt sind; Copilot und andere OpenAI-kompatible Anbieter lehnen mit „Typ muss entweder ‚image_url‘ oder ‚text‘ sein“ ab; Fix konvertiert „Datei“-/„Dokument“-Blöcke in „Text“ und löscht unbekannte Typen)### 🔧 Workflow\n\n-**chore(generate-release)**: ATOMIC-COMMIT-REGEL hinzufügen – Versionsupgrade („npm-Versionspatch“) MUSS vor dem Commit von Feature-Dateien erfolgen, um sicherzustellen, dass das Tag immer auf einen Commit verweist, der alle Versionsänderungen zusammen enthält---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo als Agent (Systemeingabeaufforderung + Toolfilter), Kontext-Caching-Schutz, automatische Aktualisierung, detaillierte Protokolle, MITM Kiro IDE.### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n-**005_combo_agent_fields.sql**: „ALTER TABLE Combos ADD COLUMN system_message TEXT DEFAULT NULL“, „tool_filter_regex TEXT DEFAULT NULL“, „context_cache_protection INTEGER DEFAULT 0“. -**006_detailed_request_logs.sql**: Neue Tabelle „request_detail_logs“ mit Ringpuffer-Trigger mit 500 Einträgen, Opt-in über Einstellungsumschaltung### Funktionen\n\n-**feat(combo)**: Überschreiben von Systemnachrichten per Combo (#399 – Das Feld „system_message“ ersetzt oder fügt eine Systemaufforderung vor der Weiterleitung an den Anbieter ein) -**feat(combo)**: Tool Filter Regex per Combo (#399 – „tool_filter_regex“ behält nur Tools bei, die mit Mustern übereinstimmen; unterstützt OpenAI + Anthropic-Formate) -**feat(combo)**: Kontext-Caching-Schutz (#401 – „context_cache_protection“ markiert Antworten mit „provider/model“ und pinnt das Modell für Sitzungskontinuität) -**feat(settings)**: Automatische Aktualisierung über Einstellungen (#320 – „GET /api/system/version“ + „POST /api/system/update“ – prüft die NPM-Registrierung und aktualisiert im Hintergrund mit dem Neustart von PM2) -**feat(logs)**: Detaillierte Anforderungsprotokolle (#378 – erfasst vollständige Pipeline-Körper in 4 Phasen: Client-Anfrage, übersetzte Anfrage, Anbieter-Antwort, Client-Antwort – Opt-in-Umschaltung, 64-KB-Kürzung, Ringpuffer mit 500 Einträgen) -**feat(mitm)**: MITM Kiro IDE-Profil (#336 – „src/mitm/targets/kiro.ts“ zielt auf api.anthropic.com ab und verwendet die vorhandene MITM-Infrastruktur wieder)---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE-Verbesserungen, lokale Provider_Nodes-Erweiterungen, Proxy-Registrierung, Claude-Passthrough-Korrekturen.### Funktionen\n\n-**feat(health)**: Hintergrund-Gesundheitsprüfung für lokale „provider_nodes“ mit exponentiellem Backoff (30s→300s) und „Promise.allSettled“, um Blockierungen zu vermeiden (#423, @Regis-RCR) -**feat(embeddings)**: „/v1/embeddings“ an lokale „provider_nodes“ weiterleiten – „buildDynamicEmbeddingProvider()“ mit Hostnamen-Validierung (#422, @Regis-RCR) -**feat(audio)**: TTS/STT an lokale „provider_nodes“ weiterleiten – „buildDynamicAudioProvider()“ mit SSRF-Schutz (#416, @Regis-RCR) -**feat(proxy)**: Proxy-Registrierung, Verwaltungs-APIs und Kontingentlimit-Generalisierung (#429, @Regis-RCR)### 🐛 Bug Fixes\n\n-**fix(sse)**: Claude-spezifische Felder („metadata“, „anthropic_version“) entfernen, wenn das Ziel OpenAI-kompatibel ist (#421, @prakersh) -**fix(sse)**: Claude SSE-Nutzung („input_tokens“, „output_tokens“, Cache-Tokens) im Passthrough-Stream-Modus extrahieren (#420, @prakersh) -**fix(sse)**: Fallback „call_id“ für Toolaufrufe mit fehlenden/leeren IDs generieren (#419, @prakersh) -**fix(sse)**: Claude-zu-Claude-Passthrough – vorderer Körper völlig unberührt, keine Neuübersetzung (#418, @prakersh) -**fix(sse)**: Filtern Sie verwaiste „tool_result“-Elemente nach der Claude-Code-Kontextkomprimierung, um 400-Fehler zu vermeiden (#417, @prakersh) -**fix(sse)**: Toolaufrufe mit leeren Namen im Responses-API-Übersetzer überspringen, um „placeholder_tool“-Endlosschleifen zu verhindern (#415, @prakersh) -**fix(sse)**: Leere Textinhaltsblöcke vor der Übersetzung entfernen (#427, @prakersh) -**fix(api)**: „refreshable: true“ zur Claude OAuth-Testkonfiguration hinzufügen (#428, @prakersh)### 📦 Dependencies\n\n- Bump „vitest“, „@vitest/\\*“ und verwandte devDependencies (#414, @dependabot)---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker-Kompatibilität – Entfernen Sie das „node:“-Protokoll aus allen „src/“-Importen.### 🐛 Bug Fixes\n\n-**fix(build)**: Protokollpräfix „node:“ aus „import“-Anweisungen in 17 Dateien unter „src/“ entfernt. Die Importe „node:fs“, „node:path“, „node:url“, „node:os“ usw. führten bei Turbopack-Builds (Next.js 15 Docker) und bei Upgrades von älteren globalen npm-Installationen zu „Die Ecmascript-Datei hatte einen Fehler“. Betroffene Dateien: „migrationRunner.ts“, „core.ts“, „backup.ts“, „prompts.ts“, „dataPaths.ts“ und 12 weitere in „src/app/api/“ und „src/lib/“. -**Aufgabe (Arbeitsablauf)**: „generate-release.md“ wurde aktualisiert, um die Synchronisierung von Docker Hub und die Bereitstellung von Dual-VPS in jeder Version zu**obligatorischen**Schritten zu machen.---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: Argumentationsmodell-Parameterfilterung, lokaler Anbieter 404-Fix, Kilo-Gateway-Anbieter, Abhängigkeitsbumps.### ✨ New Features\n\n-**feat(api)**:**Kilo Gateway**(`api.kilo.ai`) als neuer API-Schlüsselanbieter (alias `kg`) hinzugefügt – 335+ Modelle, 6 kostenlose Modelle, 3 Autorouting-Modelle („kilo-auto/frontier“, „kilo-auto/balanced“, „kilo-auto/free“). Passthrough-Modelle werden über den Endpunkt „/api/gateway/models“ unterstützt. (PR #408 von @Regis-RCR)### 🐛 Bug Fixes\n\n-**fix(sse)**: Nicht unterstützte Parameter für Argumentationsmodelle (o1, o1-mini, o1-pro, o3, o3-mini) entfernen. Modelle in der Familie „o1“/„o3“ lehnen „temperature“, „top_p“, „frequenz_penalty“, „presence_penalty“, „logprobs“, „top_logprobs“ und „n“ mit HTTP 400 ab. Parameter werden jetzt vor der Weiterleitung auf der Ebene „chatCore“ entfernt. Verwendet ein deklaratives „unsupportedParams“-Feld pro Modell und eine vorberechnete O(1)-Map für die Suche. (PR #412 von @Regis-RCR) -**fix(sse)**: Der lokale Anbieter 404 führt jetzt zu einer**modellspezifischen Sperre (5 Sekunden)**anstelle einer Sperrung auf Verbindungsebene (2 Minuten). Wenn ein lokales Inferenz-Backend (Ollama, LM Studio, oMLX) 404 für ein unbekanntes Modell zurückgibt, bleibt die Verbindung aktiv und andere Modelle arbeiten sofort weiter. Behebt außerdem einen bereits bestehenden Fehler, bei dem „model“ nicht an „markAccountUnavailable()“ übergeben wurde. Lokale Anbieter werden über den Hostnamen erkannt („localhost“, „127.0.0.1“, „::1“, erweiterbar über die Umgebungsvariable „LOCAL_HOSTNAMES“). (PR #410 von @Regis-RCR)### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- „Agentenbasis“ 7 → 8---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n-**Fix(Anbieter)**: Nicht vorhandene Modellnamen bei 5 Anbietern entfernt: -**gemini / gemini-cli**: „gemini-3.1-pro/flash“ und „gemini-3-\\*-preview“ entfernt (existieren nicht in Google API v1beta); ersetzt durch „gemini-2.5-pro“, „gemini-2.5-flash“, „gemini-2.0-flash“, „gemini-1.5-pro/flash“. -**Antigravitation**: „gemini-3.1-pro-high/low“ und „gemini-3-flash“ entfernt (ungültige interne Aliase); durch echte 2.x-Modelle ersetzt -**github (Copilot)**: „gemini-3-flash-preview“ und „gemini-3-pro-preview“ entfernt; ersetzt durch „gemini-2.5-flash“. -**nvidia**: „nvidia/llama-3.3-70b-instruct“ → „meta/llama-3.3-70b-instruct“ korrigiert (NVIDIA NIM verwendet den Namensraum „meta/“ für Meta-Modelle); „nvidia/llama-3.1-70b-instruct“ und „nvidia/llama-3.1-405b-instruct“ hinzugefügt -**fix(db/combo)**: „Free-Stack“-Combo auf Remote-DB aktualisiert: „qw/qwen3-coder-plus“ (abgelaufenes Aktualisierungstoken) entfernt, „nvidia/llama-3.3-70b-instruct“ korrigiert → „nvidia/meta/llama-3.3-70b-instruct“, korrigiert „gemini/gemini-3.1-flash“ → „gemini/gemini-2.5-flash“, hinzugefügt „if/deepseek-v3.2“.---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: Zod/Pino-Hash-Strip in Build-Pipeline integriert, synthetischer Anbieter hinzugefügt, VPS PM2-Pfad korrigiert.### 🐛 Bug Fixes\n\n-**fix(build)**: Turbopack-Hash-Strip läuft jetzt zur**Kompilierungszeit**für ALLE Pakete – nicht nur „better-sqlite3“. Schritt 5.6 in „prepublish.mjs“ geht alle „.js“ in „app/.next/server/“ durch und entfernt das 16-stellige Hex-Suffix aus jedem gehashten „require()“. Behebt „zod-dcb22c...“, „pino-...“ usw. MODULE_NOT_FOUND bei globalen npm-Installationen. Schließt #398 -**fix(deploy)**: PM2 zeigte auf beiden VPS auf veraltete Git-Clone-Verzeichnisse. Im globalen npm-Paket auf „app/server.js“ umkonfiguriert. Aktualisierter „/deploy-vps“-Workflow zur Verwendung von „npm pack + scp“ (npm-Registrierung lehnt 299-MB-Pakete ab).### Funktionen\n\n-**feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) – datenschutzorientierte OpenAI-kompatible Inferenz. „passthroughModels: true“ für den dynamischen HuggingFace-Modellkatalog. Erste Modelle: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 von @Regis-RCR)### 📋 Issues Closed\n\n-**Schließen #398**: NPM-Hash-Regression – durch Hash-Strip zur Kompilierungszeit in der Vorveröffentlichung behoben -**Triage #324**: Fehler-Screenshot ohne Schritte – Reproduktionsdetails angefordert---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: Modul-Hashing vollständig behoben, 2 PRs zusammengeführt (Anthropic-Tools-Filter + benutzerdefinierte Endpunktpfade), Alibaba Cloud DashScope-Anbieter hinzugefügt, 3 veraltete Probleme geschlossen.### 🐛 Bug Fixes\n\n-**fix(build)**: Webpack-„Externals“-Hash-Strip erweitert, um ALLE „serverExternalPackages“ abzudecken, nicht nur „better-sqlite3“. Next.js 16 Turbopack hasht „zod“, „pino“ und jedes andere serverexterne Paket in Namen wie „zod-dcb22c6336e0bc69“, die zur Laufzeit nicht in „node_modules“ vorhanden sind. Ein HASH_PATTERN-Regex-Catch-All entfernt jetzt das 16-Zeichen-Suffix und greift auf den Basispaketnamen zurück. Außerdem wurde „NEXT_PRIVATE_BUILD_WORKER=0“ in „prepublish.mjs“ hinzugefügt, um den Webpack-Modus zu verstärken, sowie einen Post-Build-Scan, der alle verbleibenden Hash-Refs meldet. (#396, #398, PR #403) -**fix(chat)**: Toolnamen im Anthropic-Format („tool.name“ ohne „.function“-Wrapper) wurden durch den in #346 eingeführten Filter für leere Namen stillschweigend gelöscht. LiteLLM leitet Anfragen mit dem Präfix „anthropic/“ im Anthropic Messages API-Format weiter, wodurch alle Tools gefiltert werden und Anthropic „400: tool_choice.any darf nur bei der Bereitstellung von Tools angegeben werden“ zurückgibt. Behoben durch Zurückgreifen auf „tool.name“, wenn „tool.function.name“ fehlt. 8 Regressions-Unit-Tests hinzugefügt. (PR #397)### Funktionen\n\n-**feat(api)**: Benutzerdefinierte Endpunktpfade für OpenAI-kompatible Anbieterknoten – konfigurieren Sie „chatPath“ und „modelsPath“ pro Knoten (z. B. „/v4/chat/completions“) in der Benutzeroberfläche der Anbieterverbindung. Beinhaltet eine DB-Migration (`003_provider_node_custom_paths.sql`) und URL-Pfadbereinigung (kein „..“-Durchlauf, muss mit „/“ beginnen). (PR #400) -**feat(provider)**: Alibaba Cloud DashScope als OpenAI-kompatibler Anbieter hinzugefügt. Internationaler Endpunkt: „dashscope-intl.aliyuncs.com/kompatible-mode/v1“. 12 Modelle: „qwen-max“, „qwen-plus“, „qwen-turbo“, „qwen3-coder-plus/flash“, „qwq-plus“, „qwq-32b“, „qwen3-32b“, „qwen3-235b-a22b“. Auth: Inhaber-API-Schlüssel.### 📋 Issues Closed\n\n-**close #323**: Cline-Verbindungsfehler „[object Object]“ – behoben in v2.3.7; Der Benutzer wurde angewiesen, ein Upgrade von Version 2.2.9 durchzuführen -**schließen #337**: Kiro-Kreditverfolgung – implementiert in v2.5.5 (#381); hat den Benutzer auf Dashboard → Nutzung verwiesen -**Triage #402**: ARM64 macOS DMG beschädigt – macOS-Version angefordert, genauer Fehler und empfohlene Problemumgehung „xattr -d com.apple.quarantine“.---\n\n## [2.6.1] — 2026-03-15\n\n> Kritischer Startup-Fix: Globale NPM-Installationen in Version 2.6.0 stürzten mit einem 500-Fehler aufgrund eines Turbopack/Webpack-Modulnamen-Hashing-Fehlers im Next.js 16-Instrumentierungs-Hook ab.### 🐛 Bug Fixes\n\n-**fix(build)**: Erzwingen Sie, dass „better-sqlite3“ immer mit seinem genauen Paketnamen im Webpack-Server-Bundle erforderlich ist. Next.js 16 hat den Instrumentierungs-Hook in einen separaten Block kompiliert und „require('better-sqlite3-')“ ausgegeben – einen gehashten Modulnamen, der in „node_modules“ nicht existiert – obwohl das Paket in „serverExternalPackages“ aufgeführt war. Der Server-Webpack-Konfiguration wurde eine explizite „Externals“-Funktion hinzugefügt, sodass der Bundler immer „require('better-sqlite3')“ ausgibt und den Startfehler „500 Internal Server Error“ bei sauberen globalen Installationen behebt. (#394, PR #395)### 🔧 CI\n\n-**ci**: „workflow_dispatch“ zu „npm-publish.yml“ mit Versionssynchronisierungsschutz für manuelle Trigger hinzugefügt (#392) -**ci**: „workflow_dispatch“ zu „docker-publish.yml“ hinzugefügt, GitHub-Aktionen auf die neuesten Versionen aktualisiert (#392)---\n\n## [2.6.0] - 2026-03-15\n\n> Problemlösungssprint: 4 Fehler behoben, Protokolle UX verbessert, Kiro-Kreditverfolgung hinzugefügt.### 🐛 Bug Fixes\n\n-**fix(media)**: ComfyUI und SD WebUI erscheinen nicht mehr in der Anbieterliste der Medienseite, wenn sie nicht konfiguriert sind – ruft „/api/providers“ beim Mounten ab und blendet lokale Anbieter ohne Verbindungen aus (#390) -**fix(auth)**: Round-Robin wählt ratenbegrenzte Konten nicht mehr unmittelbar nach der Abklingzeit erneut aus – „backoffLevel“ wird jetzt als primärer Sortierschlüssel in der LRU-Rotation verwendet (#340) -**fix(oauth)**: Qoder (und andere Anbieter, die auf ihre eigene Benutzeroberfläche umleiten) lassen das OAuth-Modal nicht mehr bei „Warten auf Autorisierung“ hängen – der Popup-geschlossene Detektor wechselt automatisch in den manuellen URL-Eingabemodus (#344) -**fix(logs)**: Die Anforderungsprotokolltabelle ist jetzt im hellen Modus lesbar – Status-Badges, Token-Zählungen und Combo-Tags verwenden adaptive „dark:“-Farbklassen (#378)### Funktionen\n\n-**feat(kiro)**: Kiro-Credit-Tracking zum Nutzungsabrufer hinzugefügt – fragt „getUserCredits“ vom AWS CodeWhisperer-Endpunkt ab (#337)### 🛠 Chores\n\n-**chore(tests)**: `test:plan3`, `test:fixes`, `test:security` so ausgerichtet, dass sie denselben `tsx/esm`-Loader wie `npm test` verwenden – eliminiert falsch negative Ergebnisse bei der Modulauflösung in gezielten Läufen (PR #386)---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native Passthrough-Korrektur + Routenkörper-Validierungshärtung.### 🐛 Bug Fixes\n\n-**Fix(Codex)**: Native Responses API-Passthrough für Codex-Clients beibehalten – vermeidet unnötige Übersetzungsmutationen (PR #387) -**fix(api)**: Anforderungstexte auf Preis-/Synchronisierungs- und Aufgabenrouting-Routen validieren – verhindert Abstürze durch fehlerhafte Eingaben (PR #388) -**fix(auth)**: JWT-Geheimnisse bleiben über „src/lib/db/secrets.ts“ über Neustarts hinweg bestehen – beseitigt 401-Fehler nach dem PM2-Neustart (PR #388)---\n\n## [2.5.8] - 2026-03-15\n\n> Build-Fix: Wiederherstellung der VPS-Konnektivität, die durch die unvollständige Veröffentlichung von v2.5.7 unterbrochen wurde.### 🐛 Bug Fixes\n\n-**fix(build)**: „scripts/prepublish.mjs“ verwendete immer noch das veraltete „--webpack“-Flag, was dazu führte, dass der eigenständige Build von Next.js stillschweigend fehlschlug – npm-Veröffentlichung wurde ohne „app/server.js“ abgeschlossen, wodurch die VPS-Bereitstellung unterbrochen wurde---\n\n## [2.5.7] - 2026-03-15\n\n> Fehlerbehebungen bei der Fehlerbehandlung im Media Playground.### 🐛 Bug Fixes\n\n-**fix(media)**: Transkription „API-Schlüssel erforderlich“ falsch positiv, wenn Audio keine Sprache enthält (Musik, Stille) – zeigt jetzt stattdessen „Keine Sprache erkannt“ an -**fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` und `audioSpeech.ts` gibt jetzt den richtigen JSON zurück (`{error:{message}}`), was die korrekte Erkennung von 401/403-Anmeldeinformationsfehlern im MediaPageClient ermöglicht -**fix(media)**: „parseApiError“ verarbeitet jetzt das „err_msg“-Feld von Deepgram und erkennt „api key“ in Fehlermeldungen für eine genaue Klassifizierung von Anmeldeinformationsfehlern---\n\n## [2.5.6] - 2026-03-15\n\n> Kritische Sicherheits-/Authentifizierungskorrekturen: Antigravity OAuth defekt + JWT-Sitzungen nach Neustart verloren.### 🐛 Bug Fixes\n\n-**fix(oauth) #384**: Antigravity Google OAuth sendet jetzt korrekt „client_secret“ an den Token-Endpunkt. Der Fallback für „ANTIGRAVITY_OAUTH_CLIENT_SECRET“ war eine leere Zeichenfolge, was falsch ist – „client_secret“ war also nie in der Anfrage enthalten, was bei allen Benutzern ohne eine benutzerdefinierte Umgebungsvariable zu der Fehlermeldung „client_secret fehlt“ führte. Schließt #383. -**fix(auth) #385**: „JWT_SECRET“ wird jetzt bei der ersten Generation in SQLite („namespace='secrets‘‘) beibehalten und bei nachfolgenden Starts neu geladen. Zuvor wurde bei jedem Prozessstart ein neues zufälliges Geheimnis generiert, das alle vorhandenen Cookies/Sitzungen nach jedem Neustart oder Upgrade ungültig machte. Betrifft sowohl „JWT_SECRET“ als auch „API_KEY_SECRET“. Schließt #382.---\n\n## [2.5.5] - 2026-03-15\n\n> Modelllisten-Dedup-Korrektur, Electron-Standalone-Build-Hardening und Kiro-Kreditverfolgung.### 🐛 Bug Fixes\n\n-**fix(models) #380**: „GET /api/models“ schließt jetzt Anbieter-Aliase ein, wenn der Filter für aktive Anbieter erstellt wird – Modelle für „claude“ (Alias ​​„cc“) und „github“ (Alias ​​„gh“) wurden immer angezeigt, unabhängig davon, ob eine Verbindung konfiguriert wurde, da „PROVIDER_MODELS“-Schlüssel Aliase sind, DB-Verbindungen jedoch unter Anbieter-IDs gespeichert werden. Behoben durch Erweiterung jeder aktiven Anbieter-ID, um auch ihren Alias ​​über „PROVIDER_ID_TO_ALIAS“ einzuschließen. Schließt #353. -**fix(electron) #379**: Neues „scripts/prepare-electron-standalone.mjs“ stellt ein dediziertes „/.next/electron-standalone“-Bundle vor der Electron-Verpackung bereit. Bricht mit einem eindeutigen Fehler ab, wenn „node_modules“ ein symbolischer Link ist (Electron-Builder würde eine Laufzeitabhängigkeit von der Build-Maschine ausliefern). Plattformübergreifende Pfadbereinigung über „path.basename“. Von @kfiramar.### ✨ New Features\n\n-**feat(kiro) #381**: Kiro-Guthabenverfolgung – Nutzungsendpunkt gibt jetzt Kreditdaten für Kiro-Konten zurück, indem er „codewhisperer.us-east-1.amazonaws.com/getUserCredits“ aufruft (derselbe Endpunkt, den Kiro IDE intern verwendet). Gibt verbleibende Credits, Gesamtguthaben, Verlängerungsdatum und Abonnementstufe zurück. Schließt #337.## [2.5.4] - 2026-03-15\n\n> Logger-Startup-Fix, Login-Bootstrap-Sicherheitsfix und Verbesserung der Entwicklungs-HMR-Zuverlässigkeit. CI-Infrastruktur gehärtet.### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n-**fix(logger) #376**: Pino-Transport-Logger-Pfad wiederherstellen – „formatters.level“ in Kombination mit „transport.targets“ wird von Pino abgelehnt. Transportgestützte Konfigurationen entfernen jetzt den Ebenenformatierer über „getTransportCompatibleConfig()“. Korrigiert außerdem die numerische Ebenenzuordnung in „/api/logs/console“: „30→info, 40→warn, 50→error“ (wurde um eins verschoben). -**fix(login) #375**: Die Anmeldeseite startet jetzt vom öffentlichen „/api/settings/require-login“-Endpunkt statt vom geschützten „/api/settings“. In passwortgeschützten Setups erhielt die Vorauthentifizierungsseite einen 401-Fehler und fiel unnötigerweise auf sichere Standardeinstellungen zurück. Die öffentliche Route gibt jetzt alle Bootstrap-Metadaten („requireLogin“, „hasPassword“, „setupComplete“) mit einem konservativen 200-Fallback bei Fehler zurück. -**fix(dev) #374**: „localhost“ und „127.0.0.1“ zu „allowedDevOrigins“ in „next.config.mjs“ hinzugefügt – HMR-Websocket wurde beim Zugriff auf die App über die Loopback-Adresse blockiert, was zu wiederholten Cross-Origin-Warnungen führte.### 🔧 CI & Infrastructure\n\n-**ESLint OOM-Korrektur**: „eslint.config.mjs“ ignoriert jetzt „vscode-extension/**“, „electron/**“, „docs/**“, „app/.next/**“ und „clipr/**“ – ESLint stürzte mit einem JS-Heap-OOM ab, indem VS-Code-Binärblobs und kompilierte Blöcke gescannt wurden. -**Unit-Test-Korrektur**: Veraltetes „ALTER TABLEprovider_connections ADD COLUMN „group““ aus 2 Testdateien entfernt – Spalte ist jetzt Teil des Basisschemas (hinzugefügt in #373), was bei jedem CI-Lauf zu „SQLITE_ERROR: doppelter Spaltenname“ führt. -**Pre-Commit-Hook\\*\\*: „npm run test:unit“ zu „.husky/pre-commit“ hinzugefügt – Unit-Tests blockieren jetzt fehlerhafte Commits, bevor sie CI erreichen.## [2.5.3] - 2026-03-14\n\n> Kritische Fehlerbehebungen: DB-Schema-Migration, Laden der Startumgebung, Behebung des Provider-Fehlerstatus und i18n-Tooltip-Korrektur. Verbesserungen der Codequalität zusätzlich zu jeder PR.### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n–**fix(db) #373**: Spalte „provider_connections.group“ zum Basisschema + Backfill-Migration für vorhandene Datenbanken hinzufügen – Spalte wurde in allen Abfragen verwendet, fehlte jedoch in der Schemadefinition -**fix(i18n) #371**: Ersetzen Sie den nicht vorhandenen Schlüssel „t(\"deleteConnection\")“ durch den vorhandenen Schlüssel „providers.delete“ – behebt den Laufzeitfehler „MISSING_MESSAGE: issues.deleteConnection“ auf der Anbieterdetailseite -**fix(auth) #372**: Veraltete Fehlermetadaten („errorCode“, „lastErrorType“, „lastErrorSource“) aus Anbieterkonten nach einer echten Wiederherstellung löschen – zuvor wurden wiederhergestellte Konten immer als fehlgeschlagen angezeigt -**fix(startup) #369**: Env-Laden über „npm run start“, „run-standalone.mjs“ und Electron vereinheitlichen, um die Priorität „DATA_DIR/.env → ~/.omniroute/.env → ./.env“ zu berücksichtigen – verhindert die Generierung eines neuen „STORAGE_ENCRYPTION_KEY“ über eine vorhandene verschlüsselte Datenbank### 🔧 Code Quality\n\n- Dokumentierte Muster „result.success“ vs. „response?.ok“ in „auth.ts“ (beide beabsichtigt, jetzt erklärt)\n- „overridePath?.trim()“ in „electron/main.js“ normalisiert, um mit „bootstrap-env.mjs“ übereinzustimmen\n- Kommentar zur Zusammenführungsreihenfolge „preferredEnv“ beim Start von Electron hinzugefügt\n\n> Kontingentrichtlinie für Codex-Konten mit automatischer Rotation, schneller Stufenumschaltung, GPT-5.4-Modell und Analyse-Label-Korrektur.### ✨ New Features (PRs #366, #367, #368)\n\n-**Codex-Kontingentrichtlinie (PR #366)**: Das Kontingentfenster für 5 Stunden/Woche pro Konto wird im Anbieter-Dashboard umgeschaltet. Konten werden automatisch übersprungen, wenn aktivierte Fenster den Schwellenwert von 90 % erreichen, und nach „resetAt“ wieder zugelassen. Enthält „quotaCache.ts“ mit nebenwirkungsfreiem Status-Getter. -**Codex Fast Tier Toggle (PR #367)**: Dashboard → Einstellungen → Codex Service Tier. Durch die standardmäßige Deaktivierung wird „service_tier: „flex““ nur für Codex-Anfragen eingefügt, wodurch die Kosten um etwa 80 % gesenkt werden. Vollständiger Stack: UI-Registerkarte + API-Endpunkt + Executor + Übersetzer + Startwiederherstellung. -**gpt-5.4-Modell (PR #368)**: Fügt „cx/gpt-5.4“ und „codex/gpt-5.4“ zur Codex-Modellregistrierung hinzu. Regressionstest inklusive.### 🐛 Bug Fixes\n\n-**Fix #356**: Analytics-Diagramme (Top-Anbieter, Nach Konto, Anbieteraufschlüsselung) zeigen jetzt für OpenAI-kompatible Anbieter menschenlesbare Anbieternamen/-bezeichnungen anstelle von rohen internen IDs an.\n\n> Hauptversion: Strategie für strikt zufälliges Routing, Zugriffskontrollen für API-Schlüssel, Verbindungsgruppen, externe Preissynchronisierung und wichtige Fehlerbehebungen für Denkmodelle, Kombinationstests und Validierung von Toolnamen.### ✨ New Features (PRs #363 & #365)\n\n-**Streng-zufällige Routing-Strategie**: Fisher-Yates-Shuffle-Deck mit Anti-Repeat-Garantie und Mutex-Serialisierung für gleichzeitige Anfragen. Unabhängige Decks pro Combo und pro Anbieter. -**API-Schlüsselzugriffskontrollen**: „allowedConnections“ (beschränkt, welche Verbindungen ein Schlüssel verwenden kann), „is_active“ (Schlüssel mit 403 aktivieren/deaktivieren), „accessSchedule“ (zeitbasierte Zugriffskontrolle), „autoResolve“-Umschaltung, Schlüssel über PATCH umbenennen. -**Verbindungsgruppen**: Gruppieren Sie Anbieterverbindungen nach Umgebung. Akkordeonansicht auf der Seite „Limits“ mit LocalStorage-Persistenz und intelligentem automatischen Wechsel. -**Externe Preissynchronisierung (LiteLLM)**: 3-stufige Preisauflösung (Benutzerüberschreibungen → synchronisiert → Standardeinstellungen). Melden Sie sich über „PRICING_SYNC_ENABLED=true“ an. MCP-Tool „omniroute_sync_pricing“. 23 neue Tests. -**i18n**: 30 Sprachen mit strikter Zufallsstrategie und API-Schlüsselverwaltungszeichenfolgen aktualisiert. pt-BR vollständig übersetzt.### 🐛 Bug Fixes\n\n-**Fix #355**: Stream-Leerlauf-Timeout von 60 Sekunden auf 300 Sekunden erhöht – verhindert den Abbruch erweiterter Denkmodelle (claude-opus-4-6, o3 usw.) während langer Argumentationsphasen. Konfigurierbar über „STREAM_IDLE_TIMEOUT_MS“. -**Fix #350**: Der Combo-Test umgeht jetzt „REQUIRE_API_KEY=true“ mithilfe des internen Headers und verwendet universell das OpenAI-kompatible Format. Timeout von 15 auf 20 Sekunden verlängert. -**Fix #346**: Tools mit leerem „function.name“ (weitergeleitet von Claude Code) werden jetzt gefiltert, bevor Upstream-Anbieter sie erhalten, wodurch Fehler „Ungültige Eingabe[N].name: leere Zeichenfolge“ verhindert werden.### 🗑️ Closed Issues\n\n-**#341**: Debug-Abschnitt entfernt – Ersatz ist „/dashboard/logs“ und „/dashboard/health“.\n\n> API-Key-Round-Robin-Unterstützung für Multi-Key-Anbieter-Setups und Bestätigung von Wildcard-Routing und Quotenfenster-Rolling, das bereits vorhanden ist.### ✨ New Features\n\n-**API-Schlüssel-Round-Robin (T07)**: Anbieterverbindungen können jetzt mehrere API-Schlüssel enthalten (Verbindung bearbeiten → Zusätzliche API-Schlüssel). Anfragen rotieren im Round-Robin-Verfahren zwischen Primär- und Zusatzschlüsseln über „providerSpecificData.extraApiKeys[]“. Schlüssel werden pro Verbindung indiziert im Speicher gehalten – es sind keine Änderungen am DB-Schema erforderlich.### 📝 Already Implemented (confirmed in audit)\n\n-**Wildcard Model Routing (T13)**: „wildcardRouter.ts“ mit Wildcard-Matching im Glob-Stil („gpt\\*“, „claude-?-sonnet“ usw.) ist bereits in „model.ts“ mit Spezifitätsranking integriert. -**Quota Window Rolling (T08)**: „accountFallback.ts:isModelLocked()“ erweitert das Fenster bereits automatisch – wenn „Date.now() > enter.until“, wird die Sperre sofort gelöscht (keine veraltete Blockierung).\n\n> Verfeinerung der Benutzeroberfläche, Ergänzungen der Routing-Strategie und elegante Fehlerbehandlung für Nutzungsbeschränkungen.### ✨ New Features\n\n-**Fill-First- und P2C-Routing-Strategien**: „Fill-First“ (Kontingent entleeren, bevor es weitergeht) und „P2C“ (Power-of-Two-Choices-Auswahl mit geringer Latenz) zur Combo-Strategie-Auswahl hinzugefügt, mit vollständigen Anleitungsfeldern und farbcodierten Abzeichen. -**Kostenlose Stack-Voreinstellungsmodelle**: Beim Erstellen einer Kombination mit der Free Stack-Vorlage werden jetzt automatisch 7 erstklassige kostenlose Anbietermodelle ausgefüllt (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Benutzer aktivieren einfach die Anbieter und erhalten sofort eine Kombination von 0 $/Monat. -**Breiteres Combo-Modal**: Das Combo-Modal zum Erstellen/Bearbeiten verwendet jetzt „max-w-4xl“ für die komfortable Bearbeitung großer Combos.### 🐛 Bug Fixes\n\n-**Limits-Seite HTTP 500 für Codex & GitHub**: „getCodexUsage()“ und „getGitHubUsage()“ geben jetzt eine benutzerfreundliche Meldung zurück, wenn der Anbieter 401/403 (abgelaufenes Token) zurückgibt, anstatt einen 500-Fehler auf der Limits-Seite auszulösen und zu verursachen. -**MaintenanceBanner falsch positiv**: Das Banner zeigt beim Laden der Seite nicht mehr fälschlicherweise „Server ist nicht erreichbar“ an. Behoben durch Aufruf von „checkHealth()“ direkt beim Mounten und Entfernen veralteter „show“-State-Abschlüsse. -**Tooltips für Anbietersymbole**: Die Symbolschaltflächen „Bearbeiten“ (Bleistift) und „Löschen“ in der Anbieterverbindungszeile verfügen jetzt über native HTML-Tooltips – alle 6 Aktionssymbole sind jetzt selbstdokumentiert.\n\n> Mehrere Verbesserungen durch Community-Problemanalyse, Unterstützung neuer Anbieter, Fehlerbehebungen für Token-Tracking, Modellrouting und Streaming-Zuverlässigkeit.### ✨ New Features\n\n-**Task-Aware Smart Routing (T05)**: Automatische Modellauswahl basierend auf dem Inhaltstyp der Anfrage – Codierung → Deepseek-Chat, Analyse → Gemini-2.5-Pro, Vision → GPT-4o, Zusammenfassung → Gemini-2.5-Flash. Konfigurierbar über Einstellungen. Neue API „GET/PUT/POST /api/settings/task-routing“. -**HuggingFace-Anbieter**: HuggingFace Router als OpenAI-kompatibler Anbieter mit Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini hinzugefügt. -**Vertex AI-Anbieter**: Vertex AI (Google Cloud)-Anbieter mit Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude über Vertex hinzugefügt. -**Playground-Datei-Uploads**: Audio-Upload für die Transkription, Bild-Upload für Vision-Modelle (automatische Erkennung anhand des Modellnamens), Inline-Bildrendering für Ergebnisse der Bildgenerierung. -**Visuelles Feedback zur Modellauswahl**: Bereits hinzugefügte Modelle in der Kombinationsauswahl zeigen jetzt ✓ grünes Abzeichen – verhindert doppelte Verwirrung. -**Qwen-Kompatibilität (PR #352)**: Aktualisierte User-Agent- und CLI-Fingerabdruckeinstellungen für die Kompatibilität mit Qwen-Anbietern. -**Round-Robin-Statusverwaltung (PR #349)**: Verbesserte Round-Robin-Logik zur Handhabung ausgeschlossener Konten und zur korrekten Aufrechterhaltung des Rotationsstatus. -**Clipboard UX (PR #360)**: Gehärtete Zwischenablageoperationen mit Fallback für nicht sichere Kontexte; Verbesserungen bei der Normalisierung des Claude-Tools.### 🐛 Bug Fixes\n\n-**Fix #302 – OpenAI SDK stream=False löscht tool_calls**: T01 Accept-Header-Aushandlung erzwingt kein Streaming mehr, wenn „body.stream“ explizit „false“ ist. Hat dazu geführt, dass „tool_calls“ stillschweigend gelöscht wurden, wenn das OpenAI Python SDK im Nicht-Streaming-Modus verwendet wurde. -**Fix #73 – Claude Haiku wurde ohne Provider-Präfix an OpenAI weitergeleitet**: „claude-_“-Modelle, die ohne Provider-Präfix gesendet wurden, leiten jetzt korrekt an den „Antigravity“-Anbieter (Anthropic) weiter. Auch die Heuristik „gemini-_“/„gemma-\\*“ → „gemini“ hinzugefügt. -**Fix #74 – Token-Zählungen immer 0 für Antigravity/Claude-Streaming**: Das SSE-Ereignis „message_start“, das „input_tokens“ trägt, wurde von „extractUsage()“ nicht analysiert, was dazu führte, dass alle Eingabe-Token-Zählungen abfielen. Die Verfolgung von Eingabe-/Ausgabe-Tokens funktioniert jetzt korrekt für Streaming-Antworten. -**Fix #180 – Modellimport-Duplikate ohne Rückmeldung**: „ModelSelectModal“ zeigt jetzt eine ✓ grüne Hervorhebung für Modelle an, die sich bereits in der Kombination befinden, wodurch deutlich wird, dass sie bereits hinzugefügt wurden. -**Fehler bei der Generierung von Medienseiten**: Bildergebnisse werden jetzt als „“-Tags statt als rohes JSON gerendert. Transkriptionsergebnisse werden als lesbarer Text angezeigt. Bei Anmeldeinformationsfehlern wird anstelle eines stillen Fehlers ein gelbes Banner angezeigt. -**Schaltfläche zur Token-Aktualisierung auf der Anbieterseite**: Benutzeroberfläche zur manuellen Token-Aktualisierung für OAuth-Anbieter hinzugefügt.### 🔧 Improvements\n\n-**Provider Registry**: HuggingFace und Vertex AI zu „providerRegistry.ts“ und „providers.ts“ (Frontend) hinzugefügt. -**Lese-Cache**: Neues „src/lib/db/readCache.ts“ für effizientes DB-Lese-Caching. -**Kontingent-Cache**: Verbesserter Kontingent-Cache mit TTL-basierter Räumung.### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- „docker/setup-qemu-action“ → v4 (PR #342)\n- „docker/setup-buildx-action“ → v4 (PR #343)### 📁 New Files\n\n| Datei | Zweck |\n| --------------------------------------------- | ------------------------------------------------ | ----------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Aufgabenbewusste Routing-Logik (7 Aufgabentypen) |\n| `src/app/api/settings/task-routing/route.ts` | Task-Routing-Konfigurations-API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manuelle Aktualisierung des OAuth-Tokens |\n| `src/lib/db/readCache.ts` | Effizienter DB-Lese-Cache |\n| `src/shared/utils/clipboard.ts` | Gehärtete Zwischenablage mit Fallback | ## [2.4.1] - 2026-03-13 |\n\n### 🐛 Fix\n\n-**Combos modal: Free Stack sichtbar und hervorgehoben**– Free Stack-Vorlage wurde ausgeblendet (4. im 3-Spalten-Raster). Behoben: Auf Position 1 verschoben, auf 2x2-Raster umgestellt, sodass alle 4 Vorlagen sichtbar sind, grüner Rand + KOSTENLOSE Badge-Hervorhebung.## [2.4.0] - 2026-03-13\n\n> **Hauptversion**– Free-Stack-Ökosystem, Überarbeitung des Transkriptionsspielplatzes, mehr als 44 Anbieter, umfassende kostenlose Dokumentation und allgemeine Verbesserungen der Benutzeroberfläche.### Funktionen\n\n-**Combos: Free Stack-Vorlage**– Neue 4. Vorlage „Free Stack ($0)“ mit Round-Robin über Kiro + Qoder + Qwen + Gemini CLI. Schlägt bei der ersten Verwendung die vorgefertigte Null-Kosten-Kombination vor. -**Medien/Transkription: Deepgram als Standard**– Deepgram (Nova 3, 200 $ kostenlos) ist jetzt der Standard-Transkriptionsanbieter. AssemblyAI (50 $ kostenlos) und Groq Whisper (für immer kostenlos) werden mit kostenlosen Guthabenabzeichen angezeigt. -**README: Abschnitt „Kostenlos starten“**– Neue frühe README-5-Schritte-Tabelle, die zeigt, wie man in wenigen Minuten kostenlose KI einrichtet. -**README: Kostenlose Transkriptionskombination**– Neuer Abschnitt mit Deepgram/AssemblyAI/Groq-Kombinationsvorschlägen und kostenlosen Kreditdetails pro Anbieter. -**providers.ts: hasFree-Flag**– NVIDIA NIM, Cerebras und Groq sind mit dem hasFree-Logo und freeNote für die Benutzeroberfläche des Anbieters gekennzeichnet. -**i18n: templateFreeStack-Schlüssel**– Kostenlose Stack-Kombinationsvorlage übersetzt und in alle 30 Sprachen synchronisiert.## [2.3.16] - 2026-03-13\n\n### Dokumentation\n\n-**README: 44+ Providers**– Alle drei Vorkommen von „36+ Providers“ wurden auf „44+“ aktualisiert, was die tatsächliche Codebasisanzahl widerspiegelt (44 Provider in Providers.ts). -**README: Neuer Abschnitt „🆓 Kostenlose Modelle – Was Sie tatsächlich bekommen“**– 7-Anbieter-Tabelle mit Ratenbegrenzungen pro Modell hinzugefügt für: Kiro (Claude unbegrenzt über AWS Builder ID), Qoder (5 Modelle unbegrenzt), Qwen (4 Modelle unbegrenzt), Gemini CLI (180.000/Monat), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1 Mio. Token/Tag / 60.000 TPM), Groq (30 RPM). / 14,4K RPD). Enthält die \\/usr/bin/bash Ultimate Free Stack-Kombinationsempfehlung. -**README: Preistabelle aktualisiert**– Cerebras zur API KEY-Stufe hinzugefügt, NVIDIA von „1000 Credits“ auf „Dev-forever free“ korrigiert, Anzahl und Namen der Qoder/Qwen-Modelle aktualisiert -**README: Qoder 8→5 Modelle**(benannt: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2) -**README: Qwen 3→4 Modelle**(benannt: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)## [2.3.15] - 2026-03-13\n\n### Funktionen\n\n-**Auto-Combo-Dashboard (Stufenpriorität)**: „🏷️ Tier“ als 7. Bewertungsfaktorbezeichnung in der Faktoraufschlüsselungsanzeige „/dashboard/auto-combo“ hinzugefügt – alle 7 Auto-Combo-Bewertungsfaktoren sind jetzt sichtbar. -**i18n – AutoCombo-Abschnitt**: 20 neue Übersetzungsschlüssel für das Auto-Combo-Dashboard („title“, „status“, „modePack“, „providerScores“, „factorTierPriority“ usw.) zu allen 30 Sprachdateien hinzugefügt.## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n-**Qoder OAuth (#339)**: Der gültige Standard „clientSecret“ wurde wiederhergestellt – war zuvor eine leere Zeichenfolge, was bei jedem Verbindungsversuch zu „Ungültige Client-Anmeldeinformationen“ führte. Die öffentlichen Anmeldeinformationen sind jetzt der Standard-Fallback (überschreibbar über die Umgebungsvariable „QODER_OAUTH_CLIENT_SECRET“). -**MITM-Server nicht gefunden (#335)**: „prepublish.mjs“ kompiliert jetzt „src/mitm/\\*.ts“ mit „tsc“ in JavaScript, bevor es in das npm-Bundle kopiert wird. Bisher wurden nur rohe „.ts“-Dateien kopiert – was bedeutet, dass „server.js“ in globalen npm/Volta-Installationen nie existierte. -**GeminiCLI fehlt projectId (#338)**: Anstatt einen harten 500-Fehler auszulösen, wenn „projectId“ in gespeicherten Anmeldeinformationen fehlt (z. B. nach einem Docker-Neustart), protokolliert OmniRoute jetzt eine Warnung und versucht die Anfrage auszuführen – es wird ein aussagekräftiger anbieterseitiger Fehler anstelle eines OmniRoute-Absturzes zurückgegeben. -**Electron-Versionskonflikt (#323)**: Die Version „electron/package.json“ wurde mit „2.3.13“ synchronisiert (war „2.0.13“), sodass die Desktop-Binärversion mit dem npm-Paket übereinstimmt.### ✨ New Models (#334)\n\n-**Kiro**: „claude-sonnet-4“, „claude-opus-4.6“, „deepseek-v3.2“, „minimax-m2.1“, „qwen3-coder-next“, „auto“. -**Codex**: `gpt5.4`### 🔧 Improvements\n\n-**Tier-Scoring (API + Validierung)**: „tierPriority“ (Gewichtung „0,05“) zum Zod-Schema „ScoringWeights“ und zur API-Route „combos/auto“ hinzugefügt – der 7. Scoring-Faktor wird jetzt vollständig von der REST-API akzeptiert und bei der Eingabe validiert. Das „Stabilitäts“-Gewicht wurde von „0,10“ auf „0,05“ angepasst, um die Gesamtsumme = „1,0“ beizubehalten.### ✨ New Features\n\n-**Gestaffelte Kontingentbewertung (Auto-Combo)**: „TierPriority“ als 7. Bewertungsfaktor hinzugefügt – Konten mit Ultra/Pro-Stufen werden jetzt gegenüber kostenlosen Stufen bevorzugt, wenn andere Faktoren gleich sind. Neue optionale Felder „accountTier“ und „quotaResetIntervalSecs“ auf „ProviderCandidate“. Alle 4 Moduspakete aktualisiert („Schnell versenden“, „Kostensparend“, „Qualität geht vor“, „Offline-freundlich“). -**Intra-Family Model Fallback (T5)**: Wenn ein Modell nicht verfügbar ist (404/400/403), greift OmniRoute jetzt automatisch auf Geschwistermodelle aus derselben Familie zurück, bevor ein Fehler zurückgegeben wird („modelFamilyFallback.ts“). -**Konfigurierbares API-Bridge-Timeout**: Mit der Umgebungsvariable „API_BRIDGE_PROXY_TIMEOUT_MS“ können Bediener das Proxy-Timeout optimieren (Standard 30 Sekunden). Behebt 504-Fehler bei langsamen Upstream-Antworten. (#332) -**Star History**: Das star-history.com-Widget wurde in allen 30 READMEs durch starchart.cc („?variant=adaptive“) ersetzt – passt sich dem Hell-/Dunkel-Thema an und wird in Echtzeit aktualisiert.### 🐛 Bug Fixes\n\n-**Auth – Erstmaliges Passwort**: Die Umgebungsvariable „INITIAL*PASSWORD“ wird jetzt beim Festlegen des ersten Dashboard-Passworts akzeptiert. Verwendet „timingSafeEqual“ für einen konstanten Zeitvergleich und verhindert so Timing-Angriffe. (#333) -**README-Kürzung**: Ein fehlendes schließendes Tag „“ im Abschnitt „Fehlerbehebung“ wurde behoben, das dazu führte, dass GitHub nicht mehr alles darunter renderte (Tech Stack, Dokumente, Roadmap, Mitwirkende). -**pnpm-Installation**: Redundante „@swc/helpers“-Überschreibung aus „package.json“ entfernt, die mit der direkten Abhängigkeit in Konflikt stand und „EOVERRIDE“-Fehler auf pnpm verursachte. Konfiguration „pnpm.onlyBuiltDependencies“ hinzugefügt. -**CLI Path Injection (T12)**: „isSafePath()“-Validator in „cliRuntime.ts“ hinzugefügt, um Pfaddurchquerung und Shell-Metazeichen in „CLI*\\*\\_BIN“-Umgebungsvariablen zu blockieren. -**CI**: „package-lock.json“ wurde nach dem Entfernen des Overrides neu generiert, um „npm ci“-Fehler in GitHub-Aktionen zu beheben.### 🔧 Improvements\n\n-**Antwortformat (T1)**: „response_format“ (json_schema/json_object) wird jetzt als Systemeingabeaufforderung für Claude eingefügt, wodurch die Kompatibilität mit strukturierten Ausgaben ermöglicht wird. -**429-Wiederholung (T2)**: Intra-URL-Wiederholungsversuch für 429 Antworten (2× Versuche mit 2 Sekunden Verzögerung), bevor auf die nächste URL zurückgegriffen wird. -**Gemini-CLI-Header (T3)**: Fingerabdruck-Header „User-Agent“ und „X-Goog-Api-Client“ für Gemini-CLI-Kompatibilität hinzugefügt. -**Preiskatalog (T9)**: Preiseinträge für „deepseek-3.1“, „deepseek-3.2“ und „qwen3-coder-next“ hinzugefügt.### 📁 New Files\n\n| Datei | Zweck |\n| ------------------------------------------ | ------------------------------------------------------------- | --------- |\n| `open-sse/services/modelFamilyFallback.ts` | Modellfamiliendefinitionen und familieninterne Fallback-Logik | ### Fixed |\n\n-**KiloCode**: Zeitüberschreitung bei Kilocode-Gesundheitsprüfung bereits in Version 2.3.11 behoben -**OpenCode**: Fügen Sie Opencode zur cliRuntime-Registrierung mit einem Zeitlimit von 15 Sekunden für die Integritätsprüfung hinzu -**OpenClaw / Cursor**: Erhöhen Sie das Timeout für die Gesundheitsprüfung auf 15 Sekunden für Varianten mit langsamem Start -**VPS**: Droid- und Openclaw-NPM-Pakete installieren; Aktivieren Sie CLI_EXTRA_PATHS für kiro-cli -**cliRuntime**: Opencode-Tool-Registrierung hinzufügen und Timeout für die Fortsetzung erhöhen## [2.3.11] - 2026-03-12\n\n### Fixed\n\n-**KiloCode-Gesundheitscheck**: „healthcheckTimeoutMs“ von 4000 ms auf 15000 ms erhöhen – Kilocode rendert beim Start ein ASCII-Logo-Banner, was in Umgebungen mit langsamem/Kaltstart zu einem falschen „healthcheck_failed“ führt## [2.3.10] - 2026-03-12\n\n### Fixed\n\n-**Lint**: „check:any-budget:t11“-Fehler behoben – „as any“ durch „as Record“ in OAuthModal.tsx ersetzen (3 Vorkommen)### Docs\n\n-**CLI-TOOLS.md**: Vollständige Anleitung für alle 11 CLI-Tools (Claude, Codex, Gemini, Opencode, Cline, Kilocode, Continue, Kiro-Cli, Cursor, Droid, Openclaw) -**i18n**: CLI-TOOLS.md mit 30 Sprachen synchronisiert, mit übersetztem Titel + Intro## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n-**/v1/completions**: Neuer Legacy-OpenAI-Abschlussendpunkt – akzeptiert sowohl die Zeichenfolge „prompt“ als auch das Array „messages“ und normalisiert sich automatisch auf das Chat-Format -**EndpointPage**: Zeigt jetzt alle drei OpenAI-kompatiblen Endpunkttypen an: Chat-Abschlüsse, Antwort-API und Legacy-Abschlüsse -**i18n**: „completionsLegacy/completionsLegacyDesc“ zu 30 Sprachdateien hinzugefügt### Fixed\n\n-**OAuthModal**: Korrigieren Sie „[object Object]“, das bei allen OAuth-Verbindungsfehlern angezeigt wird – extrahieren Sie „.message“ ordnungsgemäß aus Fehlerantwortobjekten in allen drei „throw new Error(data.error)“-Aufrufen (Exchange, Device-Code, Authorize).\n– Betrifft Cline, Codex, GitHub, Qwen, Kiro und alle anderen OAuth-Anbieter## [2.3.7] - 2026-03-12\n\n### Fixed\n\n-**Cline OAuth**: Fügen Sie „decodeURIComponent“ vor der Base64-Dekodierung hinzu, damit URL-codierte Authentifizierungscodes aus der Rückruf-URL korrekt analysiert werden, wodurch Fehler „Ungültiger oder abgelaufener Autorisierungscode“ bei Remote-Einrichtungen (LAN-IP) behoben werden -**Cline OAuth**: „mapTokens“ füllt jetzt „name = firstName + lastName ||“ aus email`, damit Cline-Konten echte Benutzernamen anstelle von „Konto-ID“ anzeigen -**OAuth-Kontonamen**: Alle OAuth-Austauschströme (Exchange, Poll, Poll-Callback) normalisieren jetzt „Name = E-Mail“, wenn der Name fehlt, sodass jedes OAuth-Konto seine E-Mail-Adresse als Anzeigebezeichnung im Anbieter-Dashboard anzeigt -**OAuth-Kontonamen**: Sequentielles „Konto N“-Fallback in „db/providers.ts“ entfernt – Konten ohne E-Mail/Name verwenden jetzt über „getAccountDisplayName()“ eine stabile ID-basierte Bezeichnung anstelle einer fortlaufenden Nummer, die sich ändert, wenn Konten gelöscht werden## [2.3.6] - 2026-03-12\n\n### Fixed\n\n-**Provider-Testbatch**: Das Zod-Schema wurde so korrigiert, dass es „providerId: null“ akzeptiert (Frontend sendet null für Nicht-Provider-Modi); gab fälschlicherweise für alle Batch-Tests „Ungültige Anfrage“ zurück -**Provider-Testmodal**: Die Anzeige von „[object Object]“ wurde korrigiert, indem API-Fehlerobjekte vor dem Rendern in „setTestResults“ und „ProviderTestResultsView“ in Strings normalisiert wurden -**i18n**: Fehlende Schlüssel „cliTools.toolDescriptions.opencode“, „cliTools.toolDescriptions.kiro“, „cliTools.guides.opencode“, „cliTools.guides.kiro“ zu „en.json“ hinzugefügt -**i18n**: 1111 fehlende Schlüssel in allen 29 nicht-englischsprachigen Dateien synchronisiert, wobei englische Werte als Fallbacks verwendet wurden## [2.3.5] - 2026-03-11\n\n### Fixed\n\n-**@swc/helpers**: Permanenter „Postinstall“-Fix hinzugefügt, um „@swc/helpers“ in die „node_modules“ der eigenständigen App zu kopieren – verhindert MODULE_NOT_FOUND-Absturz bei globalen npm-Installationen## [2.3.4] - 2026-03-10\n\n### Added\n\n- Mehrere Anbieterintegrationen und Dashboard-Verbesserungen\n"}, "d33c0ed1b5e66c2e1d848ebf52928f520e6b3f42": {"t": 1785765406.035644, "n": 168185, "h": "ea652bac5c85894b", "c": "# Changelog (Deutsch)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.5.3] - 2026-04-05\n\n### Fixed\n\n- **Middleware:** Resolved infinite redirect loop on dashboard for fresh instances when requireLogin is disabled.\n\n---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n- **Qoder API Native Integration:** Completely refactored the Qoder Executor to bypass the legacy COSY AES/RSA encryption algorithm, routing directly into the native DashScope OpenAi-compatible URL. Eliminates complex dependencies on Node `crypto` modules while improving stream fidelity.\n- **Resilience Engine Overhaul:** Integrated context overflow graceful fallbacks, proactive OAuth token detection, and empty-content emission prevention (#990).\n- **Context-Optimized Routing Strategy:** Added new intelligent routing capability to natively maximize context windows in automated combo deployments (#990).\n\n### 🐛 Bug Fixes\n\n- **Responses API Stream Corruption:** Fixed deep-cloning corruption where Anthropic/OpenAI translation boundaries stripped `response.` specific SSE prefixes from streaming boundaries (#992).\n- **Claude Cache Passthrough Alignment:** Aligned CC-Compatible cache markers consistently with upstream Client Pass-Through mode preserving prompt caching.\n- **Turbopack Memory Leak:** Pinned Next.js to strict `16.0.10` preventing memory leaks and build staleness from recent upstream Turbopack hashed module regressions (#987).\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **Models.dev Integration:** Integrated models.dev as the authoritative runtime source for model pricing, capabilities, and specifications, overriding hardcoded prices. Includes a settings UI to manage sync intervals, translation strings for all 30 languages, and robust test coverage.\n- **Provider Native Capabilities:** Added support for declaring and checking native API features (e.g. `systemInstructions_supported`) preventing failures by sanitizing invalid roles. Currently configured for Gemini Base and Antigravity OAuth providers.\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Sicherheit\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Funktionen\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Sicherheit\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicherheit\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicherheit\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Dokumentation\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Dokumentation\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funktionen\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funktionen\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funktionen\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicherheit\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funktionen\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funktionen\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funktionen\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funktionen\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funktionen\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funktionen\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funktionen\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funktionen\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicherheit\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\bany\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funktionen\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funktionen\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funktionen\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funktionen\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funktionen\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funktionen\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Dokumentation\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funktionen\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "b100325fe0e34ff2cbf20eb3e0b78929d25babbf": {"t": 1785765408.1653848, "n": 168040, "h": "01dce32742494eaf", "c": "# Changelog (Deutsch)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n\n## [Unreleased]\n\n---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n- **Qoder API Native Integration:** Completely refactored the Qoder Executor to bypass the legacy COSY AES/RSA encryption algorithm, routing directly into the native DashScope OpenAi-compatible URL. Eliminates complex dependencies on Node `crypto` modules while improving stream fidelity.\n- **Resilience Engine Overhaul:** Integrated context overflow graceful fallbacks, proactive OAuth token detection, and empty-content emission prevention (#990).\n- **Context-Optimized Routing Strategy:** Added new intelligent routing capability to natively maximize context windows in automated combo deployments (#990).\n\n### 🐛 Bug Fixes\n\n- **Responses API Stream Corruption:** Fixed deep-cloning corruption where Anthropic/OpenAI translation boundaries stripped `response.` specific SSE prefixes from streaming boundaries (#992).\n- **Claude Cache Passthrough Alignment:** Aligned CC-Compatible cache markers consistently with upstream Client Pass-Through mode preserving prompt caching.\n- **Turbopack Memory Leak:** Pinned Next.js to strict `16.0.10` preventing memory leaks and build staleness from recent upstream Turbopack hashed module regressions (#987).\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **Models.dev Integration:** Integrated models.dev as the authoritative runtime source for model pricing, capabilities, and specifications, overriding hardcoded prices. Includes a settings UI to manage sync intervals, translation strings for all 30 languages, and robust test coverage.\n- **Provider Native Capabilities:** Added support for declaring and checking native API features (e.g. `systemInstructions_supported`) preventing failures by sanitizing invalid roles. Currently configured for Gemini Base and Antigravity OAuth providers.\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Sicherheit\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Funktionen\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Sicherheit\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicherheit\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicherheit\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Dokumentation\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Dokumentation\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funktionen\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funktionen\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funktionen\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicherheit\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funktionen\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funktionen\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funktionen\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funktionen\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funktionen\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funktionen\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funktionen\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funktionen\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicherheit\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funktionen\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funktionen\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funktionen\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funktionen\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funktionen\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funktionen\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Dokumentation\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funktionen\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "bd281e5753a872fcae52091f909734e96710f61e": {"t": 1785765409.8048177, "n": 166298, "h": "19fef8ac91eddc16", "c": "# Changelog (Deutsch)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Sicherheit\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Funktionen\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Sicherheit\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicherheit\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicherheit\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Dokumentation\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Dokumentation\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funktionen\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funktionen\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funktionen\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicherheit\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funktionen\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funktionen\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funktionen\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funktionen\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funktionen\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funktionen\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funktionen\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funktionen\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicherheit\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funktionen\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funktionen\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funktionen\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funktionen\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funktionen\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funktionen\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Dokumentation\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funktionen\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "19f46eb81743cf9992edc6ff7af268a1da79ffe6": {"t": 1785765411.5242436, "n": 165617, "h": "764a3947059707e2", "c": "# Changelog (Deutsch)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Sicherheit\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Funktionen\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Sicherheit\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicherheit\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicherheit\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Dokumentation\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Dokumentation\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funktionen\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funktionen\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funktionen\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicherheit\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funktionen\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funktionen\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funktionen\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funktionen\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funktionen\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funktionen\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funktionen\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funktionen\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicherheit\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funktionen\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funktionen\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funktionen\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funktionen\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funktionen\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funktionen\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Dokumentation\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funktionen\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "bfeb1693d691d7e3e60da1fc1c81b3ccf113c42f": {"t": 1785765413.5314484, "n": 151798, "h": "c51af8c60ca68d39", "c": "# Changelog (Deutsch)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n### 🛠️ Maintenance\n\n- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.\n\n## [3.4.2] - 2026-04-01\n\n### 🐛 Bug Fixes\n\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.\n\n### 🛠️ Maintenance\n\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicherheit\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicherheit\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Dokumentation\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Dokumentation\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funktionen\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funktionen\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funktionen\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicherheit\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funktionen\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funktionen\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funktionen\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funktionen\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funktionen\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funktionen\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funktionen\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funktionen\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicherheit\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funktionen\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funktionen\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funktionen\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funktionen\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funktionen\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funktionen\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Dokumentation\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funktionen\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}, "e071393eb5ed2de0eff9eefa7d275cd313b3b40a": {"t": 1785765415.303644, "n": 143875, "h": "ab0066877a53cb84", "c": "# Changelog (Deutsch)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)\n\n---\n\n\n## [Unreleased]\n\n---\n\n## [3.3.9] - 2026-03-31\n\n### 🐛 Bug Fixes\n\n- **Custom Provider Rotation:** Integrated `getRotatingApiKey` internally inside DefaultExecutor, ensuring `extraApiKeys` rotation triggers correctly for custom and compatible upstream providers (#815)\n\n---\n\n## [3.3.8] - 2026-03-30\n\n### Funktionen\n\n- **Models API Filtering:** Endpoint `/v1/models` now dynamically filters its list based on the permissions tied to the `Authorization: Bearer ` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Sicherheit\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Sicherheit\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\\\Program Files\\\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Dokumentation\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Dokumentation\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funktionen\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funktionen\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funktionen\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Sicherheit\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funktionen\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funktionen\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funktionen\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funktionen\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funktionen\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funktionen\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funktionen\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funktionen\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Sicherheit\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\\bany\\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funktionen\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funktionen\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funktionen\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funktionen\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funktionen\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funktionen\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Dokumentation\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funktionen\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}}, "docs/i18n/pl/CHANGELOG.md": {"63029ae7eb5118baa91257939233db8fb0aed60b": {"t": 1786067815.3152564, "n": 229461, "h": "3bd8b4706965ea92", "c": "# Changelog (Polski)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.6.8] — 2026-04-17\n\n### ✨ New Features\n\n- **feat(providers):** Support `xhigh` reasoning tier exclusively on Claude models that expose it (#1356)\n- **feat(providers):** Add CC Compatible connection-level 1M context toggle (#1357)\n- **feat(core):** Add full support for Node.js 24 LTS (Krypton) environments with continuous integration coverage (#1340)\n- **feat(dashboard):** Display Antigravity credit balance in dashboard Limits & Quotas (#1338)\n- **feat(i18n):** Add internationalization support for combo features and dashboard components; sync translations across 31 keys (#1318)\n- **feat(providers):** Add Claude Opus 4.7 to Claude Code OAuth models natively with extended context and caching (#1347)\n- **feat(core):** Add stopSequences support and expand tool definitions to include Google Search capabilities\n- **feat(auth):** Enforce dashboard session authentication on all management API routes, preventing unauthenticated access to configuration endpoints\n- **feat(runtime):** Add hot-reloadable guardrails and model diagnostics for real-time rule evaluation without restarts\n- **feat(core):** Add payload rules, tag-based routing, and scheduled budget systems for fine-grained request governance\n- **feat(providers):** Expose Antigravity preview model aliases and Gemini CLI onboarding flow for first-time setup\n- **feat(antigravity):** Add client model aliases and thoughtSignature bypass modes for Antigravity OAuth connections\n- **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations\n- **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages\n\n### Bezpieczeństwo\n\n- **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns\n- **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353)\n- **fix(providers):** Resolve Codex token refresh race condition via mutex `getAccessToken` preventing `refresh_token_reused` Auth0 revocations\n\n### 🔧 Maintenance & Architecture\n\n- **refactor(core):** Split CLI runner and decouple migration engine for extensibility (#1358)\n- **refactor(audit):** Rewire audit dashboard from dead in-memory `configAudit` store to live SQLite `audit_log` table — 331+ hidden compliance entries now visible in `/dashboard/audit`\n- **build(deps):** Bump `softprops/action-gh-release` from v2 to v3\n- **ci:** Bump GitHub Actions CI node-version to Node.js 24 natively\n- **fix(types):** Resolve TypeScript compilation errors in `claudeCodeCompatible.ts` (type predicates, `cache_control` index access) and `proxyFetch.ts` (`signal` nullability)\n\n### 🐛 Bug Fixes\n\n- **fix(context):** Scale reserved context tokens dynamically using a 15% sliding window for smaller models\n- **test(core):** Replace unit test with integration test for proactive context compression to align with isolated runner rules (#1378)\n- **fix(services):** Pass origin provider to refreshWithRetry to avoid tripping the generic \"unknown\" circuit breaker (fixes Codex accounts erroneously disabling)\n- **fix(db):** Prevent native module ABI load crashes from assuming database corruption and skipping databases\n- **fix(db):** Increase mass-migration threshold from 5 to 50 pending migrations to protect legacy users upgrading node\n- **fix(db):** Prevent migration runner safety aborts from triggering on fresh `DATA_DIR` installations by detecting new databases (#1328)\n- **fix(mcp):** Checkpoint and close MCP audit SQLite database safely on process signals and shutdown (#1348)\n- **fix(mcp):** Fully decouple MCP audit SQLite connection caching via globalThis to fix unhandled teardown in standalone Next.js chunks (#1349)\n- **fix(cli):** Avoid creating app router directory during postinstall initialization on non-built source trees (#1351)\n- **fix(codex):** Correctly translate `system` role to `developer` in input array to unlock GPT-5 automatic prompt caching (#1346)\n- **fix(core):** Pass client headers to executor in chatCore (#1335)\n- **fix(providers):** Separate test batch calls and ignore unknown connections\n- **fix(providers):** Add grok-web SSO cookie validation handler (#1334)\n- **fix(db):** Preserve key_value settings (dashboard passwords, saved aliases) across DB heuristic recreation cycles (#1333)\n- **fix(routing):** Allow combo fallback to cascade context overflow 400 errors instead of immediate aborts (#1331)\n- **fix(core):** Resolve thinking leaks, consecutive roles, and missing thoughtSignatures for Antigravity translator (#1316)\n- **fix(translator):** Only apply thoughtSignature to the first `functionCall` part in Gemini parallel tool calls, preventing duplicate signatures\n- **fix(providers):** Default to batch testing execution blocks for web, search, and audio modalities to prevent connection timeouts\n- **fix(cli):** Resolve Node 22 TS entrypoint incompatibility by using esbuild compilation (#1315)\n- **fix(chat):** Preserve max_output_tokens for Responses API targets in chatCore sanitization (#1313)\n- **fix(api):** API Manager usage stats showing 0 for all registered keys (#1310)\n- **fix(api):** Support image-only models in catalog and allow authless search providers to bypass validation requirements\n- **fix(routes):** Require prompts for media generation requests (`/images`, `/videos`, `/music`), returning 400 on missing payloads\n- **fix(dashboard):** Auto-scroll ActivityHeatmap to show current date (#1309)\n- **fix(dashboard):** Restore horizontal layout with `w-max` wrapper in heatmap components\n- **fix(i18n):** Update `nodeIncompatibleHint` to recommend Node 24 LTS across all 31 languages\n- **fix(i18n):** Add Chinese i18n support to remaining dashboard components (`Loading.tsx`, `DataTable`, etc.)\n- **fix(requestLogger):** Add missing `cacheSource` and `tps` columns to i18n log detail views\n\n## [3.6.6] — 2026-04-15\n\n### ✨ New Features\n\n- **feat(storage):** Add database backup cleanup controls, UI management, and customizable retention period env vars (#1304)\n- **feat(providers):** Add Freepik Pikaso image generation provider with support for cookie/subscription-based auth modes (#1277)\n- **feat(providers): Add Perplexity Web (Session) Provider** — Routes through Perplexity's internal SSE API using a session cookie, giving native proxy access without separate API costs to GPT-5.4, Claude Opus, Gemini 3.1 Pro, and Nemotron via preferences mapping (#1289)\n- **feat(api): Sync Tokens & V1 WebSocket Bridge** — Dedicated sync token storage, issuance, revocation, and bundle download routes backed by stable config bundle versioning with ETag support. Exposes `/v1/ws` WebSocket upgrade route and a custom Next.js server bridge (`scripts/v1-ws-bridge.mjs`) so OpenAI-compatible WebSocket traffic can be proxied through the gateway. Compliance auditing expanded with structured metadata, pagination, request context, auth/provider credential events, and SSRF-blocked validation logging. New migrations: `024_create_sync_tokens.sql`. New modules: `syncTokens.ts`, `src/lib/sync/bundle.ts`, `src/lib/sync/tokens.ts`, `src/lib/ws/handshake.ts`, `src/lib/apiBridgeServer.ts`, `src/lib/compliance/providerAudit.ts`.\n- **feat(models): GLM Thinking Preset & Hybrid Token Counting** — GLM Thinking (`glmt`) registered as a first-class provider preset with shared GLM model metadata, pricing, per-connection usage sync, dashboard support, and `maxTokens: 65536 / thinkingBudgetTokens: 24576` request defaults with 900s extended timeout. Provider-side `/messages/count_tokens` endpoint used when a Claude-compatible upstream supports it; gracefully falls back to estimation on missing models, missing credentials, or upstream failures. Startup seeding of default model aliases (`src/lib/modelAliasSeed.ts`) normalizes common cross-proxy model dialects so canonical slash-based model IDs are not misrouted. New file `open-sse/config/glmProvider.ts`.\n- **feat(core): Hardened Outbound Provider Calls & Cooldown Retries** — Guarded outbound fetch helpers (`src/shared/network/safeOutboundFetch.ts`, `src/shared/network/outboundUrlGuard.ts`) blocking private/local URLs with configurable retry, timeout normalisation, and route-level status propagation for provider validation and model discovery. Cooldown-aware chat retries (`src/sse/services/cooldownAwareRetry.ts`) with configurable `requestRetry` and `maxRetryIntervalSec` settings and model-scoped cooldown responses. Improved rate-limit learning from headers and error bodies so short upstream lockouts can recover automatically. Runtime environment validation (`src/lib/env/runtimeEnv.ts`) checks env at startup. Pollinations now requires an API key. Antigravity and Codex header handling aligned via `open-sse/config/antigravityUpstream.ts` and `open-sse/config/codexClient.ts`. Gemini tool names restored in translated responses; synthetic Claude text block injected when upstream SSE completes empty.\n- **feat(logs):** Add TPS (Tokens Per Second) metric to log details modal metadata grid (#1182)\n- **feat(memory+skills):** Full-featured Memory & Skills systems with FTS5 SQLite search, dynamic UI pagination, backend observability, and extensive test coverage (#1228)\n- **feat(bailian-quota):** Add Alibaba Coding Plan quota monitoring, multi-window quota extraction, and UI credential validation (#1235)\n- **feat(storage): Call Log Storage Refactor** — Extracted heavy request/response JSON payloads from the core SQLite database (`storage.sqlite`) into filesystem artifacts stored within `DATA_DIR/call_logs`. This massively reduces WAL bloat and eliminates `SQLITE_FULL` crashes on high-traffic nodes (#1307).\n- **feat(providers): Add Grok Web (Subscription) Provider** — Routes through the xAI web interface for subscription users via cookie session mapping (#1295).\n- **feat(api): Advanced Media Support** — Extends OpenAI generic proxy layer to natively support `image`, `embeddings`, `audio-transcriptions`, and `audio-speech` workflows (#1297).\n- **feat(cli-tools): Qwen Code CLI Integration** — Full integration for Qwen Code local execution mapping, model resolution, and dynamic API key fetching (#1266, #1263).\n- **feat(oauth):** Supports `cursor-agent` CLI as a native Cursor credential source alongside the standard configuration (#1258).\n- **feat(models):** Custom and imported models now merge correctly into filter lists for all available global providers (#1191).\n\n### 🐛 Bug Fixes\n\n- **fix(providers):** match correct endpoint api.xiaomimimo.com for Xiaomi MiMo (#1303)\n- **fix(core):** strip provider alias routing prefix from payload for custom endpoints to fix Azure OpenAI 400 errors (#1261)\n- **fix(core):** ProxyFetch Undici dispatcher automatically bypasses LAN/local addresses, preventing fetch failures on internal OpenRouter requests (#1254)\n- **fix(core):** Gemini thought stream signature detection upgraded to use native part.thought boolean, preventing reasoning text leaks (#1298)\n- **deps:** bump hono from 4.12.12 to 4.12.14 to resolve CVE SSR HTML injection vulnerability (#1306, #59)\n- **deps:** update dompurify to 3.4.0 in frontend overrides mitigating XSS HTML Injection (CVE-XYZ / Dependabot #60)\n- **test:** Disable SQLite automatic backups during continuous integration (CI) tests to resolve E2E timeout issues limiting runner scaling (#24481475058)\n- **feat(core): Proactive Context Compression** — `chatCore` now proactively compresses oversized message contexts before hitting upstream providers to dramatically reduce `context_length_exceeded` errors. Employs binary-search message pruning with structural integrity guarantees tracking explicit `tool_use` boundaries ensuring truncated tool inputs drop paired outputs appropriately (#1292, #1293)\n\n- **fix(cli):** Resolve codex routing config parsing by strictly quoting section keys array, enforcing responses wire_api with fallback, and standardizing select-model button positioning mirroring Claude UI\n- **fix(providers):** Correct Lobehub provider icons rendering by removing unsupported local references ensuring local SVG/PNG fallback mechanism invokes natively\n- **fix(db):** Implement Database migration tracking safety abort safeguards (pre-migration backups via `VACUUM INTO` and mass renumbering warnings) to protect existing database structures on startup upgrades (#1281)\n- **fix(dashboard):** Cleaned up target codex `config.toml` structure preventing recursive section rendering by enforcing quotes on section dot paths and mapping correct UI `OMNIROUTE_API_KEY` names.\n- **fix(mcp):** Add dedicated explicit timeout constraint overrides for search handlers (#1280)\n- **fix(crypto):** Add validation guard to encryption layer to surface clear UI errors when cryptographic environment variables are missing, replacing raw Node.js TypeErrors. Legacy env vars `OMNIROUTE_CRYPT_KEY` and `OMNIROUTE_API_KEY_BASE64` now also accepted as fallbacks (#1165)\n- **fix(providers):** Update Pollinations provider definition to require API keys and specify their new limited pollen/hour free tier (#1177)\n- **Streaming `\\n\\n` Artifact Fix (#1211):** Changed `` tag-stripping regex from `?` to `*` quantifier across `combo.ts`, `comboAgentMiddleware.ts`, and `contextHandoff.ts` to greedily strip all accumulated JSON-escaped newline sequences surrounding the tag. This prevents literal `\\n\\n` prefix artifacts from appearing in consumer streaming responses\n- **E2E Combo Test Locator:** Fixed Playwright strict-mode violation in `combo-unification.spec.ts` by replacing ambiguous `getByRole` locator with a compound filter locator for the \"All\" strategy tab\n- **fix(cc-compatible):** Trim beta flags and preserve cache passthrough for third-party HTTP proxy compatibility (#1230)\n- **fix(providers):** Update Xiaomi MiMo endpoints to the live token-plan, migrating away from dead API URLs (#1238)\n- **fix:** Forward client `x-initiator` header to GitHub Copilot upstream to accurately distinguish agent vs user turns (#1227)\n- **fix:** Resolve backlog bugs including streaming edge cases, unhandled rejections, and quota parse failures (#1206, #1220, #1231, #1175, #1187, #1218, #1202)\n- **fix(tests):** Resolve memory migration and skills route pagination bugs arising from PR overlaps\n- **fix(i18n):** Add missing Chinese i18n support to dashboard components (`DataTable`, `EmptyState`, etc), update `en.json/zh-CN.json` routing keys, and natively resolve JSX defaults via `next-intl` (#1274)\n\n### 🔧 Internal Improvements\n\n- **Compliance Audit Expansion:** `src/lib/compliance/index.ts` expanded with structured metadata, pagination support, request context enrichment, and new `providerAudit.ts` module logging auth and provider credential events, SSRF-blocked validation attempts, and provider CRUD operations\n- **Config Sync Bundle:** `src/lib/sync/bundle.ts` exports `buildConfigBundle()` generating a versioned JSON snapshot of settings, provider connections, nodes, model aliases, combos, and API keys (passwords redacted) with ETag support for bandwidth-efficient polling\n- **Codex Client Constants:** Centralized `CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT_PLATFORM`, and pattern-validated env overrides (`CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT`) in `open-sse/config/codexClient.ts`\n- **Antigravity Upstream Constants:** `open-sse/config/antigravityUpstream.ts` consolidates all Antigravity base URLs and model/fetchAvailableModels discovery path builders\n- **Model Alias Seed:** `src/lib/modelAliasSeed.ts` seeds 30+ cross-proxy model dialect aliases (e.g. `openai/gpt-5` → `gpt-5`, `anthropic/claude-opus-4-6` → `cc/claude-opus-4-6`) at startup via idempotent `upsert`\n- **Test Coverage:** 15+ new unit test suites covering sync routes, WebSocket bridge, compliance index, GLM provider config, cooldown-aware retry, safe outbound fetch, stream utilities, Codex executor, provider validation branches, model cross-proxy compatibility, and model alias seeding\n- **TypeScript Migration:** Finalized migration of remaining JS tests (`proxy-load` and `testFromFile`) to TypeScript ES modules, ensuring a fully synchronized TS stack.\n- **Reliability & Resilience:** Added exponential backoff to `models.dev` auto-sync to combat transient network failures, raised interval floor to 1 hour, and added LKGP debug logging for enhanced observability during routing. (#1286)\n\n---\n\n## [3.6.5] — 2026-04-13\n\n### ✨ New Features\n\n- **Antigravity AI Credits Fallback:** Automatically retries with `GOOGLE_ONE_AI` credit injection when free-tier quota is exhausted. Per-account credit balance (5-hour TTL) is cached from SSE `remainingCredits` and exposed as a numeric badge in the Provider Usage dashboard (#1190 — thanks @sFaxsy)\n- **Claude Code Native Parity:** Full header/body signing parity with the Claude Code 2.1.87 OAuth client — CCH xxHash64 body signing with singleton WASM initialization promise (fixing race conditions), dynamic per-request fingerprint, bidirectional TitleCase ↔ lowercase tool name remapping (14 tools), API constraint enforcement (`temperature=1` for thinking, max 4 `cache_control` blocks, auto-inject ephemeral on last user message), and optional ZWJ obfuscation. Wired into `BaseExecutor` for automatic CCH signing on all `anthropic-compatible-cc-*` providers and into `chatCore` for synchronous parity pipeline steps (#1188 — thanks @RaviTharuma)\n- **Per-Connection Codex Defaults:** Codex Fast Service Tier and Reasoning Effort settings are now per-connection instead of a single global toggle. Existing connections are migrated automatically on startup via an idempotent backfill migration (#1176 — thanks @rdself)\n- **Cursor Usage Dashboard:** New `getCursorUsage()` fetches quotas from Cursor's `/api/usage`, `/api/auth/me`, and `/api/subscription` endpoints. Displays standard requests, on-demand usage, and per-plan limits (Free/Pro/Business/Team). Client version bumped to `3.1.0` and `x-cursor-user-agent` header added for parity\n- **Database Health Check System:** Automated periodic SQLite integrity monitoring via `runDbHealthCheck()` — detects orphan quota/domain rows, broken combo references, stale snapshots, and invalid JSON state. Runs every 6 hours (configurable via `OMNIROUTE_DB_HEALTHCHECK_INTERVAL_MS`), with auto-repair and pre-repair backup. Exposed as **MCP tool #18** (`omniroute_db_health_check`) with Zod schemas and `autoRepair` option. Dashboard panel in Health page with status card, issue count, repaired count, and one-click repair button\n- **OpenAI Responses API Store Opt-In:** Per-connection `openaiStoreEnabled` flag controls whether the `store` field is preserved or forced to `false` on Codex Responses API requests. When enabled, `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields are round-tripped through the Chat Completions → Responses translation, enabling multi-turn context caching on supported providers\n- **Email Privacy Toggle (Combos Page):** Global email visibility toggle (`EmailPrivacyToggle`) added to the Combos page header with responsive layout, tooltip guidance, and per-connection label masking via `pickDisplayValue()`. All combo builder options, provider connection lists, and quota screens now respect the global privacy state from `emailPrivacyStore`\n- **skills.sh Integration:** Added `skills.sh` as an external skill provider. Users can now search, browse, and install agent skills directly from a new \"skills.sh\" tab in the Skills dashboard. Includes backend API resolvers, frontend implementation with search/install states, and a dedicated unit test suite (#1223 — thanks @RaviTharuma)\n- **Stabilization Settings:** Added persistence support for `lkgpEnabled` and `backgroundDegradation` settings, integrated into `instrumentation-node.ts` for improved lifecycle awareness (#1212)\n- **xxhash-wasm dependency:** Added `xxhash-wasm@^1.1.0` for CCH signing (xxHash64 with seed `0x6E52736AC806831E`)\n\n### 🐛 Bug Fixes\n\n- **Codex `stream: false` via Combo (ALL_ACCOUNTS_INACTIVE):** Fixed a critical bug where Codex combos returned `ALL_ACCOUNTS_INACTIVE` or empty content when the client sent `stream: false`. Root cause was triple: (1) `CodexExecutor.transformRequest()` mutated `body.stream` in-place to `true`, contaminating the combo's quality check which skipped validation thinking it was streaming; (2) the non-stream SSE parser used the wrong format (Chat Completions instead of Responses API) for Codex SSE output; (3) combo quality validation read the mutated `body.stream` instead of the client's original intent. Fixed by: cloning the body via `structuredClone()` in CodexExecutor, detecting Codex/Responses SSE format in the non-stream fallback path (with auto-translation back to Chat Completions), and capturing `clientRequestedStream` before the combo loop\n- **Gemini CLI Tool Schema Rejection:** Fixed 400 Bad Request errors from the Google API by strictly filtering non-standard vendor extensions (starting with `x-`) and `deprecated` fields from tool parameter schemas (#1206)\n- **SOCKS5 Proxy Interop (Node.js 22):** Resolved `invalid onRequestStart method` crashes caused by `undici` version mismatches between dispatchers and the built-in fetch. Hardened `proxyFetch.ts` to strictly use the library's fetch implementation for custom dispatchers (#1219)\n- **Search Cache Coalescing with TTL=0:** Fixed a bug where providers configured with `cacheTTLMs: 0` (caching explicitly disabled) still had concurrent requests coalesced and returned `{ cached: true }`. Now each call gets its own independent upstream fetch (#1178 — thanks @sjhddh)\n- **Antigravity Credit Cache Alignment (PR #1190):** Reconciled `accountId` derivation between `AntigravityExecutor.collectStreamToResponse` and `getAntigravityUsage` to use consistent cache keys (`email || sub || \"unknown\"`). Previously, SSE-parsed credit balances could be written under a different key than the one read by the usage dashboard, causing stale/missing credit badges\n- **Non-streaming reasoning_content Duplication:** Fixed clients rendering duplicated reasoning panels when both `reasoning_content` and visible `content` were present in non-streaming responses. `responseSanitizer` now strips `reasoning_content` from messages that already have visible text content, preserving it only for reasoning-only messages\n- **Streaming Regression Fix:** Hardened the `sanitize` TransformStream in the combo engine to strip both literal and JSON-escaped newline sequences, eliminating leading `\\n\\n` prefixes in assistant responses (#1211)\n- **Gemini Empty Choice Fix:** Ensured initial assistant deltas always include an empty `content: \"\"` string to satisfy strict OpenAI client requirements and prevent empty choice responses in tools (#1209)\n- **Gemini Tools Sanitizer Deduplication:** Extracted shared tool conversion logic into `buildGeminiTools()` helper (`geminiToolsSanitizer.ts`), eliminating duplicate implementations between `openai-to-gemini.ts` and `claude-to-gemini.ts`. The new helper correctly handles `web_search` / `web_search_preview` tool types by emitting `googleSearch` tools with priority over function declarations\n- **Qwen/Qoder Thinking+Tool_Choice Conflict:** Added `sanitizeQwenThinkingToolChoice()` to both `DefaultExecutor` (for Qwen provider) and `QoderExecutor` to prevent provider-side 400 errors when clients send `tool_choice` alongside thinking/reasoning parameters that are mutually exclusive upstream\n- **API Key Deletion Orphan Cleanup:** Deleting an API key now also removes associated `domain_budgets` and `domain_cost_history` rows, preventing orphan data accumulation\n- **CC-compatible test assertion:** Fixed pre-existing test that expected no `cache_control` on system blocks — the billing header system block now carries `cache_control: { type: \"ephemeral\" }` per PR #1188 design\n- **Codex Combo Smoke Test False Positives:** Fixed combo tests incorrectly reporting `ERROR` for valid Codex streaming responses when `response.output` is empty but text deltas were emitted. The summary now falls back to accumulated delta text (#1176 — thanks @rdself)\n- **Electron Builder Version Mismatch:** Fixed Electron desktop startup failures on Windows packaged builds caused by native modules (`better-sqlite3`) being under `app.asar.unpacked` while helpers were in `app/node_modules`. `resolveServerNodePath()` now merges both locations with deduplication and existence checks (#1172 — thanks @backryun)\n\n### 🔧 Internal Improvements\n\n- **SSE Parser: Responses API Non-Stream Conversion:** Added full `parseSSEToResponsesOutput()` implementation in `sseParser.ts` (255+ lines) — reconstructs complete Responses API objects from SSE event streams, handling `response.output_text.delta/done`, `response.reasoning_summary_text.delta/done`, `response.function_call_arguments.delta/done`, and terminal events. Used by the new chatCore non-stream fallback path for Codex\n- **Cursor Executor Version Sync:** Updated Cursor client User-Agent to `3.1.0` and centralized version constants (`CURSOR_CLIENT_VERSION`, `CURSOR_USER_AGENT`) for consistent fingerprinting across executor, usage fetcher, and OAuth flows\n- **Responses API Translator Parity:** `convertResponsesApiFormat()` now accepts credentials and passes them through to the translator, enabling store-aware field propagation. Round-trip preservation of `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields\n- **Provider Schema Validation:** Added `openaiStoreEnabled` boolean validation to `providerSpecificData` Zod schema\n- **Combo Error Response Normalization:** Empty combo targets now return 404 (`comboModelNotFoundResponse`) instead of generic 503, improving client-side error differentiation\n- **Dependency Updates:** Bumps `typescript-eslint` to `8.58.2` (dev), `axios` to `1.15.0` (prod), and `next` to `16.2.2` (prod) (#1224, #1225)\n\n### ⚠️ Breaking Changes\n\n- **`DELETE /api/settings/codex-service-tier` removed:** This endpoint no longer exists. Codex Service Tier configuration has moved to per-connection `providerSpecificData.requestDefaults`. Existing connections are migrated automatically on first startup after upgrade. Any external scripts or integrations that call this endpoint should be updated — use `PUT /api/providers/:id` with `providerSpecificData.requestDefaults.serviceTier` instead (#1176).\n- **CCH signing on CC-compatible providers:** All requests to `anthropic-compatible-cc-*` providers now include an xxHash64 integrity token (`cch=...`) in the billing header. Providers that do not validate CCH will ignore it (no behavioral change), but any custom middleware inspecting the billing header should expect a 5-character hex token instead of the `00000` placeholder\n\n---\n\n## [3.6.4] — 2026-04-12\n\n### ✨ New Features\n\n- **Combo Builder v2 (Wizard UI):** Completely redesigned the combo creation/editing interface as a multi-stage wizard with stages: Basics → Steps → Strategy → Review. The builder fetches provider, model, and connection metadata via a new `GET /api/combos/builder/options` endpoint, enabling precise provider/model/account selection with duplicate detection and automatic next-connection suggestion. Heavy UI components (`ModelSelectModal`, `ProxyConfigModal`, `ModelRoutingSection`) are now lazily loaded via `next/dynamic` for faster initial page render\n- **Combo Step Architecture (Schema v2):** Introduced a structured step model (`ComboModelStep`, `ComboRefStep`) replacing the legacy flat string/object combo entries. Steps carry explicit `id`, `kind`, `providerId`, `connectionId`, `weight`, and `label` fields, enabling pinned-account routing, cross-combo references, and per-step metrics. All combo CRUD operations normalize entries through the new `src/lib/combos/steps.ts` module. Zod schemas updated with `comboModelStepInputSchema` and `comboRefStepInputSchema` unions\n- **Composite Tiers System:** Added tiered model routing via `config.compositeTiers` — each tier maps a named stage to a specific combo step with optional fallback chains. Includes comprehensive validation (`src/lib/combos/compositeTiers.ts`) ensuring step existence, preventing circular fallback, and validating default tier references. Zod schema enforcement blocks composite tiers on global defaults (concrete combos only)\n- **Model Capabilities Registry:** Created `src/lib/modelCapabilities.ts` providing `getResolvedModelCapabilities()` — a unified resolver that merges static specs, provider registry data, and live-synced capabilities into a single `ResolvedModelCapabilities` object covering tool calling, reasoning, vision, context window, thinking budget, modalities, and model lifecycle metadata\n- **Observability Module:** Extracted health and telemetry payload construction into `src/lib/monitoring/observability.ts` with `buildHealthPayload()`, `buildTelemetryPayload()`, and `buildSessionsSummary()` builders. The health endpoint now returns session activity, quota monitor status, and per-provider breakdowns alongside existing system metrics\n- **Session & Quota Monitor Dashboard:** Added live Session Activity and Quota Monitors panels to the Health dashboard, showing active session counts, sticky-bound sessions, per-API-key breakdowns, and top session details alongside quota monitor alerting/exhausted/error status with per-provider drill-down\n- **Combo Health Per-Target Analytics:** The combo-health API now resolves per-target metrics using the new `resolveNestedComboTargets()` function, providing step-level success rates, latency, and historical usage breakdowns per execution key — enabling per-account, per-connection health visibility\n- **Auto-Combo → Combos Unification:** Merged the separate `/dashboard/auto-combo` page into the main `/dashboard/combos` page. Auto/LKGP combos are now managed alongside all other combos with a new strategy filter tabs system (All / Intelligent / Deterministic). The old auto-combo route redirects to `/dashboard/combos?filter=intelligent`. Removed the `auto-combo` sidebar entry, consolidating navigation into the single `Combos` item\n- **Intelligent Routing Panel (`IntelligentComboPanel`):** New inline panel (371 lines) within the combos page that shows real-time provider scores, 6-factor scoring breakdown (quota, health, cost, latency, task fitness, stability), mode pack selector, incident mode status, and excluded providers for `auto`/`lkgp` combos — replacing the former standalone auto-combo dashboard\n- **Builder Intelligent Step (`BuilderIntelligentStep`):** New conditional wizard step (280 lines) that appears in the Builder v2 flow only when `strategy=auto` or `strategy=lkgp` is selected. Exposes candidate pool selection, mode pack presets, router sub-strategy selector, exploration rate slider, budget cap, and collapsible advanced scoring weights configuration\n- **Intelligent Routing Module (`intelligentRouting.ts`):** Extracted strategy categorization and filtering logic into a dedicated shared module (210 lines) with `getStrategyCategory()`, `isIntelligentStrategy()`, `filterCombosByStrategyCategory()`, `normalizeIntelligentRoutingFilter()`, and `normalizeIntelligentRoutingConfig()` utility functions\n- **LKGP Standalone Strategy:** Implemented `lkgp` (Last Known Good Provider) as a fully functional standalone combo strategy. Previously, `lkgp` as a combo strategy silently fell through to `priority` ordering — the LKGP lookup only ran inside the `auto` engine. Now `strategy: \"lkgp\"` correctly queries the LKGP state, moves the last successful provider to the top of the target list, and saves the LKGP state after each successful request. Falls back to priority ordering when no LKGP state exists\n- **Unified Routing Rules & Model Aliases:** Consolidated the routing rules and model alias management controls into the Settings page, reducing fragmentation across the dashboard\n\n### ⚡ Performance\n\n- **Middleware Lazy Loading:** Refactored `src/proxy.ts` to lazy-import `apiAuth`, `db/settings`, and `modelSyncScheduler` modules, reducing middleware cold-start overhead. Added inline `isPublicApiRoute()` to avoid loading the full auth module for public routes\n- **E2E Auth Bypass:** Added `NEXT_PUBLIC_OMNIROUTE_E2E_MODE` environment flag to bypass authentication gates for dashboard and management API routes during Playwright E2E test runs\n\n### 🐛 Bug Fixes\n\n- **P2C Credential Selection:** Implemented Power-of-Two-Choices (P2C) connection scoring in `src/sse/services/auth.ts` with quota headroom awareness, error/recency penalties, and forced/excluded connection support. The new `getProviderCredentialsWithQuotaPreflight()` function integrates quota preflight checks directly into credential selection, eliminating the separate Codex-only preflight path\n- **Fixed-Account Combo Steps:** Combo steps with explicit `connectionId` now correctly bypass provider-level model cooldowns and circuit breakers, preventing a single account failure from blocking pinned-connection routing for the same model\n- **Combo Metrics Per-Target Tracking:** Extended `comboMetrics.ts` to track `byTarget` metrics keyed by execution path, recording per-step `provider`, `providerId`, `connectionId`, and `label` alongside existing per-model aggregates\n- **Call Logs Schema Expansion:** Added `requested_model`, `request_type`, `tokens_cache_read`, `tokens_cache_creation`, `tokens_reasoning`, `combo_step_id`, and `combo_execution_key` columns to `call_logs` with auto-migration. Added composite index `idx_cl_combo_target` for efficient per-target historical queries\n- **Quota Monitor Enrichment:** Expanded `quotaMonitor.ts` with full lifecycle state tracking (`status`, `startedAt`, `lastPolledAt`, `consecutiveFailures`, `totalPolls`, `totalAlerts`), ISO-formatted snapshots via `getQuotaMonitorSnapshots()`, and sorted summary via `getQuotaMonitorSummary()`\n- **Codex Quota Fetcher Hardening:** Improved `codexQuotaFetcher.ts` with safer connection registration and quota fetch error handling\n- **LKGP Save Refactored to Async/Await:** Replaced fire-and-forget `.then()` chain for LKGP persistence after successful combo routing with proper `async/await` + `try/catch`, preventing unhandled promise rejections and ensuring LKGP state is reliably saved before the response is returned\n- **Duplicate `auto` in Combo Strategy Schema:** Removed duplicate `\"auto\"` entry from `comboStrategySchema` (was listed on both line 104 and 108). Harmless to Zod runtime but cleaned up to avoid confusion. Schema now has exactly 13 unique strategy values\n- **Legacy Combo Refs Normalization:** Fixed combo step normalization to preserve legacy string combo references during CRUD operations, preventing data loss when editing combos created before the v2 step architecture\n\n### Bezpieczeństwo\n\n- **Auth Bypass on Backup Routes (Critical):** Added `isAuthenticated` guards to `/api/db-backups/exportAll` (full database export) and `/api/db-backups` (list, create, and restore backups) — both were previously accessible without authentication\n- **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency\n- **API Key Secret Hardening:** Removed the hardcoded `\"omniroute-default-insecure-api-key-secret\"` fallback from `apiKey.ts` — the function now fails fast if `API_KEY_SECRET` is unset, relying on the startup validator to auto-generate it\n- **NPM Tarball Leak Fix:** Added `app/.env*` to `.npmignore` to prevent the working `.env` file from being shipped inside the npm tarball distribution\n- **Electron Builder CVE Fix:** Bumped `electron-builder` to 26.8.1 to resolve `tar` CVEs in the desktop build pipeline\n\n### 🔧 Maintenance & Infrastructure\n\n- **DB Migration 021:** Added `combo_call_log_targets` migration for `combo_step_id` and `combo_execution_key` columns in call_logs\n- **Combo CRUD Normalization:** `db/combos.ts` now normalizes all stored combo entries through the step normalization pipeline on read, ensuring consistent step IDs and kind annotations regardless of when the combo was created\n- **Playwright Config:** Updated Playwright configuration and `run-next-playwright.mjs` script for improved E2E test orchestration\n- **Build Script:** Updated `build-next-isolated.mjs` with additional reliability improvements\n- **Auto-Combo UI Cleanup:** Deleted `AutoComboModal.tsx` (161 lines), replaced `auto-combo/page.tsx` (478→5 lines) with a server-side redirect to `/dashboard/combos?filter=intelligent`\n- **Sidebar Consolidation:** Removed `\"auto-combo\"` from `HIDEABLE_SIDEBAR_ITEM_IDS` and `PRIMARY_SIDEBAR_ITEMS` — `normalizeHiddenSidebarItems()` silently discards any stale `\"auto-combo\"` entries in user settings\n- **Schema Cleanup:** Removed obsolete `createAutoComboSchema` from `schemas.ts`. Exported `comboStrategySchema` for direct use in test and filter modules\n- **A2A Agent Card Update:** Renamed skill ID from `auto-combo` to `intelligent-routing` with updated description referencing the unified combos dashboard\n- **Builder Draft Refactor:** Extended `builderDraft.ts` with dynamic stage list generation via `getComboBuilderStages()` and `isIntelligentBuilderStrategy()`. Stage navigation (`getNextComboBuilderStage`, `getPreviousComboBuilderStage`, `canAccessComboBuilderStage`) now accepts options to conditionally include/skip the `intelligent` wizard step\n- **i18n Consolidation:** Removed the standalone `\"autoCombo\"` i18n block (22 keys) from all 30 language files. Migrated keys into the `\"combos\"` block with new additions for filter tabs, intelligent panel, and builder step labels\n\n### 🧪 Tests\n\n- **16 New Test Suites:** Added comprehensive test coverage including:\n - `combo-builder-draft.test.mjs` (186 lines) — Builder draft step construction and validation\n - `combo-builder-options-route.test.mjs` (228 lines) — Builder options API endpoint\n - `combo-health-route.test.mjs` (266 lines) — Combo health analytics with per-target metrics\n - `combo-routes-composite-tiers.test.mjs` (157 lines) — Composite tiers API integration\n - `composite-tiers-validation.test.mjs` (131 lines) — Composite tier validation rules\n - `db-combos-crud.test.mjs` — Combo CRUD with step normalization\n - `db-core-init.test.mjs` (129 lines) — DB initialization and column migrations\n - `model-capabilities-registry.test.mjs` (105 lines) — Model capabilities resolution\n - `observability-payloads.test.mjs` (165 lines) — Health/telemetry payload construction\n - `openapi-spec-route.test.mjs` — OpenAPI spec generation\n - `proxy-e2e-mode.test.mjs` (74 lines) — E2E mode auth bypass\n - `quota-monitor.test.mjs` — Quota monitor lifecycle state\n - `run-next-playwright.test.mjs` (119 lines) — Playwright runner script\n - `sse-auth.test.mjs` (154 lines) — P2C credential selection and quota preflight\n - `telemetry-summary-route.test.mjs` (35 lines) — Telemetry summary endpoint\n - Plus updates to 12 existing test files for compatibility with new step architecture\n- **Auto-Combo Unification Tests:**\n - `autocombo-unification.test.mjs` (156 lines) — Strategy categorization, schema deduplication, sidebar cleanup, and routing strategies metadata validation\n - `combo-unification.spec.ts` (189 lines) — Playwright E2E tests for filter tabs, intelligent panel rendering, redirect from old route, sidebar entry removal, and Builder v2 intelligent step flow\n - 3 new LKGP standalone tests in `combo-routing-engine.test.mjs` — Validates LKGP provider prioritization, fallback to priority when no state exists, and LKGP state persistence after successful requests\n - Updated `combo-builder-draft.test.mjs` with intelligent stage navigation tests\n - Updated `sidebar-visibility.test.mjs` to reflect `auto-combo` removal\n\n---\n\n## [3.6.3] — 2026-04-11\n\n### ✨ New Features\n\n- **OpenAI-Compatible Loose Validation:** Empty API keys can now be naturally submitted and saved for any `openai-compatible-*` providers (e.g. Pollinations, localized routes) directly in the UI instead of blocking save actions (#1152)\n- **Cloudflare Configuration:** Updated the provider schema and UI integration for Cloudflare AI to officially expose and support the backend `accountId` field securely without overrides (#1150)\n\n### 🐛 Bug Fixes\n\n- **Vertex JSON Validation Crash:** Prevented `invalid character in header` crashes inside the `/validate` endpoint by creating a native authentication parser that correctly handles Google Identity Service Account JSON flows prior to pinging endpoints (#1153)\n- **Extraneous Payload Rejection:** Globally prevented upstream `400 Bad Request` execution crashes by stripping the non-standard `prompt_cache_retention` attribute forcibly attached by Cursor/Cline IDE engines when targeting strict OpenAI/Anthropic routes (#1154)\n- **Reasoning Content Drop:** Prevented pure reasoning packets, common in advanced fallback models like DeepSeek, from being aborted mid-stream by explicitly adjusting the `Empty Content (502)` circuit breakers to acknowledge `reasoning_content` states as valid (#1155)\n- **Desktop Windows Build Crash:** Fixed `better_sqlite3.node is not a valid Win32 application` preventing OmniRoute Desktop from launching on Windows by properly removing the ABI-mismatched sqlite cache from Next.js standalone and falling back to the cross-compiled Electron equivalent during packager build steps (#1163)\n- **Login Visual Security:** Removed the raw fallback hash dump that artificially rendered underneath the login modal in Docker instances missing `OMNIROUTE_API_KEY_BASE64` flags (#1148)\n\n### 🔧 Maintenance & Dependencies\n\n- **Dependabot Updates:** Safely bumped GitHub Actions `docker/build-push-action` to v7 and `actions/download-artifact` to v8\n- **Electron Updates:** Upgraded desktop wrapper core to Electron `41.2.0` and `electron-builder` to `26.8.1`, incorporating essential V8/Chromium security patches\n- **NPM Package Groups:** Updated `production` and `development` NPM groups to securely handle minor audit warnings and keep toolchains modern\n- **CI/CD Reliability:** Fixed persistent `Snyk` token-absence failures on automated pull requests by appropriately bypassing on dependabot actions\n\n## [3.6.2] — 2026-04-11\n\n### ✨ New Features\n\n- **33 New API Key Providers:** Massive provider expansion adding DeepInfra, Vercel AI Gateway, Lambda AI, SambaNova, nScale, OVHcloud AI, Baseten, PublicAI, Moonshot AI, Meta Llama API, v0 (Vercel), Morph, Featherless AI, FriendliAI, LlamaGate, Galadriel, Weights & Biases Inference, Volcengine, AI21 Labs, Venice.ai, Codestral, Upstage, Maritalk, Xiaomi MiMo, Inference.net, NanoGPT, Predibase, Bytez, Heroku AI, Databricks, Snowflake Cortex, and GigaChat (Sber). OmniRoute now supports **100+ providers** (4 Free + 8 OAuth + 91 API Key + Custom compatible)\n- **Global Email Privacy Toggle:** Added a persistent eye-icon toggle button across all dashboard pages (Providers, Usage Limits, Playground) that reveals or hides masked email addresses. Toggle state is stored in localStorage and synced globally via Zustand store\n- **Documentation Refresh:** Updated README, ARCHITECTURE, FEATURES, AGENTS.md, and API_REFERENCE for v3.6.2 with accurate provider counts (100+), new executor list, and system API documentation\n- **Uninstall Guide:** Created comprehensive `docs/UNINSTALL.md` covering clean uninstallation for all deployment methods (npm, Docker, Electron, source)\n\n### 🐛 Bug Fixes\n\n- **PDF Attachments:** Unlocked deep string object parsing (`geminiHelper`) ensuring Gemini translation successfully passes complex PDF payloads from OpenAI-compatible streams without dropping them silently (#993)\n- **SkillsMP Engine:** Corrected object extraction path mappings inside the API router to fix UI marketplace rendering under Docker/Standalone Node isolated deployments (#988)\n\n---\n\n## [3.6.1] — 2026-04-10\n\n### ✨ New Features\n\n- **OAuth Env Repair Action:** Added a \"Repair env\" button to the OAuth Providers dashboard that detects and restores missing OAuth client IDs from `.env.example` — with timestamped backup and append-only safety. Includes full 33-language i18n support and sanitized API responses (#1116, by @yart)\n\n### 🐛 Bug Fixes\n\n- **i18n: Missing Provider Keys:** Added missing `filterModels`, `modelsActive`, `showModel`, `hideModel` keys across all 32 locale files, fixing runtime `MISSING_MESSAGE` errors in the providers UI. Also cleaned up duplicate keys in `en.json` (#1111, by @rilham97)\n- **GPT-5.4 Routing:** Added missing `targetFormat: \"openai-responses\"` to `gpt-5.4` and `gpt-5.4-mini` models in both the Codex and GitHub Copilot providers, fixing `[400]: model not accessible via /chat/completions` errors (#1114, by @ask33r)\n\n---\n\n## [3.6.0] — 2026-04-10\n\n### ✨ New Features & Analytics\n\n- **Combo Smoke Test:** Raised the default token budget to 2048 to prevent truncation of thinking models during preflight checks, and fully randomized the arithmetic probe prompt to bypass deterministic caching from upstream relays (#1105)\n\n### 🐛 Bug Fixes & Compliance\n\n- **DB Bloat / Row Limits:** Added `CALL_LOGS_TABLE_MAX_ROWS` and `PROXY_LOGS_TABLE_MAX_ROWS` (default: 100,000) to the backend DB compliance cleaner to prevent runaway SQLite growth. Limits are enforced automatically on the TTL cycle (#1104, fixes #1101)\n- **HTML Error Handling:** The router now correctly identifies unexpected HTML responses (e.g. ``) sent by upstream providers (like Azure/Copilot) instead of throwing obscure `Unexpected token '<'` JSON parse errors, bubbling up a clean 502 Bad Gateway (#1104, fixes #1066)\n- **Android/Termux SQLite Native Support:** `better-sqlite3` is now correctly built from source with cross-compilation flags in ARM64 local Termux deployments without failing on missing prebuilt binaries (#1107)\n\n---\n\n## [3.5.9] — 2026-04-09\n\n### ✨ New Features\n\n- **Persistent Combo Ordering:** Drag combo cards by handle to reorder them in the dashboard; order is persisted to SQLite via a new `sort_order` column and `POST /api/combos/reorder` endpoint. Includes DB migration `020_combo_sort_order.sql` and JSON import preservation (#1095)\n- **Sidebar Group Reorder:** Moved \"Logs\" before \"Health\" in the System section and \"Limits & Quotas\" after \"Cache\" in the Primary section for a more logical navigation flow (#1095)\n\n### 🐛 Bug Fixes\n\n- **Stream Failure Surfacing:** Upstream `response.failed` events (e.g. Codex rate-limit errors) are now properly surfaced as non-200 errors instead of being silently swallowed as empty 200 OK streams. Rate-limit failures return HTTP 429 (#1098, closes #1093)\n- **Upstream Model Preservation:** The Responses-to-OpenAI stream translator now preserves the actual upstream model (e.g. `gpt-5.4`) instead of hardcoding a `gpt-4` fallback (#1098, closes #1094)\n- **Docker EXDEV Fix:** `build-next-isolated.mjs` now falls back from `fs.rename()` to `cp/rm` when Docker buildx raises `EXDEV` (cross-device link), unblocking the Docker image publish workflow (#1097)\n- **macOS CLI Path Resolution:** `cliRuntime.ts` resolves symlink parents with `fs.realpath()` to handle macOS `/var` → `/private/var` chains, preventing false `symlink_escape` rejections (#1097)\n- **Request Log Token Layout:** Split token badges into separate Input (Total In, Cache Read, Cache Write) and Output (Total Out, Reasoning) groups for clearer readability; renamed \"Time\" label to \"Completed Time\" (#1096)\n\n---\n\n## [3.5.8] — 2026-04-09\n\n### ✨ New Features & Analytics\n\n- **Analytics Layout Redesign:** Replaced flat metrics with a responsive `CompactStatGrid`, grouping data visually across sections (#1089)\n\n### 🐛 Bug Fixes\n\n- **Build Core:** Force Turbopack cleanup via Prepbulish script to prevent Next.js 16 app/ routing conflicts on runtime.\n- **Provider Quarantine:** Introduces model/provider circuit-breakers with adaptive TTL exponential backoff for recurring upstream errors (#1090)\n- **Oauth Keep-Alive:** Safely protects authenticated active accounts against spontaneous dropping from router due to transient token refresh failures (#1085)\n\n### 🔒 Security & Maintenance\n\n- **Dependabot:** bumped axios from 1.14.0 to 1.15.0 addressing SSRF flags (#1088)\n\n---\n\n## [3.5.7] — 2026-04-09\n\n### 🐛 Bug Fixes & Security\n\n- **Turbopack Standalone Chunks:** Fixed a critical bug in `scripts/prepublish.mjs` where Turbopack chunks missing from the `.next/standalone` trace resulted in a `500 ChunkLoadError` (e.g., `_not-found` page crash) during production deployments via NPM or Docker. Standalone chunks are now explicitly copied and correctly stripped of Turbopack hashes.\n\n---\n\n## [3.5.6] — 2026-04-09\n\n### ✨ New Features\n\n- **Email Privacy Masking:** OAuth account emails are now masked in the provider dashboard (e.g. `di*****@g****.com`) to prevent accidental exposure when sharing screenshots. Full address visible on hover via `title` attribute (#1025).\n- **OpenRouter & GitHub in Embedding/Image Registries:** OpenRouter (3 embedding models, 4 image models) and GitHub Models (2 embedding models via Azure inference) are now first-class entries in the provider registries, enabling their use for `/v1/embeddings` and `/v1/images/generations` (#960).\n- **Model Visibility Toggle & Search Filter:** The provider page model list now includes a real-time search/filter bar and a per-model visibility toggle (👁 icon). Hidden models are grayed out and excluded from the `/v1/models` catalog. An active-count badge (`N/M active`) shows at a glance how many models are enabled (#750).\n- **Chinese Localization (zh-CN):** Added missing translations for Context Relay, Memory, LKGP, and Models.dev sync features, while standardizing terminology across the application (#1079).\n- **Environment Auto-Sync:** Added `sync-env.mjs` to auto-generate and append `.env` from `.env.example` during installation, automatically generating cryptographic secrets on first run.\n- **Source Mode Dashboard Update:** Fixed real-time Source (git-checkout) updating in the dashboard, enabling secure, real-time update pipelines for non-NPM installations.\n\n### 🐛 Bug Fixes & Security\n\n- **Hardcoded Secret Cleanup:** Removed 12 hardcoded OAuth credential fallbacks from the source code, forcing secure reliance on environment variables and resolving static analysis security alerts.\n- **Next.js Security Patch:** Bumped `next` from 16.2.2 to 16.2.3 to resolve critical RSC deserialization RCE vulnerability (SNYK-JS-NEXT-15954202).\n- **Memory/Cache UI Crash:** Added null-safety guards (`?? 0`) to `.toLocaleString()` calls in Memory and Cache dashboard pages, preventing `TypeError` crashes when database tables are empty or contain null numeric values (#1083).\n- **WebSearch tool_choice Translation:** Fixed OpenAI-to-Claude translator dropping `tool_choice` objects with `type: \"function\"` as-is, which Claude rejects. Now properly maps all OpenAI `tool_choice` variants (`function`, `required`, `none`) to Claude-compatible format (`tool`, `any`, `auto`), fixing \"Did 0 searches\" in Claude Code WebSearch (#1072).\n- **Provider Validation baseUrl Override:** Added `baseUrl` passthrough from frontend validation requests to the backend validation endpoint. Chinese-site users of Alibaba Coding Plan (bailian-coding-plan) can now validate API keys against their custom Base URL instead of always hitting the international endpoint (#1078).\n- **Minimax Auth Header:** Switched Minimax provider from `x-api-key` to `Authorization: Bearer` header format, matching the current API spec (#1076).\n- **Native Fetch Fallback:** Added graceful fallback to native `fetch` when the `undici` dispatcher fails, improving resilience in environments where undici is unavailable (#1054).\n- **EPIPE Flood Fix:** Added circuit-breaker logic to prevent EPIPE errors from creating a feedback loop that fills logs at GB/s (#1006).\n- **Qoder PAT Validation:** Improved Qoder Personal Access Token validation with actionable error messages that guide users to the correct token format (#966).\n- **CI/CD Pipeline:** Fixed `check:docs-sync` failure by syncing OpenAPI version to 3.5.6 and finalizing CHANGELOG release heading. Commented out `DATA_DIR` in `.env.example` to prevent E2E test failures in CI runners lacking root permissions.\n\n### 🌍 i18n\n\n- **Auto Language Generation (CI):** Added CI pipeline to auto-generate missing language files and strings via `feat(CI,i18n)` workflow, covering 30+ locales (#1071).\n\n---\n\n## [3.5.5] — 2026-04-08\n\n### ✨ New Features\n\n- **Node.js 24 Compatibility Warning:** Added a proactive version incompatibility warning on the login page to guide users to the stable Node.js 22 LTS, preventing native sqlite binding crashes.\n- **Context Relay Combo Strategy:** Added the new `context-relay` combo strategy with priority-style routing, structured handoff summary generation once quota usage reaches the warning threshold, and handoff injection after the next real account switch.\n- **Global Context Relay Defaults:** Added global Settings defaults plus combo-level configuration for `handoffThreshold`, `handoffModel`, and `handoffProviders`, so new or unconfigured combos can inherit the feature consistently.\n\n### 🐛 Bug Fixes\n\n- **Proxy Connection Healthchecks:** Applied proxy resolution per connection in the sweeping loop (`tokenHealthCheck.ts`) and global provider validation sweeps, resolving Node 22 bypass and improving proxy stability (#1051, #1056, #1061).\n- **Security Vulnerability Remediation:** Resolved multiple CodeQL scanning alerts including SSRF in model sync, insecure randomness in web crypto (`generateSessionId`), and incomplete URL sanitization.\n- **Context Relay Typing & Synchronization:** Reverted out-of-scope test breakages and resolved `handoffProvider` and response `input` extraction payload typing.\n- **Legacy OpenAI-Compatible Responses Routing:** Fixed legacy/imported OpenAI-compatible providers (for example `openai-compatible-sp-openai`) incorrectly routing Chat Completions traffic to `/chat/completions` when the real provider node was configured as `apiType: \"responses\"`. OmniRoute now treats `providerSpecificData.apiType` as authoritative across routing, executors, and translator tools, avoiding false empty-content failures during combo/provider smoke tests (#1069).\n- **Gemini PDF Attachment Integration:** Fixed payload generation and format for parsing `inline_data` and generic base64 sources for deep Gemini PDF routing (#993, #1021).\n- **Vercel AI SDK Fallbacks:** Mapped `max_output_tokens` to `max_tokens` for strict OpenAI-compatible providers, resolving errors from standard AI agents and frameworks (#994).\n- **External Auth & UI Reliability:** Handled null `state` failures in Cline OAuth exchange (#1016), added 3rd-party 400 error patterns to combo fallback (#1024), and resolved desktop sidebar layout and popover overflows (#1039, #1001).\n- **Context Relay In-Flight Deduplication:** Prevented duplicate handoff generation for the same session/combo while an earlier summary request is still in flight.\n- **Context Relay Provider Gating:** Aligned runtime behavior with configuration so explicit `handoffProviders` exclusions, including an empty array, now disable handoff generation as expected.\n\n### 🛠️ Maintenance & Dependabot\n\n- **Updated Sub-dependencies:** Bumped `hono` to `4.12.12` and `@hono/node-server` to `1.19.13` to patch critical security gaps (#1063, #1064, #1067, #1068).\n\n### Dokumentacja\n\n- **Documentation Synchronization:** Updated system documentation (README, Architecture, Features, Tools, Troubleshooting) and synced `i18n` configurations to match the v3.5.5 context relay patterns and proxy troubleshooting steps.\n- **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance.\n\n---\n\n## [3.5.4] — 2026-04-07\n\n### ✨ New Features\n\n- **Detailed Token Tracking:** Added granular token breakdown columns (cache read, cache write, reasoning) to call logs with proper null vs zero distinction. Includes DB migration 018 and 5-label UI display per provider capability (#1017 — thanks @rdself).\n- **Legacy JSON Config Import/Export:** Restored JSON-based settings export and import for migration from legacy 9router configurations. Security-hardened with Zero-Trust redaction of passwords and `requireLogin` fields, and automatic pre-import database backups (#1012 — thanks @luandiasrj).\n- **Non-Stream Aliases:** Added API support for explicit non-streaming aliases (`non_stream`, `disable_stream`, `disable_streaming`, `streaming=false`), normalized at the boundary before provider translation (#1036 — thanks @wlfonseca).\n- **Russian Dashboard Localization:** Comprehensive Russian translation for the dashboard UI, including fixes for 2 Ukrainian locale keys (#1003 — thanks @mercs2910).\n\n### 🐛 Bug Fixes\n\n- **Anthropic Streaming Input Undercount:** Fixed a critical bug where Anthropic streaming `prompt_tokens` only reported non-cached tokens (e.g., `in=3` when actual total was 113,616). Cache tokens are now summed into prompt_tokens during streaming (#1017).\n- **Built-in Responses API Tool Types:** Preserved built-in Responses API tools (`web_search`, `file_search`, `computer`, `code_interpreter`, `image_generation`) from being silently stripped by the empty-name tool filter — these tools carry no `.name` field (#1014 — thanks @rdself).\n- **Cursor/Codex Responses Compatibility:** Fixed empty output in Cursor when using Codex models by hoisting system input items to `instructions`, sanitizing invalid tool names, and detecting Responses-format payloads on chat/completions endpoint (#1002 — thanks @mercs2910).\n- **OAuth Token Expiry Display:** Fixed OAuth connections showing \"expired\" badge even with valid tokens by reading `tokenExpiresAt` (updated on refresh) instead of `expiresAt` (original grant timestamp) (#1032 — thanks @tombii).\n- **Codex Fast-Tier Copy:** Corrected dashboard settings copy from `service_tier=fast` to `service_tier=priority`, matching the actual Codex wire format (#1045 — thanks @kfiramar).\n- **macOS Desktop App Startup:** Stabilized packaged macOS app launch by excluding desktop artifacts from the standalone bundle and improving launch path detection (#1004 — thanks @mercs2910).\n- **macOS Sidebar Layout:** Fixed macOS traffic light overlap, sidebar spacing, and button overflow in the Electron desktop app (#1001 — thanks @mercs2910).\n\n### ⚡ Performance\n\n- **Analytics Page Load:** Dramatically reduced analytics page load times (30s→1-2s for 50K entries) via date-filtered DB queries, parallel `Promise.all()` cost calculations, and merged 6 COUNT queries into a single CASE WHEN aggregate (#1038 — thanks @oyi77).\n\n### 🔒 Security & Dependencies\n\n- **Node Base Image:** Upgraded Docker base from `22-bookworm-slim` to `22.22.2-trixie-slim` (#1011 — Snyk).\n- **Production Dependencies:** Bumped 5 production dependencies (#1044 — Dependabot).\n- **Vite:** Bumped from 8.0.3 to 8.0.5 (#1031 — Dependabot).\n- **Development Dependencies:** Bumped 4 development dependencies (#1030 — Dependabot).\n\n### 🧪 Tests\n\n- **Token Accounting Tests:** Added 18 new unit tests covering detailed token breakdown, null vs zero semantics, per-provider token extraction, and Anthropic streaming input fix (#1017).\n- **Built-in Tool Tests:** Added 3 new test cases for built-in Responses API tool type preservation (#1014).\n- **ChatCore Sanitization:** Updated sanitization tests to accommodate Responses format detection (PR #1002) and built-in tool preservation (PR #1014).\n\n### 🛠️ Maintenance\n\n- **PR Workflow:** Updated `/review-prs` workflow to merge PRs into the release branch (`release/vX.Y.Z`) instead of directly into `main`, ensuring proper pre-release staging.\n\n### Coverage\n\n- **2537 tests, 2532 passing** — Statement coverage: 91.95%, Branch coverage: 78.79%, Function coverage: 93.19%\n\n## [3.5.3] - 2026-04-07\n\n### Bezpieczeństwo\n\n- **Vulnerabilities:** Fully remediated 12 High-Severity CodeQL vulnerabilities by migrating from Math.random to `crypto.randomUUID()`, wrapping SSE injection points with aggressive backslash escaping, sanitizing trailing HTTP fragments, and enforcing rigid SSRF HTTP verification schemes across internal routes.\n- **Dependencies:** Upgraded Next.js to `^16.2.2` and Vite to `>=8.0.5` resolving critical DoS, arbitrary file reads and CSRF vectors in the build/server environments.\n\n### Fixed\n\n- **E2E Stability:** Eliminated extreme CI unreliability and transient test timeouts (Playwright) by propagating internal standalone `_next/static` assets properly and refactoring deep UI interactions inside defensive `expect().toPass()` loops.\n- **Middleware:** Resolved infinite redirect loop on dashboard for fresh instances when requireLogin is disabled.\n- **Core Fallbacks:** Preserved primary failure contexts and enhanced Edge-case error handling pipelines across chat and fallback loops.\n- **Proxy/Hooks:** Optimized local git hooks, normalized token coverage endpoints into `/coverage`, and guarded GLM region lookups.\n\n### 🛠️ Maintenance\n\n- **CI/CD Stabilization:** Prevented random GitHub Runner freezes by decoupling sharded processes, adjusting test concurrencies, unref-ing active connections on server teardown, and strictly capping job timeout durations.\n\n### Dokumentacja\n\n- **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned).\n\n### Coverage\n\n- **Testing:** Consolidated the workspace test coverage framework hitting 92.1% statement line coverage, with new rigid unit-tests matching API key policies and tool scopes.\n\n---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n- **Qoder API Native Integration:** Completely refactored the Qoder Executor to bypass the legacy COSY AES/RSA encryption algorithm, routing directly into the native DashScope OpenAi-compatible URL. Eliminates complex dependencies on Node `crypto` modules while improving stream fidelity.\n- **Resilience Engine Overhaul:** Integrated context overflow graceful fallbacks, proactive OAuth token detection, and empty-content emission prevention (#990).\n- **Context-Optimized Routing Strategy:** Added new intelligent routing capability to natively maximize context windows in automated combo deployments (#990).\n\n### 🐛 Bug Fixes\n\n- **Responses API Stream Corruption:** Fixed deep-cloning corruption where Anthropic/OpenAI translation boundaries stripped `response.` specific SSE prefixes from streaming boundaries (#992).\n- **Claude Cache Passthrough Alignment:** Aligned CC-Compatible cache markers consistently with upstream Client Pass-Through mode preserving prompt caching.\n- **Turbopack Memory Leak:** Pinned Next.js to strict `16.0.10` preventing memory leaks and build staleness from recent upstream Turbopack hashed module regressions (#987).\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **Models.dev Integration:** Integrated models.dev as the authoritative runtime source for model pricing, capabilities, and specifications, overriding hardcoded prices. Includes a settings UI to manage sync intervals, translation strings for all 30 languages, and robust test coverage.\n- **Provider Native Capabilities:** Added support for declaring and checking native API features (e.g. `systemInstructions_supported`) preventing failures by sanitizing invalid roles. Currently configured for Gemini Base and Antigravity OAuth providers.\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### Bezpieczeństwo\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### Funkcje\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### Bezpieczeństwo\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### Bezpieczeństwo\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### Bezpieczeństwo\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### Dokumentacja\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### Dokumentacja\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### Funkcje\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### Funkcje\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### Funkcje\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### Bezpieczeństwo\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### Funkcje\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### Funkcje\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### Funkcje\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### Funkcje\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### Funkcje\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### Funkcje\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### Funkcje\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### Funkcje\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### Bezpieczeństwo\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\bany\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### Funkcje\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### Funkcje\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### Funkcje\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### Funkcje\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### Funkcje\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### Funkcje\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### Dokumentacja\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### Funkcje\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}}, "docs/i18n/ar/CHANGELOG.md": {"63029ae7eb5118baa91257939233db8fb0aed60b": {"t": 1786067815.3377256, "n": 229365, "h": "683fd9d01f7f17e7", "c": "# Changelog (العربية)\n\n🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [hi](../hi/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md) · 🇹🇷 [tr](../tr/CHANGELOG.md)\n\n---\n\n## [Unreleased]\n\n---\n\n## [3.6.8] — 2026-04-17\n\n### ✨ New Features\n\n- **feat(providers):** Support `xhigh` reasoning tier exclusively on Claude models that expose it (#1356)\n- **feat(providers):** Add CC Compatible connection-level 1M context toggle (#1357)\n- **feat(core):** Add full support for Node.js 24 LTS (Krypton) environments with continuous integration coverage (#1340)\n- **feat(dashboard):** Display Antigravity credit balance in dashboard Limits & Quotas (#1338)\n- **feat(i18n):** Add internationalization support for combo features and dashboard components; sync translations across 31 keys (#1318)\n- **feat(providers):** Add Claude Opus 4.7 to Claude Code OAuth models natively with extended context and caching (#1347)\n- **feat(core):** Add stopSequences support and expand tool definitions to include Google Search capabilities\n- **feat(auth):** Enforce dashboard session authentication on all management API routes, preventing unauthenticated access to configuration endpoints\n- **feat(runtime):** Add hot-reloadable guardrails and model diagnostics for real-time rule evaluation without restarts\n- **feat(core):** Add payload rules, tag-based routing, and scheduled budget systems for fine-grained request governance\n- **feat(providers):** Expose Antigravity preview model aliases and Gemini CLI onboarding flow for first-time setup\n- **feat(antigravity):** Add client model aliases and thoughtSignature bypass modes for Antigravity OAuth connections\n- **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations\n- **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages\n\n### الأمان\n\n- **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns\n- **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353)\n- **fix(providers):** Resolve Codex token refresh race condition via mutex `getAccessToken` preventing `refresh_token_reused` Auth0 revocations\n\n### 🔧 Maintenance & Architecture\n\n- **refactor(core):** Split CLI runner and decouple migration engine for extensibility (#1358)\n- **refactor(audit):** Rewire audit dashboard from dead in-memory `configAudit` store to live SQLite `audit_log` table — 331+ hidden compliance entries now visible in `/dashboard/audit`\n- **build(deps):** Bump `softprops/action-gh-release` from v2 to v3\n- **ci:** Bump GitHub Actions CI node-version to Node.js 24 natively\n- **fix(types):** Resolve TypeScript compilation errors in `claudeCodeCompatible.ts` (type predicates, `cache_control` index access) and `proxyFetch.ts` (`signal` nullability)\n\n### 🐛 Bug Fixes\n\n- **fix(context):** Scale reserved context tokens dynamically using a 15% sliding window for smaller models\n- **test(core):** Replace unit test with integration test for proactive context compression to align with isolated runner rules (#1378)\n- **fix(services):** Pass origin provider to refreshWithRetry to avoid tripping the generic \"unknown\" circuit breaker (fixes Codex accounts erroneously disabling)\n- **fix(db):** Prevent native module ABI load crashes from assuming database corruption and skipping databases\n- **fix(db):** Increase mass-migration threshold from 5 to 50 pending migrations to protect legacy users upgrading node\n- **fix(db):** Prevent migration runner safety aborts from triggering on fresh `DATA_DIR` installations by detecting new databases (#1328)\n- **fix(mcp):** Checkpoint and close MCP audit SQLite database safely on process signals and shutdown (#1348)\n- **fix(mcp):** Fully decouple MCP audit SQLite connection caching via globalThis to fix unhandled teardown in standalone Next.js chunks (#1349)\n- **fix(cli):** Avoid creating app router directory during postinstall initialization on non-built source trees (#1351)\n- **fix(codex):** Correctly translate `system` role to `developer` in input array to unlock GPT-5 automatic prompt caching (#1346)\n- **fix(core):** Pass client headers to executor in chatCore (#1335)\n- **fix(providers):** Separate test batch calls and ignore unknown connections\n- **fix(providers):** Add grok-web SSO cookie validation handler (#1334)\n- **fix(db):** Preserve key_value settings (dashboard passwords, saved aliases) across DB heuristic recreation cycles (#1333)\n- **fix(routing):** Allow combo fallback to cascade context overflow 400 errors instead of immediate aborts (#1331)\n- **fix(core):** Resolve thinking leaks, consecutive roles, and missing thoughtSignatures for Antigravity translator (#1316)\n- **fix(translator):** Only apply thoughtSignature to the first `functionCall` part in Gemini parallel tool calls, preventing duplicate signatures\n- **fix(providers):** Default to batch testing execution blocks for web, search, and audio modalities to prevent connection timeouts\n- **fix(cli):** Resolve Node 22 TS entrypoint incompatibility by using esbuild compilation (#1315)\n- **fix(chat):** Preserve max_output_tokens for Responses API targets in chatCore sanitization (#1313)\n- **fix(api):** API Manager usage stats showing 0 for all registered keys (#1310)\n- **fix(api):** Support image-only models in catalog and allow authless search providers to bypass validation requirements\n- **fix(routes):** Require prompts for media generation requests (`/images`, `/videos`, `/music`), returning 400 on missing payloads\n- **fix(dashboard):** Auto-scroll ActivityHeatmap to show current date (#1309)\n- **fix(dashboard):** Restore horizontal layout with `w-max` wrapper in heatmap components\n- **fix(i18n):** Update `nodeIncompatibleHint` to recommend Node 24 LTS across all 31 languages\n- **fix(i18n):** Add Chinese i18n support to remaining dashboard components (`Loading.tsx`, `DataTable`, etc.)\n- **fix(requestLogger):** Add missing `cacheSource` and `tps` columns to i18n log detail views\n\n## [3.6.6] — 2026-04-15\n\n### ✨ New Features\n\n- **feat(storage):** Add database backup cleanup controls, UI management, and customizable retention period env vars (#1304)\n- **feat(providers):** Add Freepik Pikaso image generation provider with support for cookie/subscription-based auth modes (#1277)\n- **feat(providers): Add Perplexity Web (Session) Provider** — Routes through Perplexity's internal SSE API using a session cookie, giving native proxy access without separate API costs to GPT-5.4, Claude Opus, Gemini 3.1 Pro, and Nemotron via preferences mapping (#1289)\n- **feat(api): Sync Tokens & V1 WebSocket Bridge** — Dedicated sync token storage, issuance, revocation, and bundle download routes backed by stable config bundle versioning with ETag support. Exposes `/v1/ws` WebSocket upgrade route and a custom Next.js server bridge (`scripts/v1-ws-bridge.mjs`) so OpenAI-compatible WebSocket traffic can be proxied through the gateway. Compliance auditing expanded with structured metadata, pagination, request context, auth/provider credential events, and SSRF-blocked validation logging. New migrations: `024_create_sync_tokens.sql`. New modules: `syncTokens.ts`, `src/lib/sync/bundle.ts`, `src/lib/sync/tokens.ts`, `src/lib/ws/handshake.ts`, `src/lib/apiBridgeServer.ts`, `src/lib/compliance/providerAudit.ts`.\n- **feat(models): GLM Thinking Preset & Hybrid Token Counting** — GLM Thinking (`glmt`) registered as a first-class provider preset with shared GLM model metadata, pricing, per-connection usage sync, dashboard support, and `maxTokens: 65536 / thinkingBudgetTokens: 24576` request defaults with 900s extended timeout. Provider-side `/messages/count_tokens` endpoint used when a Claude-compatible upstream supports it; gracefully falls back to estimation on missing models, missing credentials, or upstream failures. Startup seeding of default model aliases (`src/lib/modelAliasSeed.ts`) normalizes common cross-proxy model dialects so canonical slash-based model IDs are not misrouted. New file `open-sse/config/glmProvider.ts`.\n- **feat(core): Hardened Outbound Provider Calls & Cooldown Retries** — Guarded outbound fetch helpers (`src/shared/network/safeOutboundFetch.ts`, `src/shared/network/outboundUrlGuard.ts`) blocking private/local URLs with configurable retry, timeout normalisation, and route-level status propagation for provider validation and model discovery. Cooldown-aware chat retries (`src/sse/services/cooldownAwareRetry.ts`) with configurable `requestRetry` and `maxRetryIntervalSec` settings and model-scoped cooldown responses. Improved rate-limit learning from headers and error bodies so short upstream lockouts can recover automatically. Runtime environment validation (`src/lib/env/runtimeEnv.ts`) checks env at startup. Pollinations now requires an API key. Antigravity and Codex header handling aligned via `open-sse/config/antigravityUpstream.ts` and `open-sse/config/codexClient.ts`. Gemini tool names restored in translated responses; synthetic Claude text block injected when upstream SSE completes empty.\n- **feat(logs):** Add TPS (Tokens Per Second) metric to log details modal metadata grid (#1182)\n- **feat(memory+skills):** Full-featured Memory & Skills systems with FTS5 SQLite search, dynamic UI pagination, backend observability, and extensive test coverage (#1228)\n- **feat(bailian-quota):** Add Alibaba Coding Plan quota monitoring, multi-window quota extraction, and UI credential validation (#1235)\n- **feat(storage): Call Log Storage Refactor** — Extracted heavy request/response JSON payloads from the core SQLite database (`storage.sqlite`) into filesystem artifacts stored within `DATA_DIR/call_logs`. This massively reduces WAL bloat and eliminates `SQLITE_FULL` crashes on high-traffic nodes (#1307).\n- **feat(providers): Add Grok Web (Subscription) Provider** — Routes through the xAI web interface for subscription users via cookie session mapping (#1295).\n- **feat(api): Advanced Media Support** — Extends OpenAI generic proxy layer to natively support `image`, `embeddings`, `audio-transcriptions`, and `audio-speech` workflows (#1297).\n- **feat(cli-tools): Qwen Code CLI Integration** — Full integration for Qwen Code local execution mapping, model resolution, and dynamic API key fetching (#1266, #1263).\n- **feat(oauth):** Supports `cursor-agent` CLI as a native Cursor credential source alongside the standard configuration (#1258).\n- **feat(models):** Custom and imported models now merge correctly into filter lists for all available global providers (#1191).\n\n### 🐛 Bug Fixes\n\n- **fix(providers):** match correct endpoint api.xiaomimimo.com for Xiaomi MiMo (#1303)\n- **fix(core):** strip provider alias routing prefix from payload for custom endpoints to fix Azure OpenAI 400 errors (#1261)\n- **fix(core):** ProxyFetch Undici dispatcher automatically bypasses LAN/local addresses, preventing fetch failures on internal OpenRouter requests (#1254)\n- **fix(core):** Gemini thought stream signature detection upgraded to use native part.thought boolean, preventing reasoning text leaks (#1298)\n- **deps:** bump hono from 4.12.12 to 4.12.14 to resolve CVE SSR HTML injection vulnerability (#1306, #59)\n- **deps:** update dompurify to 3.4.0 in frontend overrides mitigating XSS HTML Injection (CVE-XYZ / Dependabot #60)\n- **test:** Disable SQLite automatic backups during continuous integration (CI) tests to resolve E2E timeout issues limiting runner scaling (#24481475058)\n- **feat(core): Proactive Context Compression** — `chatCore` now proactively compresses oversized message contexts before hitting upstream providers to dramatically reduce `context_length_exceeded` errors. Employs binary-search message pruning with structural integrity guarantees tracking explicit `tool_use` boundaries ensuring truncated tool inputs drop paired outputs appropriately (#1292, #1293)\n\n- **fix(cli):** Resolve codex routing config parsing by strictly quoting section keys array, enforcing responses wire_api with fallback, and standardizing select-model button positioning mirroring Claude UI\n- **fix(providers):** Correct Lobehub provider icons rendering by removing unsupported local references ensuring local SVG/PNG fallback mechanism invokes natively\n- **fix(db):** Implement Database migration tracking safety abort safeguards (pre-migration backups via `VACUUM INTO` and mass renumbering warnings) to protect existing database structures on startup upgrades (#1281)\n- **fix(dashboard):** Cleaned up target codex `config.toml` structure preventing recursive section rendering by enforcing quotes on section dot paths and mapping correct UI `OMNIROUTE_API_KEY` names.\n- **fix(mcp):** Add dedicated explicit timeout constraint overrides for search handlers (#1280)\n- **fix(crypto):** Add validation guard to encryption layer to surface clear UI errors when cryptographic environment variables are missing, replacing raw Node.js TypeErrors. Legacy env vars `OMNIROUTE_CRYPT_KEY` and `OMNIROUTE_API_KEY_BASE64` now also accepted as fallbacks (#1165)\n- **fix(providers):** Update Pollinations provider definition to require API keys and specify their new limited pollen/hour free tier (#1177)\n- **Streaming `\\n\\n` Artifact Fix (#1211):** Changed `` tag-stripping regex from `?` to `*` quantifier across `combo.ts`, `comboAgentMiddleware.ts`, and `contextHandoff.ts` to greedily strip all accumulated JSON-escaped newline sequences surrounding the tag. This prevents literal `\\n\\n` prefix artifacts from appearing in consumer streaming responses\n- **E2E Combo Test Locator:** Fixed Playwright strict-mode violation in `combo-unification.spec.ts` by replacing ambiguous `getByRole` locator with a compound filter locator for the \"All\" strategy tab\n- **fix(cc-compatible):** Trim beta flags and preserve cache passthrough for third-party HTTP proxy compatibility (#1230)\n- **fix(providers):** Update Xiaomi MiMo endpoints to the live token-plan, migrating away from dead API URLs (#1238)\n- **fix:** Forward client `x-initiator` header to GitHub Copilot upstream to accurately distinguish agent vs user turns (#1227)\n- **fix:** Resolve backlog bugs including streaming edge cases, unhandled rejections, and quota parse failures (#1206, #1220, #1231, #1175, #1187, #1218, #1202)\n- **fix(tests):** Resolve memory migration and skills route pagination bugs arising from PR overlaps\n- **fix(i18n):** Add missing Chinese i18n support to dashboard components (`DataTable`, `EmptyState`, etc), update `en.json/zh-CN.json` routing keys, and natively resolve JSX defaults via `next-intl` (#1274)\n\n### 🔧 Internal Improvements\n\n- **Compliance Audit Expansion:** `src/lib/compliance/index.ts` expanded with structured metadata, pagination support, request context enrichment, and new `providerAudit.ts` module logging auth and provider credential events, SSRF-blocked validation attempts, and provider CRUD operations\n- **Config Sync Bundle:** `src/lib/sync/bundle.ts` exports `buildConfigBundle()` generating a versioned JSON snapshot of settings, provider connections, nodes, model aliases, combos, and API keys (passwords redacted) with ETag support for bandwidth-efficient polling\n- **Codex Client Constants:** Centralized `CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT_PLATFORM`, and pattern-validated env overrides (`CODEX_CLIENT_VERSION`, `CODEX_USER_AGENT`) in `open-sse/config/codexClient.ts`\n- **Antigravity Upstream Constants:** `open-sse/config/antigravityUpstream.ts` consolidates all Antigravity base URLs and model/fetchAvailableModels discovery path builders\n- **Model Alias Seed:** `src/lib/modelAliasSeed.ts` seeds 30+ cross-proxy model dialect aliases (e.g. `openai/gpt-5` → `gpt-5`, `anthropic/claude-opus-4-6` → `cc/claude-opus-4-6`) at startup via idempotent `upsert`\n- **Test Coverage:** 15+ new unit test suites covering sync routes, WebSocket bridge, compliance index, GLM provider config, cooldown-aware retry, safe outbound fetch, stream utilities, Codex executor, provider validation branches, model cross-proxy compatibility, and model alias seeding\n- **TypeScript Migration:** Finalized migration of remaining JS tests (`proxy-load` and `testFromFile`) to TypeScript ES modules, ensuring a fully synchronized TS stack.\n- **Reliability & Resilience:** Added exponential backoff to `models.dev` auto-sync to combat transient network failures, raised interval floor to 1 hour, and added LKGP debug logging for enhanced observability during routing. (#1286)\n\n---\n\n## [3.6.5] — 2026-04-13\n\n### ✨ New Features\n\n- **Antigravity AI Credits Fallback:** Automatically retries with `GOOGLE_ONE_AI` credit injection when free-tier quota is exhausted. Per-account credit balance (5-hour TTL) is cached from SSE `remainingCredits` and exposed as a numeric badge in the Provider Usage dashboard (#1190 — thanks @sFaxsy)\n- **Claude Code Native Parity:** Full header/body signing parity with the Claude Code 2.1.87 OAuth client — CCH xxHash64 body signing with singleton WASM initialization promise (fixing race conditions), dynamic per-request fingerprint, bidirectional TitleCase ↔ lowercase tool name remapping (14 tools), API constraint enforcement (`temperature=1` for thinking, max 4 `cache_control` blocks, auto-inject ephemeral on last user message), and optional ZWJ obfuscation. Wired into `BaseExecutor` for automatic CCH signing on all `anthropic-compatible-cc-*` providers and into `chatCore` for synchronous parity pipeline steps (#1188 — thanks @RaviTharuma)\n- **Per-Connection Codex Defaults:** Codex Fast Service Tier and Reasoning Effort settings are now per-connection instead of a single global toggle. Existing connections are migrated automatically on startup via an idempotent backfill migration (#1176 — thanks @rdself)\n- **Cursor Usage Dashboard:** New `getCursorUsage()` fetches quotas from Cursor's `/api/usage`, `/api/auth/me`, and `/api/subscription` endpoints. Displays standard requests, on-demand usage, and per-plan limits (Free/Pro/Business/Team). Client version bumped to `3.1.0` and `x-cursor-user-agent` header added for parity\n- **Database Health Check System:** Automated periodic SQLite integrity monitoring via `runDbHealthCheck()` — detects orphan quota/domain rows, broken combo references, stale snapshots, and invalid JSON state. Runs every 6 hours (configurable via `OMNIROUTE_DB_HEALTHCHECK_INTERVAL_MS`), with auto-repair and pre-repair backup. Exposed as **MCP tool #18** (`omniroute_db_health_check`) with Zod schemas and `autoRepair` option. Dashboard panel in Health page with status card, issue count, repaired count, and one-click repair button\n- **OpenAI Responses API Store Opt-In:** Per-connection `openaiStoreEnabled` flag controls whether the `store` field is preserved or forced to `false` on Codex Responses API requests. When enabled, `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields are round-tripped through the Chat Completions → Responses translation, enabling multi-turn context caching on supported providers\n- **Email Privacy Toggle (Combos Page):** Global email visibility toggle (`EmailPrivacyToggle`) added to the Combos page header with responsive layout, tooltip guidance, and per-connection label masking via `pickDisplayValue()`. All combo builder options, provider connection lists, and quota screens now respect the global privacy state from `emailPrivacyStore`\n- **skills.sh Integration:** Added `skills.sh` as an external skill provider. Users can now search, browse, and install agent skills directly from a new \"skills.sh\" tab in the Skills dashboard. Includes backend API resolvers, frontend implementation with search/install states, and a dedicated unit test suite (#1223 — thanks @RaviTharuma)\n- **Stabilization Settings:** Added persistence support for `lkgpEnabled` and `backgroundDegradation` settings, integrated into `instrumentation-node.ts` for improved lifecycle awareness (#1212)\n- **xxhash-wasm dependency:** Added `xxhash-wasm@^1.1.0` for CCH signing (xxHash64 with seed `0x6E52736AC806831E`)\n\n### 🐛 Bug Fixes\n\n- **Codex `stream: false` via Combo (ALL_ACCOUNTS_INACTIVE):** Fixed a critical bug where Codex combos returned `ALL_ACCOUNTS_INACTIVE` or empty content when the client sent `stream: false`. Root cause was triple: (1) `CodexExecutor.transformRequest()` mutated `body.stream` in-place to `true`, contaminating the combo's quality check which skipped validation thinking it was streaming; (2) the non-stream SSE parser used the wrong format (Chat Completions instead of Responses API) for Codex SSE output; (3) combo quality validation read the mutated `body.stream` instead of the client's original intent. Fixed by: cloning the body via `structuredClone()` in CodexExecutor, detecting Codex/Responses SSE format in the non-stream fallback path (with auto-translation back to Chat Completions), and capturing `clientRequestedStream` before the combo loop\n- **Gemini CLI Tool Schema Rejection:** Fixed 400 Bad Request errors from the Google API by strictly filtering non-standard vendor extensions (starting with `x-`) and `deprecated` fields from tool parameter schemas (#1206)\n- **SOCKS5 Proxy Interop (Node.js 22):** Resolved `invalid onRequestStart method` crashes caused by `undici` version mismatches between dispatchers and the built-in fetch. Hardened `proxyFetch.ts` to strictly use the library's fetch implementation for custom dispatchers (#1219)\n- **Search Cache Coalescing with TTL=0:** Fixed a bug where providers configured with `cacheTTLMs: 0` (caching explicitly disabled) still had concurrent requests coalesced and returned `{ cached: true }`. Now each call gets its own independent upstream fetch (#1178 — thanks @sjhddh)\n- **Antigravity Credit Cache Alignment (PR #1190):** Reconciled `accountId` derivation between `AntigravityExecutor.collectStreamToResponse` and `getAntigravityUsage` to use consistent cache keys (`email || sub || \"unknown\"`). Previously, SSE-parsed credit balances could be written under a different key than the one read by the usage dashboard, causing stale/missing credit badges\n- **Non-streaming reasoning_content Duplication:** Fixed clients rendering duplicated reasoning panels when both `reasoning_content` and visible `content` were present in non-streaming responses. `responseSanitizer` now strips `reasoning_content` from messages that already have visible text content, preserving it only for reasoning-only messages\n- **Streaming Regression Fix:** Hardened the `sanitize` TransformStream in the combo engine to strip both literal and JSON-escaped newline sequences, eliminating leading `\\n\\n` prefixes in assistant responses (#1211)\n- **Gemini Empty Choice Fix:** Ensured initial assistant deltas always include an empty `content: \"\"` string to satisfy strict OpenAI client requirements and prevent empty choice responses in tools (#1209)\n- **Gemini Tools Sanitizer Deduplication:** Extracted shared tool conversion logic into `buildGeminiTools()` helper (`geminiToolsSanitizer.ts`), eliminating duplicate implementations between `openai-to-gemini.ts` and `claude-to-gemini.ts`. The new helper correctly handles `web_search` / `web_search_preview` tool types by emitting `googleSearch` tools with priority over function declarations\n- **Qwen/Qoder Thinking+Tool_Choice Conflict:** Added `sanitizeQwenThinkingToolChoice()` to both `DefaultExecutor` (for Qwen provider) and `QoderExecutor` to prevent provider-side 400 errors when clients send `tool_choice` alongside thinking/reasoning parameters that are mutually exclusive upstream\n- **API Key Deletion Orphan Cleanup:** Deleting an API key now also removes associated `domain_budgets` and `domain_cost_history` rows, preventing orphan data accumulation\n- **CC-compatible test assertion:** Fixed pre-existing test that expected no `cache_control` on system blocks — the billing header system block now carries `cache_control: { type: \"ephemeral\" }` per PR #1188 design\n- **Codex Combo Smoke Test False Positives:** Fixed combo tests incorrectly reporting `ERROR` for valid Codex streaming responses when `response.output` is empty but text deltas were emitted. The summary now falls back to accumulated delta text (#1176 — thanks @rdself)\n- **Electron Builder Version Mismatch:** Fixed Electron desktop startup failures on Windows packaged builds caused by native modules (`better-sqlite3`) being under `app.asar.unpacked` while helpers were in `app/node_modules`. `resolveServerNodePath()` now merges both locations with deduplication and existence checks (#1172 — thanks @backryun)\n\n### 🔧 Internal Improvements\n\n- **SSE Parser: Responses API Non-Stream Conversion:** Added full `parseSSEToResponsesOutput()` implementation in `sseParser.ts` (255+ lines) — reconstructs complete Responses API objects from SSE event streams, handling `response.output_text.delta/done`, `response.reasoning_summary_text.delta/done`, `response.function_call_arguments.delta/done`, and terminal events. Used by the new chatCore non-stream fallback path for Codex\n- **Cursor Executor Version Sync:** Updated Cursor client User-Agent to `3.1.0` and centralized version constants (`CURSOR_CLIENT_VERSION`, `CURSOR_USER_AGENT`) for consistent fingerprinting across executor, usage fetcher, and OAuth flows\n- **Responses API Translator Parity:** `convertResponsesApiFormat()` now accepts credentials and passes them through to the translator, enabling store-aware field propagation. Round-trip preservation of `previous_response_id`, `prompt_cache_key`, `session_id`, and `conversation_id` fields\n- **Provider Schema Validation:** Added `openaiStoreEnabled` boolean validation to `providerSpecificData` Zod schema\n- **Combo Error Response Normalization:** Empty combo targets now return 404 (`comboModelNotFoundResponse`) instead of generic 503, improving client-side error differentiation\n- **Dependency Updates:** Bumps `typescript-eslint` to `8.58.2` (dev), `axios` to `1.15.0` (prod), and `next` to `16.2.2` (prod) (#1224, #1225)\n\n### ⚠️ Breaking Changes\n\n- **`DELETE /api/settings/codex-service-tier` removed:** This endpoint no longer exists. Codex Service Tier configuration has moved to per-connection `providerSpecificData.requestDefaults`. Existing connections are migrated automatically on first startup after upgrade. Any external scripts or integrations that call this endpoint should be updated — use `PUT /api/providers/:id` with `providerSpecificData.requestDefaults.serviceTier` instead (#1176).\n- **CCH signing on CC-compatible providers:** All requests to `anthropic-compatible-cc-*` providers now include an xxHash64 integrity token (`cch=...`) in the billing header. Providers that do not validate CCH will ignore it (no behavioral change), but any custom middleware inspecting the billing header should expect a 5-character hex token instead of the `00000` placeholder\n\n---\n\n## [3.6.4] — 2026-04-12\n\n### ✨ New Features\n\n- **Combo Builder v2 (Wizard UI):** Completely redesigned the combo creation/editing interface as a multi-stage wizard with stages: Basics → Steps → Strategy → Review. The builder fetches provider, model, and connection metadata via a new `GET /api/combos/builder/options` endpoint, enabling precise provider/model/account selection with duplicate detection and automatic next-connection suggestion. Heavy UI components (`ModelSelectModal`, `ProxyConfigModal`, `ModelRoutingSection`) are now lazily loaded via `next/dynamic` for faster initial page render\n- **Combo Step Architecture (Schema v2):** Introduced a structured step model (`ComboModelStep`, `ComboRefStep`) replacing the legacy flat string/object combo entries. Steps carry explicit `id`, `kind`, `providerId`, `connectionId`, `weight`, and `label` fields, enabling pinned-account routing, cross-combo references, and per-step metrics. All combo CRUD operations normalize entries through the new `src/lib/combos/steps.ts` module. Zod schemas updated with `comboModelStepInputSchema` and `comboRefStepInputSchema` unions\n- **Composite Tiers System:** Added tiered model routing via `config.compositeTiers` — each tier maps a named stage to a specific combo step with optional fallback chains. Includes comprehensive validation (`src/lib/combos/compositeTiers.ts`) ensuring step existence, preventing circular fallback, and validating default tier references. Zod schema enforcement blocks composite tiers on global defaults (concrete combos only)\n- **Model Capabilities Registry:** Created `src/lib/modelCapabilities.ts` providing `getResolvedModelCapabilities()` — a unified resolver that merges static specs, provider registry data, and live-synced capabilities into a single `ResolvedModelCapabilities` object covering tool calling, reasoning, vision, context window, thinking budget, modalities, and model lifecycle metadata\n- **Observability Module:** Extracted health and telemetry payload construction into `src/lib/monitoring/observability.ts` with `buildHealthPayload()`, `buildTelemetryPayload()`, and `buildSessionsSummary()` builders. The health endpoint now returns session activity, quota monitor status, and per-provider breakdowns alongside existing system metrics\n- **Session & Quota Monitor Dashboard:** Added live Session Activity and Quota Monitors panels to the Health dashboard, showing active session counts, sticky-bound sessions, per-API-key breakdowns, and top session details alongside quota monitor alerting/exhausted/error status with per-provider drill-down\n- **Combo Health Per-Target Analytics:** The combo-health API now resolves per-target metrics using the new `resolveNestedComboTargets()` function, providing step-level success rates, latency, and historical usage breakdowns per execution key — enabling per-account, per-connection health visibility\n- **Auto-Combo → Combos Unification:** Merged the separate `/dashboard/auto-combo` page into the main `/dashboard/combos` page. Auto/LKGP combos are now managed alongside all other combos with a new strategy filter tabs system (All / Intelligent / Deterministic). The old auto-combo route redirects to `/dashboard/combos?filter=intelligent`. Removed the `auto-combo` sidebar entry, consolidating navigation into the single `Combos` item\n- **Intelligent Routing Panel (`IntelligentComboPanel`):** New inline panel (371 lines) within the combos page that shows real-time provider scores, 6-factor scoring breakdown (quota, health, cost, latency, task fitness, stability), mode pack selector, incident mode status, and excluded providers for `auto`/`lkgp` combos — replacing the former standalone auto-combo dashboard\n- **Builder Intelligent Step (`BuilderIntelligentStep`):** New conditional wizard step (280 lines) that appears in the Builder v2 flow only when `strategy=auto` or `strategy=lkgp` is selected. Exposes candidate pool selection, mode pack presets, router sub-strategy selector, exploration rate slider, budget cap, and collapsible advanced scoring weights configuration\n- **Intelligent Routing Module (`intelligentRouting.ts`):** Extracted strategy categorization and filtering logic into a dedicated shared module (210 lines) with `getStrategyCategory()`, `isIntelligentStrategy()`, `filterCombosByStrategyCategory()`, `normalizeIntelligentRoutingFilter()`, and `normalizeIntelligentRoutingConfig()` utility functions\n- **LKGP Standalone Strategy:** Implemented `lkgp` (Last Known Good Provider) as a fully functional standalone combo strategy. Previously, `lkgp` as a combo strategy silently fell through to `priority` ordering — the LKGP lookup only ran inside the `auto` engine. Now `strategy: \"lkgp\"` correctly queries the LKGP state, moves the last successful provider to the top of the target list, and saves the LKGP state after each successful request. Falls back to priority ordering when no LKGP state exists\n- **Unified Routing Rules & Model Aliases:** Consolidated the routing rules and model alias management controls into the Settings page, reducing fragmentation across the dashboard\n\n### ⚡ Performance\n\n- **Middleware Lazy Loading:** Refactored `src/proxy.ts` to lazy-import `apiAuth`, `db/settings`, and `modelSyncScheduler` modules, reducing middleware cold-start overhead. Added inline `isPublicApiRoute()` to avoid loading the full auth module for public routes\n- **E2E Auth Bypass:** Added `NEXT_PUBLIC_OMNIROUTE_E2E_MODE` environment flag to bypass authentication gates for dashboard and management API routes during Playwright E2E test runs\n\n### 🐛 Bug Fixes\n\n- **P2C Credential Selection:** Implemented Power-of-Two-Choices (P2C) connection scoring in `src/sse/services/auth.ts` with quota headroom awareness, error/recency penalties, and forced/excluded connection support. The new `getProviderCredentialsWithQuotaPreflight()` function integrates quota preflight checks directly into credential selection, eliminating the separate Codex-only preflight path\n- **Fixed-Account Combo Steps:** Combo steps with explicit `connectionId` now correctly bypass provider-level model cooldowns and circuit breakers, preventing a single account failure from blocking pinned-connection routing for the same model\n- **Combo Metrics Per-Target Tracking:** Extended `comboMetrics.ts` to track `byTarget` metrics keyed by execution path, recording per-step `provider`, `providerId`, `connectionId`, and `label` alongside existing per-model aggregates\n- **Call Logs Schema Expansion:** Added `requested_model`, `request_type`, `tokens_cache_read`, `tokens_cache_creation`, `tokens_reasoning`, `combo_step_id`, and `combo_execution_key` columns to `call_logs` with auto-migration. Added composite index `idx_cl_combo_target` for efficient per-target historical queries\n- **Quota Monitor Enrichment:** Expanded `quotaMonitor.ts` with full lifecycle state tracking (`status`, `startedAt`, `lastPolledAt`, `consecutiveFailures`, `totalPolls`, `totalAlerts`), ISO-formatted snapshots via `getQuotaMonitorSnapshots()`, and sorted summary via `getQuotaMonitorSummary()`\n- **Codex Quota Fetcher Hardening:** Improved `codexQuotaFetcher.ts` with safer connection registration and quota fetch error handling\n- **LKGP Save Refactored to Async/Await:** Replaced fire-and-forget `.then()` chain for LKGP persistence after successful combo routing with proper `async/await` + `try/catch`, preventing unhandled promise rejections and ensuring LKGP state is reliably saved before the response is returned\n- **Duplicate `auto` in Combo Strategy Schema:** Removed duplicate `\"auto\"` entry from `comboStrategySchema` (was listed on both line 104 and 108). Harmless to Zod runtime but cleaned up to avoid confusion. Schema now has exactly 13 unique strategy values\n- **Legacy Combo Refs Normalization:** Fixed combo step normalization to preserve legacy string combo references during CRUD operations, preventing data loss when editing combos created before the v2 step architecture\n\n### الأمان\n\n- **Auth Bypass on Backup Routes (Critical):** Added `isAuthenticated` guards to `/api/db-backups/exportAll` (full database export) and `/api/db-backups` (list, create, and restore backups) — both were previously accessible without authentication\n- **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency\n- **API Key Secret Hardening:** Removed the hardcoded `\"omniroute-default-insecure-api-key-secret\"` fallback from `apiKey.ts` — the function now fails fast if `API_KEY_SECRET` is unset, relying on the startup validator to auto-generate it\n- **NPM Tarball Leak Fix:** Added `app/.env*` to `.npmignore` to prevent the working `.env` file from being shipped inside the npm tarball distribution\n- **Electron Builder CVE Fix:** Bumped `electron-builder` to 26.8.1 to resolve `tar` CVEs in the desktop build pipeline\n\n### 🔧 Maintenance & Infrastructure\n\n- **DB Migration 021:** Added `combo_call_log_targets` migration for `combo_step_id` and `combo_execution_key` columns in call_logs\n- **Combo CRUD Normalization:** `db/combos.ts` now normalizes all stored combo entries through the step normalization pipeline on read, ensuring consistent step IDs and kind annotations regardless of when the combo was created\n- **Playwright Config:** Updated Playwright configuration and `run-next-playwright.mjs` script for improved E2E test orchestration\n- **Build Script:** Updated `build-next-isolated.mjs` with additional reliability improvements\n- **Auto-Combo UI Cleanup:** Deleted `AutoComboModal.tsx` (161 lines), replaced `auto-combo/page.tsx` (478→5 lines) with a server-side redirect to `/dashboard/combos?filter=intelligent`\n- **Sidebar Consolidation:** Removed `\"auto-combo\"` from `HIDEABLE_SIDEBAR_ITEM_IDS` and `PRIMARY_SIDEBAR_ITEMS` — `normalizeHiddenSidebarItems()` silently discards any stale `\"auto-combo\"` entries in user settings\n- **Schema Cleanup:** Removed obsolete `createAutoComboSchema` from `schemas.ts`. Exported `comboStrategySchema` for direct use in test and filter modules\n- **A2A Agent Card Update:** Renamed skill ID from `auto-combo` to `intelligent-routing` with updated description referencing the unified combos dashboard\n- **Builder Draft Refactor:** Extended `builderDraft.ts` with dynamic stage list generation via `getComboBuilderStages()` and `isIntelligentBuilderStrategy()`. Stage navigation (`getNextComboBuilderStage`, `getPreviousComboBuilderStage`, `canAccessComboBuilderStage`) now accepts options to conditionally include/skip the `intelligent` wizard step\n- **i18n Consolidation:** Removed the standalone `\"autoCombo\"` i18n block (22 keys) from all 30 language files. Migrated keys into the `\"combos\"` block with new additions for filter tabs, intelligent panel, and builder step labels\n\n### 🧪 Tests\n\n- **16 New Test Suites:** Added comprehensive test coverage including:\n - `combo-builder-draft.test.mjs` (186 lines) — Builder draft step construction and validation\n - `combo-builder-options-route.test.mjs` (228 lines) — Builder options API endpoint\n - `combo-health-route.test.mjs` (266 lines) — Combo health analytics with per-target metrics\n - `combo-routes-composite-tiers.test.mjs` (157 lines) — Composite tiers API integration\n - `composite-tiers-validation.test.mjs` (131 lines) — Composite tier validation rules\n - `db-combos-crud.test.mjs` — Combo CRUD with step normalization\n - `db-core-init.test.mjs` (129 lines) — DB initialization and column migrations\n - `model-capabilities-registry.test.mjs` (105 lines) — Model capabilities resolution\n - `observability-payloads.test.mjs` (165 lines) — Health/telemetry payload construction\n - `openapi-spec-route.test.mjs` — OpenAPI spec generation\n - `proxy-e2e-mode.test.mjs` (74 lines) — E2E mode auth bypass\n - `quota-monitor.test.mjs` — Quota monitor lifecycle state\n - `run-next-playwright.test.mjs` (119 lines) — Playwright runner script\n - `sse-auth.test.mjs` (154 lines) — P2C credential selection and quota preflight\n - `telemetry-summary-route.test.mjs` (35 lines) — Telemetry summary endpoint\n - Plus updates to 12 existing test files for compatibility with new step architecture\n- **Auto-Combo Unification Tests:**\n - `autocombo-unification.test.mjs` (156 lines) — Strategy categorization, schema deduplication, sidebar cleanup, and routing strategies metadata validation\n - `combo-unification.spec.ts` (189 lines) — Playwright E2E tests for filter tabs, intelligent panel rendering, redirect from old route, sidebar entry removal, and Builder v2 intelligent step flow\n - 3 new LKGP standalone tests in `combo-routing-engine.test.mjs` — Validates LKGP provider prioritization, fallback to priority when no state exists, and LKGP state persistence after successful requests\n - Updated `combo-builder-draft.test.mjs` with intelligent stage navigation tests\n - Updated `sidebar-visibility.test.mjs` to reflect `auto-combo` removal\n\n---\n\n## [3.6.3] — 2026-04-11\n\n### ✨ New Features\n\n- **OpenAI-Compatible Loose Validation:** Empty API keys can now be naturally submitted and saved for any `openai-compatible-*` providers (e.g. Pollinations, localized routes) directly in the UI instead of blocking save actions (#1152)\n- **Cloudflare Configuration:** Updated the provider schema and UI integration for Cloudflare AI to officially expose and support the backend `accountId` field securely without overrides (#1150)\n\n### 🐛 Bug Fixes\n\n- **Vertex JSON Validation Crash:** Prevented `invalid character in header` crashes inside the `/validate` endpoint by creating a native authentication parser that correctly handles Google Identity Service Account JSON flows prior to pinging endpoints (#1153)\n- **Extraneous Payload Rejection:** Globally prevented upstream `400 Bad Request` execution crashes by stripping the non-standard `prompt_cache_retention` attribute forcibly attached by Cursor/Cline IDE engines when targeting strict OpenAI/Anthropic routes (#1154)\n- **Reasoning Content Drop:** Prevented pure reasoning packets, common in advanced fallback models like DeepSeek, from being aborted mid-stream by explicitly adjusting the `Empty Content (502)` circuit breakers to acknowledge `reasoning_content` states as valid (#1155)\n- **Desktop Windows Build Crash:** Fixed `better_sqlite3.node is not a valid Win32 application` preventing OmniRoute Desktop from launching on Windows by properly removing the ABI-mismatched sqlite cache from Next.js standalone and falling back to the cross-compiled Electron equivalent during packager build steps (#1163)\n- **Login Visual Security:** Removed the raw fallback hash dump that artificially rendered underneath the login modal in Docker instances missing `OMNIROUTE_API_KEY_BASE64` flags (#1148)\n\n### 🔧 Maintenance & Dependencies\n\n- **Dependabot Updates:** Safely bumped GitHub Actions `docker/build-push-action` to v7 and `actions/download-artifact` to v8\n- **Electron Updates:** Upgraded desktop wrapper core to Electron `41.2.0` and `electron-builder` to `26.8.1`, incorporating essential V8/Chromium security patches\n- **NPM Package Groups:** Updated `production` and `development` NPM groups to securely handle minor audit warnings and keep toolchains modern\n- **CI/CD Reliability:** Fixed persistent `Snyk` token-absence failures on automated pull requests by appropriately bypassing on dependabot actions\n\n## [3.6.2] — 2026-04-11\n\n### ✨ New Features\n\n- **33 New API Key Providers:** Massive provider expansion adding DeepInfra, Vercel AI Gateway, Lambda AI, SambaNova, nScale, OVHcloud AI, Baseten, PublicAI, Moonshot AI, Meta Llama API, v0 (Vercel), Morph, Featherless AI, FriendliAI, LlamaGate, Galadriel, Weights & Biases Inference, Volcengine, AI21 Labs, Venice.ai, Codestral, Upstage, Maritalk, Xiaomi MiMo, Inference.net, NanoGPT, Predibase, Bytez, Heroku AI, Databricks, Snowflake Cortex, and GigaChat (Sber). OmniRoute now supports **100+ providers** (4 Free + 8 OAuth + 91 API Key + Custom compatible)\n- **Global Email Privacy Toggle:** Added a persistent eye-icon toggle button across all dashboard pages (Providers, Usage Limits, Playground) that reveals or hides masked email addresses. Toggle state is stored in localStorage and synced globally via Zustand store\n- **Documentation Refresh:** Updated README, ARCHITECTURE, FEATURES, AGENTS.md, and API_REFERENCE for v3.6.2 with accurate provider counts (100+), new executor list, and system API documentation\n- **Uninstall Guide:** Created comprehensive `docs/UNINSTALL.md` covering clean uninstallation for all deployment methods (npm, Docker, Electron, source)\n\n### 🐛 Bug Fixes\n\n- **PDF Attachments:** Unlocked deep string object parsing (`geminiHelper`) ensuring Gemini translation successfully passes complex PDF payloads from OpenAI-compatible streams without dropping them silently (#993)\n- **SkillsMP Engine:** Corrected object extraction path mappings inside the API router to fix UI marketplace rendering under Docker/Standalone Node isolated deployments (#988)\n\n---\n\n## [3.6.1] — 2026-04-10\n\n### ✨ New Features\n\n- **OAuth Env Repair Action:** Added a \"Repair env\" button to the OAuth Providers dashboard that detects and restores missing OAuth client IDs from `.env.example` — with timestamped backup and append-only safety. Includes full 33-language i18n support and sanitized API responses (#1116, by @yart)\n\n### 🐛 Bug Fixes\n\n- **i18n: Missing Provider Keys:** Added missing `filterModels`, `modelsActive`, `showModel`, `hideModel` keys across all 32 locale files, fixing runtime `MISSING_MESSAGE` errors in the providers UI. Also cleaned up duplicate keys in `en.json` (#1111, by @rilham97)\n- **GPT-5.4 Routing:** Added missing `targetFormat: \"openai-responses\"` to `gpt-5.4` and `gpt-5.4-mini` models in both the Codex and GitHub Copilot providers, fixing `[400]: model not accessible via /chat/completions` errors (#1114, by @ask33r)\n\n---\n\n## [3.6.0] — 2026-04-10\n\n### ✨ New Features & Analytics\n\n- **Combo Smoke Test:** Raised the default token budget to 2048 to prevent truncation of thinking models during preflight checks, and fully randomized the arithmetic probe prompt to bypass deterministic caching from upstream relays (#1105)\n\n### 🐛 Bug Fixes & Compliance\n\n- **DB Bloat / Row Limits:** Added `CALL_LOGS_TABLE_MAX_ROWS` and `PROXY_LOGS_TABLE_MAX_ROWS` (default: 100,000) to the backend DB compliance cleaner to prevent runaway SQLite growth. Limits are enforced automatically on the TTL cycle (#1104, fixes #1101)\n- **HTML Error Handling:** The router now correctly identifies unexpected HTML responses (e.g. ``) sent by upstream providers (like Azure/Copilot) instead of throwing obscure `Unexpected token '<'` JSON parse errors, bubbling up a clean 502 Bad Gateway (#1104, fixes #1066)\n- **Android/Termux SQLite Native Support:** `better-sqlite3` is now correctly built from source with cross-compilation flags in ARM64 local Termux deployments without failing on missing prebuilt binaries (#1107)\n\n---\n\n## [3.5.9] — 2026-04-09\n\n### ✨ New Features\n\n- **Persistent Combo Ordering:** Drag combo cards by handle to reorder them in the dashboard; order is persisted to SQLite via a new `sort_order` column and `POST /api/combos/reorder` endpoint. Includes DB migration `020_combo_sort_order.sql` and JSON import preservation (#1095)\n- **Sidebar Group Reorder:** Moved \"Logs\" before \"Health\" in the System section and \"Limits & Quotas\" after \"Cache\" in the Primary section for a more logical navigation flow (#1095)\n\n### 🐛 Bug Fixes\n\n- **Stream Failure Surfacing:** Upstream `response.failed` events (e.g. Codex rate-limit errors) are now properly surfaced as non-200 errors instead of being silently swallowed as empty 200 OK streams. Rate-limit failures return HTTP 429 (#1098, closes #1093)\n- **Upstream Model Preservation:** The Responses-to-OpenAI stream translator now preserves the actual upstream model (e.g. `gpt-5.4`) instead of hardcoding a `gpt-4` fallback (#1098, closes #1094)\n- **Docker EXDEV Fix:** `build-next-isolated.mjs` now falls back from `fs.rename()` to `cp/rm` when Docker buildx raises `EXDEV` (cross-device link), unblocking the Docker image publish workflow (#1097)\n- **macOS CLI Path Resolution:** `cliRuntime.ts` resolves symlink parents with `fs.realpath()` to handle macOS `/var` → `/private/var` chains, preventing false `symlink_escape` rejections (#1097)\n- **Request Log Token Layout:** Split token badges into separate Input (Total In, Cache Read, Cache Write) and Output (Total Out, Reasoning) groups for clearer readability; renamed \"Time\" label to \"Completed Time\" (#1096)\n\n---\n\n## [3.5.8] — 2026-04-09\n\n### ✨ New Features & Analytics\n\n- **Analytics Layout Redesign:** Replaced flat metrics with a responsive `CompactStatGrid`, grouping data visually across sections (#1089)\n\n### 🐛 Bug Fixes\n\n- **Build Core:** Force Turbopack cleanup via Prepbulish script to prevent Next.js 16 app/ routing conflicts on runtime.\n- **Provider Quarantine:** Introduces model/provider circuit-breakers with adaptive TTL exponential backoff for recurring upstream errors (#1090)\n- **Oauth Keep-Alive:** Safely protects authenticated active accounts against spontaneous dropping from router due to transient token refresh failures (#1085)\n\n### 🔒 Security & Maintenance\n\n- **Dependabot:** bumped axios from 1.14.0 to 1.15.0 addressing SSRF flags (#1088)\n\n---\n\n## [3.5.7] — 2026-04-09\n\n### 🐛 Bug Fixes & Security\n\n- **Turbopack Standalone Chunks:** Fixed a critical bug in `scripts/prepublish.mjs` where Turbopack chunks missing from the `.next/standalone` trace resulted in a `500 ChunkLoadError` (e.g., `_not-found` page crash) during production deployments via NPM or Docker. Standalone chunks are now explicitly copied and correctly stripped of Turbopack hashes.\n\n---\n\n## [3.5.6] — 2026-04-09\n\n### ✨ New Features\n\n- **Email Privacy Masking:** OAuth account emails are now masked in the provider dashboard (e.g. `di*****@g****.com`) to prevent accidental exposure when sharing screenshots. Full address visible on hover via `title` attribute (#1025).\n- **OpenRouter & GitHub in Embedding/Image Registries:** OpenRouter (3 embedding models, 4 image models) and GitHub Models (2 embedding models via Azure inference) are now first-class entries in the provider registries, enabling their use for `/v1/embeddings` and `/v1/images/generations` (#960).\n- **Model Visibility Toggle & Search Filter:** The provider page model list now includes a real-time search/filter bar and a per-model visibility toggle (👁 icon). Hidden models are grayed out and excluded from the `/v1/models` catalog. An active-count badge (`N/M active`) shows at a glance how many models are enabled (#750).\n- **Chinese Localization (zh-CN):** Added missing translations for Context Relay, Memory, LKGP, and Models.dev sync features, while standardizing terminology across the application (#1079).\n- **Environment Auto-Sync:** Added `sync-env.mjs` to auto-generate and append `.env` from `.env.example` during installation, automatically generating cryptographic secrets on first run.\n- **Source Mode Dashboard Update:** Fixed real-time Source (git-checkout) updating in the dashboard, enabling secure, real-time update pipelines for non-NPM installations.\n\n### 🐛 Bug Fixes & Security\n\n- **Hardcoded Secret Cleanup:** Removed 12 hardcoded OAuth credential fallbacks from the source code, forcing secure reliance on environment variables and resolving static analysis security alerts.\n- **Next.js Security Patch:** Bumped `next` from 16.2.2 to 16.2.3 to resolve critical RSC deserialization RCE vulnerability (SNYK-JS-NEXT-15954202).\n- **Memory/Cache UI Crash:** Added null-safety guards (`?? 0`) to `.toLocaleString()` calls in Memory and Cache dashboard pages, preventing `TypeError` crashes when database tables are empty or contain null numeric values (#1083).\n- **WebSearch tool_choice Translation:** Fixed OpenAI-to-Claude translator dropping `tool_choice` objects with `type: \"function\"` as-is, which Claude rejects. Now properly maps all OpenAI `tool_choice` variants (`function`, `required`, `none`) to Claude-compatible format (`tool`, `any`, `auto`), fixing \"Did 0 searches\" in Claude Code WebSearch (#1072).\n- **Provider Validation baseUrl Override:** Added `baseUrl` passthrough from frontend validation requests to the backend validation endpoint. Chinese-site users of Alibaba Coding Plan (bailian-coding-plan) can now validate API keys against their custom Base URL instead of always hitting the international endpoint (#1078).\n- **Minimax Auth Header:** Switched Minimax provider from `x-api-key` to `Authorization: Bearer` header format, matching the current API spec (#1076).\n- **Native Fetch Fallback:** Added graceful fallback to native `fetch` when the `undici` dispatcher fails, improving resilience in environments where undici is unavailable (#1054).\n- **EPIPE Flood Fix:** Added circuit-breaker logic to prevent EPIPE errors from creating a feedback loop that fills logs at GB/s (#1006).\n- **Qoder PAT Validation:** Improved Qoder Personal Access Token validation with actionable error messages that guide users to the correct token format (#966).\n- **CI/CD Pipeline:** Fixed `check:docs-sync` failure by syncing OpenAPI version to 3.5.6 and finalizing CHANGELOG release heading. Commented out `DATA_DIR` in `.env.example` to prevent E2E test failures in CI runners lacking root permissions.\n\n### 🌍 i18n\n\n- **Auto Language Generation (CI):** Added CI pipeline to auto-generate missing language files and strings via `feat(CI,i18n)` workflow, covering 30+ locales (#1071).\n\n---\n\n## [3.5.5] — 2026-04-08\n\n### ✨ New Features\n\n- **Node.js 24 Compatibility Warning:** Added a proactive version incompatibility warning on the login page to guide users to the stable Node.js 22 LTS, preventing native sqlite binding crashes.\n- **Context Relay Combo Strategy:** Added the new `context-relay` combo strategy with priority-style routing, structured handoff summary generation once quota usage reaches the warning threshold, and handoff injection after the next real account switch.\n- **Global Context Relay Defaults:** Added global Settings defaults plus combo-level configuration for `handoffThreshold`, `handoffModel`, and `handoffProviders`, so new or unconfigured combos can inherit the feature consistently.\n\n### 🐛 Bug Fixes\n\n- **Proxy Connection Healthchecks:** Applied proxy resolution per connection in the sweeping loop (`tokenHealthCheck.ts`) and global provider validation sweeps, resolving Node 22 bypass and improving proxy stability (#1051, #1056, #1061).\n- **Security Vulnerability Remediation:** Resolved multiple CodeQL scanning alerts including SSRF in model sync, insecure randomness in web crypto (`generateSessionId`), and incomplete URL sanitization.\n- **Context Relay Typing & Synchronization:** Reverted out-of-scope test breakages and resolved `handoffProvider` and response `input` extraction payload typing.\n- **Legacy OpenAI-Compatible Responses Routing:** Fixed legacy/imported OpenAI-compatible providers (for example `openai-compatible-sp-openai`) incorrectly routing Chat Completions traffic to `/chat/completions` when the real provider node was configured as `apiType: \"responses\"`. OmniRoute now treats `providerSpecificData.apiType` as authoritative across routing, executors, and translator tools, avoiding false empty-content failures during combo/provider smoke tests (#1069).\n- **Gemini PDF Attachment Integration:** Fixed payload generation and format for parsing `inline_data` and generic base64 sources for deep Gemini PDF routing (#993, #1021).\n- **Vercel AI SDK Fallbacks:** Mapped `max_output_tokens` to `max_tokens` for strict OpenAI-compatible providers, resolving errors from standard AI agents and frameworks (#994).\n- **External Auth & UI Reliability:** Handled null `state` failures in Cline OAuth exchange (#1016), added 3rd-party 400 error patterns to combo fallback (#1024), and resolved desktop sidebar layout and popover overflows (#1039, #1001).\n- **Context Relay In-Flight Deduplication:** Prevented duplicate handoff generation for the same session/combo while an earlier summary request is still in flight.\n- **Context Relay Provider Gating:** Aligned runtime behavior with configuration so explicit `handoffProviders` exclusions, including an empty array, now disable handoff generation as expected.\n\n### 🛠️ Maintenance & Dependabot\n\n- **Updated Sub-dependencies:** Bumped `hono` to `4.12.12` and `@hono/node-server` to `1.19.13` to patch critical security gaps (#1063, #1064, #1067, #1068).\n\n### التوثيق\n\n- **Documentation Synchronization:** Updated system documentation (README, Architecture, Features, Tools, Troubleshooting) and synced `i18n` configurations to match the v3.5.5 context relay patterns and proxy troubleshooting steps.\n- **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance.\n\n---\n\n## [3.5.4] — 2026-04-07\n\n### ✨ New Features\n\n- **Detailed Token Tracking:** Added granular token breakdown columns (cache read, cache write, reasoning) to call logs with proper null vs zero distinction. Includes DB migration 018 and 5-label UI display per provider capability (#1017 — thanks @rdself).\n- **Legacy JSON Config Import/Export:** Restored JSON-based settings export and import for migration from legacy 9router configurations. Security-hardened with Zero-Trust redaction of passwords and `requireLogin` fields, and automatic pre-import database backups (#1012 — thanks @luandiasrj).\n- **Non-Stream Aliases:** Added API support for explicit non-streaming aliases (`non_stream`, `disable_stream`, `disable_streaming`, `streaming=false`), normalized at the boundary before provider translation (#1036 — thanks @wlfonseca).\n- **Russian Dashboard Localization:** Comprehensive Russian translation for the dashboard UI, including fixes for 2 Ukrainian locale keys (#1003 — thanks @mercs2910).\n\n### 🐛 Bug Fixes\n\n- **Anthropic Streaming Input Undercount:** Fixed a critical bug where Anthropic streaming `prompt_tokens` only reported non-cached tokens (e.g., `in=3` when actual total was 113,616). Cache tokens are now summed into prompt_tokens during streaming (#1017).\n- **Built-in Responses API Tool Types:** Preserved built-in Responses API tools (`web_search`, `file_search`, `computer`, `code_interpreter`, `image_generation`) from being silently stripped by the empty-name tool filter — these tools carry no `.name` field (#1014 — thanks @rdself).\n- **Cursor/Codex Responses Compatibility:** Fixed empty output in Cursor when using Codex models by hoisting system input items to `instructions`, sanitizing invalid tool names, and detecting Responses-format payloads on chat/completions endpoint (#1002 — thanks @mercs2910).\n- **OAuth Token Expiry Display:** Fixed OAuth connections showing \"expired\" badge even with valid tokens by reading `tokenExpiresAt` (updated on refresh) instead of `expiresAt` (original grant timestamp) (#1032 — thanks @tombii).\n- **Codex Fast-Tier Copy:** Corrected dashboard settings copy from `service_tier=fast` to `service_tier=priority`, matching the actual Codex wire format (#1045 — thanks @kfiramar).\n- **macOS Desktop App Startup:** Stabilized packaged macOS app launch by excluding desktop artifacts from the standalone bundle and improving launch path detection (#1004 — thanks @mercs2910).\n- **macOS Sidebar Layout:** Fixed macOS traffic light overlap, sidebar spacing, and button overflow in the Electron desktop app (#1001 — thanks @mercs2910).\n\n### ⚡ Performance\n\n- **Analytics Page Load:** Dramatically reduced analytics page load times (30s→1-2s for 50K entries) via date-filtered DB queries, parallel `Promise.all()` cost calculations, and merged 6 COUNT queries into a single CASE WHEN aggregate (#1038 — thanks @oyi77).\n\n### 🔒 Security & Dependencies\n\n- **Node Base Image:** Upgraded Docker base from `22-bookworm-slim` to `22.22.2-trixie-slim` (#1011 — Snyk).\n- **Production Dependencies:** Bumped 5 production dependencies (#1044 — Dependabot).\n- **Vite:** Bumped from 8.0.3 to 8.0.5 (#1031 — Dependabot).\n- **Development Dependencies:** Bumped 4 development dependencies (#1030 — Dependabot).\n\n### 🧪 Tests\n\n- **Token Accounting Tests:** Added 18 new unit tests covering detailed token breakdown, null vs zero semantics, per-provider token extraction, and Anthropic streaming input fix (#1017).\n- **Built-in Tool Tests:** Added 3 new test cases for built-in Responses API tool type preservation (#1014).\n- **ChatCore Sanitization:** Updated sanitization tests to accommodate Responses format detection (PR #1002) and built-in tool preservation (PR #1014).\n\n### 🛠️ Maintenance\n\n- **PR Workflow:** Updated `/review-prs` workflow to merge PRs into the release branch (`release/vX.Y.Z`) instead of directly into `main`, ensuring proper pre-release staging.\n\n### Coverage\n\n- **2537 tests, 2532 passing** — Statement coverage: 91.95%, Branch coverage: 78.79%, Function coverage: 93.19%\n\n## [3.5.3] - 2026-04-07\n\n### الأمان\n\n- **Vulnerabilities:** Fully remediated 12 High-Severity CodeQL vulnerabilities by migrating from Math.random to `crypto.randomUUID()`, wrapping SSE injection points with aggressive backslash escaping, sanitizing trailing HTTP fragments, and enforcing rigid SSRF HTTP verification schemes across internal routes.\n- **Dependencies:** Upgraded Next.js to `^16.2.2` and Vite to `>=8.0.5` resolving critical DoS, arbitrary file reads and CSRF vectors in the build/server environments.\n\n### Fixed\n\n- **E2E Stability:** Eliminated extreme CI unreliability and transient test timeouts (Playwright) by propagating internal standalone `_next/static` assets properly and refactoring deep UI interactions inside defensive `expect().toPass()` loops.\n- **Middleware:** Resolved infinite redirect loop on dashboard for fresh instances when requireLogin is disabled.\n- **Core Fallbacks:** Preserved primary failure contexts and enhanced Edge-case error handling pipelines across chat and fallback loops.\n- **Proxy/Hooks:** Optimized local git hooks, normalized token coverage endpoints into `/coverage`, and guarded GLM region lookups.\n\n### 🛠️ Maintenance\n\n- **CI/CD Stabilization:** Prevented random GitHub Runner freezes by decoupling sharded processes, adjusting test concurrencies, unref-ing active connections on server teardown, and strictly capping job timeout durations.\n\n### التوثيق\n\n- **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned).\n\n### Coverage\n\n- **Testing:** Consolidated the workspace test coverage framework hitting 92.1% statement line coverage, with new rigid unit-tests matching API key policies and tool scopes.\n\n---\n\n## [3.5.2] — 2026-04-05\n\n### ✨ New Features\n\n- **Qoder API Native Integration:** Completely refactored the Qoder Executor to bypass the legacy COSY AES/RSA encryption algorithm, routing directly into the native DashScope OpenAi-compatible URL. Eliminates complex dependencies on Node `crypto` modules while improving stream fidelity.\n- **Resilience Engine Overhaul:** Integrated context overflow graceful fallbacks, proactive OAuth token detection, and empty-content emission prevention (#990).\n- **Context-Optimized Routing Strategy:** Added new intelligent routing capability to natively maximize context windows in automated combo deployments (#990).\n\n### 🐛 Bug Fixes\n\n- **Responses API Stream Corruption:** Fixed deep-cloning corruption where Anthropic/OpenAI translation boundaries stripped `response.` specific SSE prefixes from streaming boundaries (#992).\n- **Claude Cache Passthrough Alignment:** Aligned CC-Compatible cache markers consistently with upstream Client Pass-Through mode preserving prompt caching.\n- **Turbopack Memory Leak:** Pinned Next.js to strict `16.0.10` preventing memory leaks and build staleness from recent upstream Turbopack hashed module regressions (#987).\n\n---\n\n## [3.5.1] — 2026-04-04\n\n### ✨ New Features\n\n- **Models.dev Integration:** Integrated models.dev as the authoritative runtime source for model pricing, capabilities, and specifications, overriding hardcoded prices. Includes a settings UI to manage sync intervals, translation strings for all 30 languages, and robust test coverage.\n- **Provider Native Capabilities:** Added support for declaring and checking native API features (e.g. `systemInstructions_supported`) preventing failures by sanitizing invalid roles. Currently configured for Gemini Base and Antigravity OAuth providers.\n- **API Provider Advanced Settings:** Added per-connection custom `User-Agent` overrides for API-key provider connections. The override is stored in `providerSpecificData.customUserAgent` and now applies to validation probes and upstream execution requests.\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Reliability:** Resolved a series of OAuth integration issues including a 400 Bad Request blocker on expired tokens, fallback generation for parsing OIDC `access_token` properties when `id_token` is omitted, model catalog discovery errors, and strict filtering of `X-Dashscope-*` headers to avoid 400 rejection from OpenAI-compatible endpoints.\n\n## [3.5.0] — 2026-04-03\n\n### ✨ New Features\n\n- **Auto-Combo & Routing:** Completed native CRUD lifecycle integration for the advanced Auto-Combo engine (#955).\n- **Core Operations:** Fixed missing translations for new native Auto-Combos options (#955).\n- **Security Validation:** Disabled SQLite auto-backup tasks natively during unit test CI execution to explicitly resolve Node 22 Event Loop hanging memory leaks (#956).\n- **Ecosystem Proxies:** Completed explicit integration mapping model synchronization schedulers, OAuth cycles, and Token Check refreshes safely through OmniRoute's native system upstream proxies (#953).\n- **MCP Extensibility:** Added and successfully registered the new `omniroute_web_search` MCP framework tool out of beta into production schemas (#951).\n- **Tokens Buffer Logic:** Added runtime configuration limits extending configurable input/output token buffers for precise Usage Tracking metrics (#959).\n\n### 🐛 Bug Fixes\n\n- **CodeQL Remediation:** Fully resolved and secured critical string indexing operations preventing Server-Side Request Forgery (SSRF) arrays indexing heuristics alongside polynomial algorithmic backtracking (ReDoS) inside deep proxy dispatcher modules.\n- **Crypto Hashes:** Replaced weak unverified legacy OAuth 1.0 hashes with robust HMAC-SHA-256 standard validation primitives ensuring tight access controls.\n- **API Boundary Protection:** Correctly verified and mapped structural route protections enforcing strict `isAuthenticated()` middleware logic covering newer dynamic endpoints targeting settings manipulation and native skills loading.\n- **CLI Ecosystem Compat:** Resolved broken native runtime parser bindings crashing `where` environment detectors strictly over `.cmd/.exe` edge cases gracefully for external plugins (#969).\n- **Cache Architecture:** Refactored exact Analytics and System Settings dashboard parameters layout structure caching to maintain stable re-hydration persistence cycles resolving visual unaligned state flashes (#952).\n- **Claude Caching Standards:** Normalized and accurately strictly preserved critical ephemeral block markers `ephemeral` caching TTL orders for downstream nodes enforcing standard compatible CC requests mapping cleanly without dropped metrics (#948).\n- **Internal Aliases Auth:** Simplified internal runtime mappings normalizing Codex credential payload lookups inside global translation parameters resolving 401 unauthenticated drops (#958).\n\n### 🛠️ Maintenance\n\n- **UI Discoverability:** Correctly adjusted layout categorizations explicitly separating free tier providers logic improving UX sorting flows inside the general API registry pages (#950).\n- **Deployment Topology:** Unified Docker deployment artifacts ensuring the root `fly.toml` matches expected cloud instance parameters out-of-the-box natively handling automated deployments scaling properly.\n- **Development Tooling:** Decoupled `LKGP` runtime parameters into explicit DB layer abstraction caching utilities ensuring strict test isolation coverage for core caching layers safely.\n\n---\n\n## [3.4.9] — 2026-04-03\n\n### Features & Refactoring\n\n- **Dashboard Auto-Combo Panel:** Completely refactored the `/dashboard/auto-combo` UI to seamlessly integrate with native Dashboard Cards and standardized visual padding/headers. Added dynamic visual progress bars mapping model selection weight mechanisms.\n- **Settings Routing Sync:** Fully exposed advanced routing `priority` and `weighted` schema targets internally inside global settings fallback lists.\n\n### Bug Fixes\n\n- **Memory & Skills Locale Nodes:** Resolved empty rendering tags for Memory and Skills options directly inside global settings views by wiring all `settings.*` mapping values internally into `en.json` (also mapped implicitly for cross-translation tools).\n\n### Internal Integrations\n\n- Integrated PR #946 — fix: preserve Claude Code compatibility in responses conversion\n- Integrated PR #944 — fix(gemini): preserve thought signatures across antigravity tool calls\n- Integrated PR #943 — fix: restore GitHub Copilot body\n- Integrated PR #942 — Fix cc-compatible cache markers\n- Integrated PR #941 — refactor(auth): improve NVIDIA alias lookup + add LKGP error logging\n- Integrated PR #939 — Restore Claude OAuth localhost callback handling\n- _(Note: PR #934 was omitted from 3.4.9 cycle to prevent core conflict regressions)_\n\n---\n\n## [3.4.8] — 2026-04-03\n\n### الأمان\n\n- Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts.\n- Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`.\n- Secured shell commands in automated scripts from string injection.\n- Migrated vulnerable catastrophic backtracking RegEx parsing patterns in chat/translation pipelines.\n- Enhanced output sanitization controls inside React UI components and Server Sent Events (SSE) tag injection.\n\n---\n\n## [3.4.7] — 2026-04-03\n\n### الميزات\n\n- Added `Cryptography` node to Monitoring and MCP health checks (#798)\n- Hardened model-catalog route permissions mapping (`/models`) (#781)\n\n### Bug Fixes\n\n- Fixed Claude OAuth token refreshes failing to preserve cache contexts (#937)\n- Fixed CC-Compatible provider errors rendering cached models unreachable (#937)\n- Fixed GitHub Executor errors related to invalid context arrays (#937)\n- Fixed NPM-installed CLI tools healthcheck failures on Windows (#935)\n- Fixed payload translation dropping valid content due to invalid API fields (#927)\n- Fixed runtime crash in Node 25 regarding API key execution (#867)\n- Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936)\n- Fixed NVIDIA NIM routing credential resolution alias mismatch (#931)\n\n### الأمان\n\n- Added safe strict input boundary protection against raw `shell: true` remote-code execution injections.\n\n---\n\n## [3.4.6] - 2026-04-02\n\n### ✨ New Features\n\n- **Providers:** Registered new image, video, and audio generation providers from the community-requested list (#926).\n- **Dashboard UI:** Added standalone sidebar navigation for the new Memory and Skills modules (#926).\n- **i18n:** Added translation strings and layout mappings across 30 languages for the Memory and Skills namespaces.\n\n### 🐛 Bug Fixes\n\n- **Resilience:** Prevented the proxy Circuit Breaker from becoming stuck in an OPEN state indefinitely by handling direct transitions to CLOSED state inside fallback combo paths (#930).\n- **Protocol Translation:** Patched the streaming transformer to sanitize response blocks based on the expected _source_ protocol rather than the provider _target_ protocol, fixing Anthropics models wrapped in OpenAI payloads crashing Claude Code (#929).\n- **API Specs & Gemini:** Fixed `thought_signature` parsing in `openai-to-gemini` and `claude-to-gemini` translators, preventing HTTP 400 errors across all Gemini 3 API tool-calls.\n- **Providers:** Cleaned up non-OpenAI-compatible endpoints preventing valid upstream connections (#926).\n- **Cache Trends:** Fixed an invalid property mapping data mismatch causing Cache Trends UI charts to crash, and extracted redundant cache metric widgets (#926).\n\n---\n\n## [3.4.5] - 2026-04-02\n\n### ✨ New Features\n\n- **CLIProxyAPI Ecosystem Integration:** Added the `cliproxyapi` executor with built-in module-level caching and proxy routing. Introduced a comprehensive Version Manager service to automatically test health, download binaries from GitHub, spawn isolated background processes, and cleanly manage the lifecycle of external CLI tools directly through the UI. Includes DB tables for proxy configuration to enable automatic SSRF-gated cross-routing of external OpenAI requests via the local CLI tool layer (#914, #915, #916).\n- **Qoder PAT Support:** Integrated Personal Access Tokens (PAT) support directly via the local `qodercli` transport instead of legacy remote `.cn` browser configurations (#913).\n- **Gemini 3.1 Pro Preview (GitHub):** Added `gemini-3.1-pro-preview` canonical explicit model support natively into the GitHub Copilot provider while preserving older routing aliases (#924).\n\n### 🐛 Bug Fixes\n\n- **GitHub Copilot Token Stability:** Repaired the Copilot token refresh loop where stale tokens weren't deep-merged into DB, and removed `reasoning_text` fields that were fatally breaking downstream Anthropic block conversions for multi-turn chats (#923).\n- **Global Timeout Matrix:** Centralized and parameterized request timeouts explicitly from `REQUEST_TIMEOUT_MS` to prevent hidden (~300s) default fetch buffers prematurely cutting off long-lived SSE streaming responses from heavy reasoning models (#918).\n- **Cloudflare Quick Tunnels State:** Fixed a severe state inconsistency where restarted OmniRoute instances erroneously showed destroyed tunnels as active, and defaulted cloudflared tunneling to `HTTP/2` to eliminate UDP receive buffer log spam (#925).\n- **i18n Translation Overhaul (Czech & Hindi):** Fixed Hindi code from DEPRECATED `in.json` to canonical `hi.json`, overhauled Czech text mappings, extracted `untranslatable-keys.json` to fix CI/CD false-positive validations, and generated comprehensive `I18N.md` docs to guide translators (#912).\n- **Tokens Provider Recovery:** Fixed Qwen losing specific `resourceUrl` endpoints after automatic health-check token refreshes because of missing DB deep merges (#917).\n- **CC Compatible UX & Streaming:** Unified the Add CC/OpenAI/Anthropic compatible actions around the Anthropic UI treatment, forced CC-compatible upstream requests to use SSE while still returning streaming or non-streaming responses based on the client request, removed CC model-list configuration/import support in favor of an explicit unsupported-model-listing error, and made CC-compatible Available Models mirror the OAuth Claude Code registry list (#921).\n\n---\n\n## [3.4.4] - 2026-04-02\n\n### 🐛 Bug Fixes\n\n- **Responses API Token Reporting:** Emit `response.completed` with correct `input_tokens`/`output_tokens` fields for Codex CLI clients, fixing token usage display (#909 — thanks @christopher-s).\n- **SQLite WAL Checkpoint on Shutdown:** Flush WAL changes into the primary database file during graceful shutdown/restart, preventing data loss on Docker container stops (#905 — thanks @rdself).\n- **Graceful Shutdown Signal:** Changed `/api/restart` and `/api/shutdown` routes from `process.exit(0)` to `process.kill(SIGTERM)`, ensuring the shutdown handler runs before exit.\n- **Docker Stop Grace Period:** Added `stop_grace_period: 40s` to Docker Compose files and `--stop-timeout 40` to Docker run examples.\n\n### 🛠️ Maintenance\n\n- Closed 5 resolved/not-a-bug issues (#872, #814, #816, #890, #877).\n- Triaged 6 issues with needs-info requests (#892, #887, #886, #865, #895, #870).\n- Responded to CLI detection tracking issue (#863) with contributor guidance.\n\n---\n\n## [3.4.3] - 2026-04-02\n\n### ✨ New Features\n\n- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.\n- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.\n- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.\n- **Cache Components:** Implemented dynamic cache components utilizing TDD.\n- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.\n- **Log Retention:** Unified request log retention and artifacts natively.\n- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.\n- **i18n & translations:** Integrated 33 language translations natively, including placeholder CI validations and Chinese documentation updates (#873, #869).\n\n### 🐛 Bug Fixes\n\n- **Qwen OAuth Mapping:** Reverted `id_token` reliance to `access_token` and enabled dynamic `resource_url` API endpoint injection for proper regional routing (#900).\n- **Model Sync Engine:** Stored the strict internal Provider ID in `getCustomModels()` sync routines instead of the UI Channel Alias format, preventing SQLite catalog insertion failures (#903).\n- **Claude Code & Codex:** Standardized non-streaming blank responses to Anthropic-formatted `(empty response)` to prevent CLI proxy crashes (#866).\n- **CC Compatible Routing:** Resolved duplicate `/v1` endpoint collision during path concatenation for generic Claude Code gateways (#904).\n- **Antigravity Dashboards:** Blocked unlimited quota models from falsely registering as exhausted `100% Usage` limit states in the Provider Usage UI (#857).\n- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).\n- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).\n- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).\n- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).\n- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).\n- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.\n- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.\n- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.\n- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.\n- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.\n- **Model Sync Engine:** Bypassed destructive `replace` overrides when the provider's auto-sync yields an empty model list, maintaining stability for dynamic catalogs (#899).\n\n### 🛠️ Maintenance\n\n- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).\n- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).\n- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.\n- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.\n- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.\n\n## [3.4.1] - 2026-03-31\n\n> [!WARNING]\n> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**\n> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.\n\n### ✨ New Features\n\n- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `` when restricted access is on (#781)\n- **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660)\n- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI\n\n### 🐛 Bug Fixes\n\n- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)\n- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)\n- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)\n- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)\n- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices\n\n---\n\n## [3.3.7] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)\n- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)\n\n---\n\n## [3.3.6] - 2026-03-30\n\n### 🐛 Bug Fixes\n\n- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)\n- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)\n- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)\n\n---\n\n## [3.3.5] - 2026-03-30\n\n### ✨ New Features\n\n- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)\n- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)\n\n### 🐛 Bug Fixes\n\n- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)\n- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)\n\n---\n\n## [3.3.4] - 2026-03-30\n\n### ✨ New Features\n\n- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.\n- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.\n- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.\n- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.\n- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.\n- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.\n- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.\n\n### 🐛 Bug Fixes\n\n- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.\n- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.\n- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.\n\n### 🧪 Tests\n\n- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.\n\n---\n\n## [3.3.3] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.\n- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).\n- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).\n- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.\n\n---\n\n## [3.3.2] - 2026-03-29\n\n### ✨ New Features\n\n- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).\n- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).\n- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).\n- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).\n\n---\n\n## [3.3.1] - 2026-03-29\n\n### 🐛 Bug Fixes\n\n- **OpenAI Codex:** Fallback processing fix for `type: \"text\"` elements carrying null or empty datasets that caused 400 rejection (#742).\n- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).\n- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).\n- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).\n\n---\n\n## [3.3.0] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.\n\n### 🐛 Bug Fixes\n\n- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.\n- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.\n\n---\n\n## [3.2.9] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)\n- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)\n\n### 🐛 Bug Fixes\n\n- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)\n\n---\n\n## [3.2.8] - 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.\n- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.\n\n### 🐛 Bug Fixes\n\n- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.\n- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\\AppData\\Local\\droid\\droid.exe`.\n- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.\n- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.\n- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.\n\n---\n\n## [3.2.7] - 2026-03-29\n\n### Fixed\n\n- **Seamless UI Updates**: The \"Update Now\" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.\n\n---\n\n## [3.2.6] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.\n- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.\n- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.\n- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.\n\n### 🐛 Bug Fixes\n\n- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.\n\n---\n\n## [3.2.5] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.\n\n## [3.2.4] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.\n\n### 🐛 Bug Fixes\n\n- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.\n\n---\n\n## [3.2.3] — 2026-03-29\n\n### ✨ Enhancements & Refactoring\n\n- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.\n\n### 🐛 Bug Fixes\n\n- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.\n- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.\n- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.\n\n---\n\n## [3.2.2] — 2026-03-29\n\n### ✨ New Features\n\n- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.\n\n### 🐛 Bug Fixes\n\n- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.\n- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.\n- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.\n\n## [3.2.1] — 2026-03-29\n\n### ✨ New Features\n\n- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.\n\n### 🐛 Bug Fixes\n\n- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.\n- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.\n- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.\n\n### 🧪 Tests\n\n- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)\n\n## [3.2.0] — 2026-03-28\n\n### ✨ New Features\n\n- **Cache Management UI** — Added a dedicated semantic caching dashboard at \\`/dashboard/cache\\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)\n- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)\n- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)\n\n### 🐛 Bug Fixes\n\n- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \\`cache_control\\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)\n- **Fix #719** — Setup internal auth boundaries for \\`ModelSyncScheduler\\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)\n- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)\n- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)\n\n### 🔒 Security & Dependencies\n\n- Bumped \\`path-to-regexp\\` to \\`8.4.0\\` resolving dependabot vulnerabilities (PR #715)\n\n## [3.1.10] — 2026-03-28\n\n### 🐛 Bug Fixes\n\n- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.\n- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: \"responses\"`.\n- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.\n- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.\n\n## [3.1.9] — 2026-03-28\n\n### ✨ New Features\n\n- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `\"minimum\": \"1\"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.\n- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.\n- **Clear All Models Button** — Added i18n translations for the \"Clear All Models\" provider action across all 30 languages.\n- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.\n- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.\n\n### 🐛 Bug Fixes\n\n- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).\n- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.\n- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.\n- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.\n- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.\n\n### 🧪 Tests\n\n- Test suite expanded from 964 → 1027 tests (63 new tests)\n- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization\n- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests\n- Enhanced feature-tests branch with comprehensive coverage tooling\n\n### 📁 New Files\n\n| File | Purpose |\n| -------------------------------------------------------- | ----------------------------------------------------------- |\n| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |\n| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |\n| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |\n| `COVERAGE_PLAN.md` | Test coverage planning document |\n\n### 🐛 Bug Fixes\n\n- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.\n\n## [3.1.8] - 2026-03-27\n\n### 🐛 Bug Fixes & Features\n\n- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).\n- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).\n- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).\n- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).\n\n---\n\n## [3.1.6] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)\n- **Clear All Models Alias Cleanup** — \"Clear All Models\" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)\n\n---\n\n## [3.1.5] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)\n\n### 🌍 i18n\n\n- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)\n\n---\n\n## [3.1.4] — 2026-03-27\n\n### 🐛 Bug Fixes\n\n- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)\n\n### 🌍 i18n\n\n- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)\n\n---\n\n## [3.1.3] — 2026-03-26\n\n### 🌍 i18n & Community\n\n- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)\n- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)\n- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)\n\n---\n\n## [3.1.2] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)\n- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.1] — 2026-03-26\n\n### ✨ New Features\n\n- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)\n- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)\n\n### 🐛 Bug Fixes\n\n- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)\n- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures**\n\n---\n\n## [3.1.0] — 2026-03-26\n\n### ✨ New Features\n\n- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)\n- **Clear All Models**: Added a \"Clear All Models\" button to the provider detail page with i18n support in 29 languages (#634)\n\n### 🐛 Bug Fixes\n\n- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)\n- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)\n- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)\n- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)\n- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)\n\n### 🧪 Tests\n\n- **936 tests, 0 failures** (+10 tests since 3.0.9)\n\n---\n\n## [3.0.9] — 2026-03-26\n\n### 🐛 Bug Fixes\n\n- **NaN tokens in Claude Code / client responses (#617):**\n - `sanitizeUsage()` now cross-maps `input_tokens`→`prompt_tokens` and `output_tokens`→`completion_tokens` before the whitelist filter, fixing responses showing NaN/0 token counts when providers return Claude-style usage field names\n\n### الأمان\n\n- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)\n\n### 📋 Issue Triage\n\n- Closed #613 (Codestral — resolved with Custom Provider workaround)\n- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)\n- Commented on #618 (tool call visibility — requesting v3.0.9 test)\n- Commented on #627 (effort level — already supported)\n\n---\n\n## [3.0.8] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**\n - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`\n - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`\n - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`\n - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields\n - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths\n\n---\n\n## [3.0.7] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)\n- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so \"Import from /models\" works correctly (#612)\n- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)\n- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails\n- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId\n\n### ✨ New Features\n\n- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider\n- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog\n- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)\n\n### 🔧 Maintenance\n\n- Merged PR #625 — Provider Limits light mode background fix\n\n---\n\n## [3.0.6] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context\n- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections\n- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)\n\n### ✨ New Features\n\n- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts\n\n### 🔧 Maintenance\n\n- Merged PR #623 — LongCat API base URL path correction\n\n---\n\n## [3.0.5] — 2026-03-25\n\n### ✨ New Features\n\n- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.\n\n---\n\n## [3.0.4] — 2026-03-25\n\n### 🐛 Bug Fixes\n\n- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)\n- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`\n- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.\n- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails\n\n---\n\n## [3.0.3] — 2026-03-25\n\n### ✨ New Features\n\n- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)\n\n### 🐛 Bug Fixes\n\n- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)\n- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)\n- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)\n- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)\n\n### 🌐 Translations\n\n- **cs:** Improved Czech translation strings across the app (PR #601)\n\n## [3.0.2] — 2026-03-25\n\n### 🚀 Enhancements & Features\n\n#### feat(ui): Connection Tag Grouping\n\n- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.\n- Connections in the provider view now dynamically group by tag with visual dividers.\n- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.\n- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.\n\n### 🐛 Bug Fixes\n\n#### fix(ui): Proxy Management UI Stabilization\n\n- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.\n- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.\n- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.\n- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.\n\n#### fix(translator): `function_call` prefix stripping\n\n- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.\n\n---\n\n## [3.0.1] — 2026-03-25\n\n### 🔧 Hotfix Patch — Critical Bug Fixes\n\nThree critical regressions reported by users after the v3.0.0 launch have been resolved.\n\n#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)\n\nThe `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.\n\n**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.\n\n#### fix(validation): add LongCat specialty validator to skip /models probe (#592)\n\nLongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.\n\n**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.\n\n#### fix(translator): normalize object tool schemas for Anthropic (#595)\n\nMCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:\"object\"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.\n\n**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `\"object\"` and `properties` is absent.\n\n---\n\n### 🔀 Community PRs Merged (2)\n\n| PR | Author | Summary |\n| -------- | ------- | -------------------------------------------------------------------------- |\n| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |\n| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |\n\n---\n\n### ✅ Issues Resolved\n\n`#592` `#595` `#605`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (unchanged from v3.0.0)\n\n---\n\n## [3.0.0] — 2026-03-24\n\n### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers\n\n> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.\n>\n> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).\n\n---\n\n### 🆕 New Providers (+31 since v2.9.5)\n\n| Provider | Alias | Tier | Notes |\n| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |\n| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |\n| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |\n| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |\n| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |\n| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |\n| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |\n| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |\n| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |\n| **MiniMax Coding** | `minimax` | Paid | International endpoint |\n| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |\n| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |\n| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |\n| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |\n| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |\n| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |\n| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |\n| **Serper Search** | `serper-search` | Paid | Web search API integration |\n| **Brave Search** | `brave-search` | Paid | Brave Search API integration |\n| **Exa Search** | `exa-search` | Paid | Neural search API integration |\n| **Tavily Search** | `tavily-search` | Paid | AI search API integration |\n| **NanoBanana** | `nb` | Paid | Image generation API |\n| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |\n| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |\n| **PlayHT** | `playht` | Paid | Voice cloning and TTS |\n| **Inworld** | `inworld` | Paid | AI character voice chat |\n| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |\n| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |\n| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |\n\n**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.\n\n---\n\n### ✨ Major Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------- | ------------ | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n\n#### 🎨 Provider Icons via @lobehub/icons (#529)\n\n130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nAuto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.\n\n#### 🔀 Per-Model Combo Routing (#563)\n\nMap model name patterns (glob) to specific combos for automatic routing:\n\n- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n- New `model_combo_mappings` table with glob-to-regex matching\n- Dashboard UI section: \"Model Routing Rules\" with inline add/edit/toggle/delete\n\n#### 🧭 API Endpoints Dashboard\n\nInteractive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.\n\n#### 🔍 Web Search Providers\n\n5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.\n\n#### 📊 Search Analytics\n\nNew tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.\n\n#### 🛡️ Per-API-Key Rate Limits (#452)\n\n`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.\n\n#### 🎵 Media Playground\n\nFull media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.\n\n---\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection\n- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced\n- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides\n- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)\n- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4\n\n---\n\n### 🐛 Bug Fixes (40+)\n\n#### OAuth & Auth\n\n- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker\n- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)\n- **#574** — Login no longer freezes after skipping wizard password setup\n- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)\n\n#### Providers & Routing\n\n- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`\n- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`\n- **#570** — Unprefixed Claude models now resolve to Anthropic provider\n- **#585** — `` internal tags no longer leak to clients in SSE streaming\n- **#493** — Custom provider model naming no longer mangled by prefix stripping\n- **#490** — Streaming + context cache protection via `TransformStream` injection\n- **#511** — `` tag injected into first content chunk (not after `[DONE]`)\n\n#### CLI & Tools\n\n- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text\n- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)\n- **#522** — API Manager: removed misleading \"Copy masked key\" button\n- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)\n- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)\n- **#510** — Windows MSYS2/Git-Bash paths normalized automatically\n- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing\n\n#### Streaming & SSE\n\n- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)\n- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)\n- **#483** — Stop trailing `data: null` after `[DONE]` signal\n- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback\n\n#### Media & Transcription\n\n- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation\n- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors\n- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)\n\n---\n\n### 🔧 Infrastructure & Improvements\n\n#### Sub2api Gap Analysis (T01–T15 + T23–T42)\n\n- **T01** — `requested_model` column in call logs (migration 009)\n- **T02** — Strip empty text blocks from nested `tool_result.content`\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers\n- **T04** — `X-Session-Id` header for external sticky routing\n- **T05** — Rate-limit DB persistence with dedicated API\n- **T06** — Account deactivated → permanent block (1-year cooldown)\n- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)\n- **T08** — Per-API-key session limits with sliding-window enforcement\n- **T09** — Codex vs Spark rate-limit scopes (separate pools)\n- **T10** — Credits exhausted → distinct 1h cooldown fallback\n- **T11** — `max` reasoning effort → 131072 budget tokens\n- **T12** — MiniMax M2.7 pricing entries\n- **T13** — Stale quota display fix (reset window awareness)\n- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)\n- **T15** — Array content normalization for Anthropic\n- **T23** — Intelligent quota reset fallback (header extraction)\n- **T24** — `503` cooldown + `406` mapping\n- **T25** — Provider validation fallback\n- **T29** — Vertex AI Service Account JWT auth\n- **T33** — Thinking level to budget conversion\n- **T36** — `403` vs `429` error classification\n- **T38** — Centralized model specifications (`modelSpecs.ts`)\n- **T39** — Endpoint fallback for `fetchAvailableModels`\n- **T41** — Background task auto-redirect to flash models\n- **T42** — Image generation aspect ratio mapping\n\n#### Other Improvements\n\n- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)\n- **Model context length** — configurable in model metadata (PR #578 by @hijak)\n- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)\n- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning\n- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing\n- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)\n- **Log export** — New JSON export button on dashboard with time range dropdown\n- **Update notification banner** — dashboard homepage shows when new versions are available\n\n---\n\n### 🌐 i18n & Documentation\n\n- **30 languages** at 100% parity — 2,788 missing keys synced\n- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)\n- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)\n- **VM Deployment Guide** — Translated to English as source document\n- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints\n- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs\n\n---\n\n### 🔀 Community PRs Merged (10)\n\n| PR | Author | Summary |\n| -------- | --------------- | -------------------------------------------------------------------- |\n| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |\n| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |\n| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |\n| **#578** | @hijak | feat: configurable context length in model metadata |\n| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |\n| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |\n| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |\n| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |\n| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |\n| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |\n| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |\n| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |\n| **#480** | @prakersh | fix: stream flush usage extraction |\n| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |\n| **#475** | @only4copilot | feat(i18n): improved Chinese translation |\n\n**Thank you to all contributors!** 🙏\n\n---\n\n### 📋 Issues Resolved (50+)\n\n`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`\n\n---\n\n### 🧪 Tests\n\n- **926 tests, 0 failures** (up from 821 in v2.9.5)\n- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more\n\n---\n\n### 📦 Database Migrations\n\n| Migration | Description |\n| --------- | --------------------------------------------------------------------- |\n| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |\n| **009** | `requested_model` column in `call_logs` |\n| **010** | `model_combo_mappings` table for per-model combo routing |\n\n---\n\n### ⬆️ Upgrading from v2.9.5\n\n```bash\n# npm\nnpm install -g omniroute@3.0.0\n\n# Docker\ndocker pull diegosouzapw/omniroute:3.0.0\n\n# Migrations run automatically on first startup\n```\n\n> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.\n> Database migrations 008-010 run automatically on startup.\n\n---\n\n## [3.0.0-rc.17] — 2026-03-24\n\n### 🔒 Security & CI/CD\n\n- **CodeQL remediation** — Fixed 10+ alerts:\n - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)\n - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)\n - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)\n- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:\n - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)\n - CI `check:route-validation:t06` now passes: **176/176 routes validated**\n\n### 🐛 Bug Fixes\n\n- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`\n\n### ⚙️ Infrastructure\n\n- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)\n- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs\n\n### 🧪 Tests\n\n- Test suite: **926 tests, 0 failures** (+3 new)\n\n---\n\n## [3.0.0-rc.16] — 2026-03-24\n\n### ✨ New Features\n\n- Increased media transcription limits\n- Added Model Context Length to registry metadata\n- Added per-model upstream custom headers via configuration UI\n- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.\n\n## [3.0.0-rc.15] — 2026-03-24\n\n### ✨ New Features\n\n- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing\n - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled\n - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)\n - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback\n - `chat.ts`: routing decision now checks model-combo mappings before single-model handling\n - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`\n - Dashboard: \"Model Routing Rules\" section added to Combos page with inline add/edit/toggle/delete\n - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo\n\n### 🌐 i18n\n\n- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`\n- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)\n- **6 new keys** added to `agents` namespace for OpenCode section\n\n### 🎨 UI/UX\n\n- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)\n- **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon\n- **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total)\n\n### الأمان\n\n- **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2`\n- `npm audit` now reports **0 vulnerabilities**\n\n### 🧪 Tests\n\n- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)\n\n---\n\n## [3.0.0-rc.14] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | -------------------------------------------------------------------------------------------- |\n| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |\n| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |\n\n### 🧪 Tests\n\n- Test suite: **908 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.13] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)\n\n---\n\n## [3.0.0-rc.12] — 2026-03-23\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |\n| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |\n| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |\n| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |\n\n### 🔧 Bug Fixes\n\n- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.\n- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.\n\n### 🧪 Tests\n\n- Test suite: **905 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.10] — 2026-03-23\n\n### 🔧 Bug Fixes\n\n- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.\n- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.\n- **#541** — Responded to user feedback about installation complexity; no code changes required.\n\n---\n\n## [3.0.0-rc.9] — 2026-03-23\n\n### ✨ New Features\n\n- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.\n- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.\n- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.\n\n### 🔧 Improvements\n\n- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.\n\n---\n\n## [3.0.0-rc.8] — 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)\n\n- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.\n- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.\n- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).\n- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.\n- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.\n- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.\n- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.\n\n---\n\n## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_\n\n> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).\n\n### 🆕 New Providers\n\n| Provider | Alias | Tier | Notes |\n| ---------------- | -------------- | ---- | -------------------------------------------------------------- |\n| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |\n| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |\n\nBoth providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).\n\n---\n\n### ✨ New Features\n\n#### 🔑 Registered Keys Provisioning API (#464)\n\nAuto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.\n\n| Endpoint | Method | Description |\n| ------------------------------------- | --------- | ------------------------------------------------ |\n| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |\n| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |\n| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |\n| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |\n| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |\n| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |\n| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |\n| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |\n| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |\n\n**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.\n**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.\n**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.\n**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.\n**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.\n**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.\n\n#### 🎨 Provider Icons — @lobehub/icons (#529)\n\nAll provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).\nFallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.\n\n#### 🔄 Model Auto-Sync Scheduler (#488)\n\nOmniRoute now automatically refreshes model lists for connected providers every **24 hours**.\n\n- Runs on server startup via the existing `/api/sync/initialize` hook\n- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable\n- Covers 16 major providers\n- Records last sync time in the settings database\n\n---\n\n### 🔧 Bug Fixes\n\n#### OAuth & Auth\n\n- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.\n\n#### Providers & Routing\n\n- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).\n- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.\n- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.\n\n#### CLI & Tools\n\n- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.\n- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).\n- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.\n- **#522 — API Manager:** Removed misleading \"Copy masked key\" button (replaced with a lock icon tooltip).\n- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.\n\n#### Developer Experience\n\n- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.\n- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...` automatically.\n- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.\n\n---\n\n### 📖 Documentation Updates\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented\n\n---\n\n### ✅ Issues Resolved in v3.0.0\n\n`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`\n\n---\n\n### 🔀 Community PRs Merged\n\n| PR | Author | Summary |\n| -------- | ------------ | ---------------------------------------------------------------------- |\n| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |\n\n---\n\n## [3.0.0-rc.7] - 2026-03-23\n\n### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)\n\n- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.\n- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.\n- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `\"codex\"`; spark models (`codex-spark*`) get scope `\"spark\"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.\n- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `\"2h 35m\"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.\n- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures**\n\n---\n\n## [3.0.0-rc.6] - 2026-03-23\n\n### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)\n\n- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.\n- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.\n- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.\n- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).\n- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.\n- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).\n- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.\n- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `\"max\"` for full-budget responses. Unit test updated.\n- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.\n- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.\n\n### 🧪 Tests\n\n- Test suite: **832 tests, 0 failures** (unchanged from rc.5)\n\n---\n\n## [3.0.0-rc.5] - 2026-03-22\n\n### ✨ New Features\n\n- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement\n - `POST /api/v1/registered-keys` — issue keys with idempotency support\n - `GET /api/v1/registered-keys` — list (masked) registered keys\n - `GET /api/v1/registered-keys/{id}` — get key metadata\n - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys\n - `GET /api/v1/quotas/check` — pre-validate before issuing\n - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits\n - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits\n - `POST /api/v1/issues/report` — optional GitHub issue reporting\n - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables\n\n---\n\n## [3.0.0-rc.4] - 2026-03-22\n\n### ✨ New Features\n\n- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)\n - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)\n - 7 models across both tiers\n\n---\n\n## [3.0.0-rc.3] - 2026-03-22\n\n### ✨ New Features\n\n- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)\n- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)\n\n### 🔧 Bug Fixes\n\n- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments\n\n---\n\n## [3.0.0-rc.2] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)\n- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model\n- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)\n\n---\n\n## [3.0.0-rc.1] - 2026-03-22\n\n### 🔧 Bug Fixes\n\n- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)\n- **#522** — API Manager: Removed misleading \"Copy masked key\" button (replaced with lock icon tooltip)\n- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped\n- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)\n- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance\n- **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...`\n- **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix\n\n### التوثيق\n\n- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented\n- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented\n\n### ✅ Closed Issues\n\n#489, #492, #510, #513, #520, #521, #522, #525, #527, #532\n\n---\n\n## [2.9.5] — 2026-03-22\n\n> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.\n\n### 🐛 Bug Fixes\n\n- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.\n- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)\n- **Context cache protection regex misses `\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.\n\n### ✨ New Providers\n\n- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`\n- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)\n- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)\n\n---\n\n## [2.9.4] — 2026-03-21\n\n> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.\n\n### 🐛 Bug Fixes\n\n- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)\n — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.\n Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.\n\n- **fix(combo)**: Escape `\n` in `tagContent` so injected JSON string is valid (#515)\n — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.\n Replaced with `\\n` literal sequences in `open-sse/services/combo.ts`.\n\n- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)\n — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated\n to `\"expired\"` in the database so the Providers page reflects the same degraded state.\n Fixed in `src/app/api/usage/[connectionId]/route.ts`.\n\n---\n\n## [2.9.3] — 2026-03-21\n\n> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.\n\n### ✨ New Providers\n\n- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.\n- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.\n- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.\n- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.\n- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.\n\n### 🔄 Provider Updates\n\n- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`\n- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)\n- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity\n\n### ⚙️ Infrastructure\n\n- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided\n- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials\n- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings\n\n### التوثيق\n\n- **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever)\n- **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables\n- **docs(readme)**: Updated pricing table with 4 new free tier rows\n- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese\n- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n---\n\n## [2.9.2] — 2026-03-21\n\n> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.\n\n### 🐛 Bug Fixes\n\n- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned \"No speech detected\" because Deepgram was receiving `Content-Type: video/mp4`.\n- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.\n- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.\n- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: \"...\", status_code: 401 } }` instead of a flat error string.\n\n### 🧪 Tests\n\n- Test suite: **821 tests, 0 failures** (unchanged)\n\n### Triaged Issues\n\n- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)\n- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)\n- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)\n- **#442** — Baseten /models endpoint: closed (documented manual workaround)\n- **#464** — Key provisioning API: acknowledged as roadmap item\n\n---\n\n## [2.9.1] — 2026-03-21\n\n> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.\n\n### Bug Fixes\n\n- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.\n\n### Merged PRs\n\n- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.\n\n### Triaged Issues\n\n- **#510** — Windows CLI healthcheck_failed: requested PATH/version info\n- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds\n- **#508** — macOS black screen: suggested `--disable-gpu` workaround\n\n---\n\n## [2.9.0] — 2026-03-20\n\n> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.\n\n### ✨ New Features\n\n- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)\n- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)\n- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)\n- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)\n\n### 🐛 Bug Fixes\n\n- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.\n- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.\n- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.\n- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.\n- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.\n\n### 🧪 Tests\n\n- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper\n- Test suite: **821 tests, 0 failures** (up from 813)\n\n### 📋 Issues Closed (8)\n\n- **#506** — Windows machineId `head` not recognized (fixed)\n- **#493** — Custom provider model naming (fixed)\n- **#490** — Streaming context cache (fixed)\n- **#452** — Per-API-key request limits (implemented)\n- **#466** — Windows login failure (same root cause as #506)\n- **#504** — MITM inactive (expected behavior)\n- **#462** — Gemini CLI PSA (resolved)\n- **#434** — Electron app crash (duplicate of #402)\n\n## [2.8.9] — 2026-03-20\n\n> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.\n\n### Merged PRs\n\n- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**\n- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)\n- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.\n\n### Bug Fixes\n\n- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.\n- **#504** — Responded with UX clarification (MITM \"Inactive\" is expected behavior when proxy is not running).\n\n---\n\n## [2.8.8] — 2026-03-20\n\n> Sprint: Fix OAuth batch test crash, add \"Test All\" button to individual provider pages.\n\n### Bug Fixes\n\n- **OAuth batch test crash** (ERR_CONNECTION_REFUSED): Replaced sequential for-loop with 5-connection concurrency limit + 30s per-connection timeout via `Promise.race()` + `Promise.allSettled()`. Prevents server crash when testing large OAuth provider groups (~30+ connections).\n\n### الميزات\n\n- **\"Test All\" button on provider pages**: Individual provider pages (e.g., `/providers/codex`) now show a \"Test All\" button in the Connections header when there are 2+ connections. Uses `POST /api/providers/test-batch` with `{mode: \"provider\", providerId}`. Results displayed in a modal with pass/fail summary and per-connection diagnosis.\n\n---\n\n## [2.8.7] — 2026-03-20\n\n> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.\n\n### Bug Fixes\n\n- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.\n- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.\n\n### Issues Responded\n\n- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)\n- **#464** — Auto-issue API keys with provider/account limits (needs more detail)\n- **#488** — Auto-update model lists (acknowledged, on roadmap)\n- **#496** — Custom embedding provider resolution (fixed)\n\n---\n\n## [2.8.6] — 2026-03-20\n\n> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.\n\n### الميزات\n\n- **MiniMax developer→system role fix** (PR #494 by @zhangqiang8vip): Per-model `preserveDeveloperRole` toggle. Adds \"Compatibility\" UI in providers page. Fixes 422 \"role param error\" for MiniMax and similar gateways.\n- **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert).\n- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.\n\n### Bug Fixes\n\n- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: \"mitm\"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.\n- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.\n\n### Cleanup\n\n- Removed `ZWS_README_V2.md` (development-only docs from PR #494).\n\n### Issues Triaged (8)\n\n- **#487** — Closed (KIRO MITM fixed in this release)\n- **#486** — needs-info (Windows REG.exe PATH issue)\n- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)\n- **#492** — needs-info (missing app/server.js on mise-managed Node)\n- **#490** — Acknowledged (streaming + context cache blocking, fix planned)\n- **#491** — Acknowledged (Codex auth state inconsistency)\n- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)\n- **#488** — Feature request backlog (auto-update model lists)\n\n---\n\n## [2.8.5] — 2026-03-19\n\n> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.\n\n### Bug Fixes\n\n- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.\n- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.\n- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.\n- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.\n\n### Closed Issues\n\n- #473 — Zombie SSE streams bypass combo fallback\n- #474 — Context cache `` tag missing on first turn\n- #481 — MITM for KIRO not activatable from dashboard\n- #468 — Gemini CLI remote server (superseded by #462 deprecation)\n- #438 — Claude unable to write files (external CLI issue)\n- #439 — AppImage doesn't work (documented libfuse2 workaround)\n- #402 — ARM64 DMG \"damaged\" (documented xattr -cr workaround)\n- #460 — CLI not runnable on Windows (documented PATH fix)\n\n---\n\n## [2.8.4] — 2026-03-19\n\n> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.\n\n### الميزات\n\n- **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026\n- **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields\n\n### Bug Fixes\n\n- **VM Guide i18n** (#471): Add `VM_DEPLOYMENT_GUIDE.md` to i18n translation pipeline, regenerate all 30 locale translations from English source (were stuck in Portuguese)\n\n### الأمان\n\n- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)\n\n### Closed Issues\n\n- #472 — Model Aliases regression (fixed in v2.8.2)\n- #471 — VM guide translations broken\n- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)\n\n### Merged PRs\n\n- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)\n\n---\n\n## [2.8.3] — 2026-03-19\n\n> Sprint: Czech i18n, SSE protocol fix, VM guide translation.\n\n### الميزات\n\n- **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit)\n- **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit)\n\n### Bug Fixes\n\n- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)\n\n### Merged PRs\n\n- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)\n\n---\n\n## [2.8.2] — 2026-03-19\n\n> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.\n\n### الميزات\n\n- **Log Export**: New Export button on `/dashboard/logs` with time range dropdown (1h, 6h, 12h, 24h). Downloads JSON of request/proxy/call logs via `/api/logs/export` API (#user-request)\n\n### Bug Fixes\n\n- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider\n- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)\n\n### Merged PRs\n\n- #480 — Extract usage from remaining buffer in flush handler (@prakersh)\n- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)\n\n---\n\n## [2.8.1] — 2026-03-19\n\n> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.\n\n### الميزات\n\n- **feat(logs)**: Call log response content now correctly accumulated from raw provider chunks (OpenAI/Claude/Gemini) before translation, fixing empty response payloads in streaming mode (#470, @zhangqiang8vip)\n- **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470)\n- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)\n- **feat(dashboard)**: Response-first layout in request log detail UI (#470)\n- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)\n\n### 🐛 Bug Fixes\n\n- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)\n- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)\n- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)\n\n---\n\n## [2.8.0] — 2026-03-19\n\n> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.\n\n### الميزات\n\n- **feat(providers)**: Added Bailian Coding Plan (`bailian-coding-plan`) — Alibaba Model Studio with Anthropic-compatible API. Static catalog of 8 models including Qwen3.5 Plus, Qwen3 Coder, MiniMax M2.5, GLM 5, and Kimi K2.5. Includes custom auth validation (400=valid, 401/403=invalid) (#467, @Mind-Dragon)\n- **feat(admin)**: Editable default URL in Provider Admin create/edit flows — users can configure custom base URLs per connection. Persisted in `providerSpecificData.baseUrl` with Zod schema validation rejecting non-http(s) schemes (#467)\n\n### 🧪 Tests\n\n- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration\n\n---\n\n## [2.7.10] — 2026-03-19\n\n> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.\n\n### الميزات\n\n- **feat(providers)**: Added Alibaba Cloud Coding Plan support with two OpenAI-compatible endpoints — `alicode` (China) and `alicode-intl` (International), each with 8 models (#465, @dtk1985)\n- **feat(providers)**: Added dedicated `kimi-coding-apikey` provider path — API-key-based Kimi Coding access is no longer forced through OAuth-only `kimi-coding` route. Includes registry, constants, models API, config, and validation test (#463, @Mind-Dragon)\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)\n\n---\n\n## [2.7.9] — 2026-03-18\n\n> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.\n\n### الميزات\n\n- **feat(codex)**: Native responses subpath passthrough for Codex — natively routes `POST /v1/responses/compact` to Codex upstream, maintaining Claude Code compatibility without stripping the `/compact` suffix (#457)\n\n### 🐛 Bug Fixes\n\n- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)\n- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)\n\n---\n\n## [2.7.8] — 2026-03-18\n\n> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.\n\n### 🐛 Bug Fixes\n\n- **fix(budget)**: \"Save Limits\" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451)\n- **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454)\n\n### الميزات\n\n- **feat(combos)**: Agent Features section added to combo create/edit modal — expose `system_message` override, `tool_filter_regex`, and `context_cache_protection` directly from the dashboard (#454)\n\n---\n\n## [2.7.7] — 2026-03-18\n\n> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.\n\n### 🐛 Bug Fixes\n\n- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)\n- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)\n\n### 🔧 Maintenance\n\n- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions\n\n---\n\n## [2.7.5] — 2026-03-18\n\n> Sprint: UX improvements and Windows CLI healthcheck fix.\n\n### 🐛 Bug Fixes\n\n- **fix(ux)**: Show default password hint on login page — new users now see `\"Default password: 123456\"` below the password input (#437)\n- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)\n\n---\n\n## [2.7.4] — 2026-03-18\n\n> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.\n\n### الميزات\n\n- **feat(search)**: Add Search Playground (10th endpoint), Search Tools page with Compare Providers/Rerank Pipeline/Search History, local rerank routing, auth guards on search API (#443 by @Regis-RCR)\n - New route: `/dashboard/search-tools`\n - Sidebar entry under Debug section\n - `GET /api/search/providers` and `GET /api/search/stats` with auth guards\n - Local provider_nodes routing for `/v1/rerank`\n - 30+ i18n keys in search namespace\n\n### 🐛 Bug Fixes\n\n- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)\n- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)\n- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)\n- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)\n\n---\n\n## [2.7.3] — 2026-03-18\n\n> Sprint: Codex direct API quota fallback fix.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)\n - `resolveQuotaWindow()` prefix matching: `\"weekly\"` now matches `\"weekly (7d)\"` cache keys\n - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly\n - 4 new regression tests (766 total)\n\n---\n\n## [2.7.2] — 2026-03-18\n\n> Sprint: Light mode UI contrast fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)\n - Error/Success/Combo filter buttons now readable in light mode\n - Combo row badge uses stronger violet in light mode\n\n---\n\n## [2.7.1] — 2026-03-17\n\n> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).\n\n### ✨ New Features\n\n- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)\n - Auto-failover across providers, 6,500+ free searches/month\n - In-memory cache with request coalescing (configurable TTL)\n - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking\n - New API: `GET /api/v1/search/analytics` for search request statistics\n - DB migration: `request_type` column on `call_logs` for non-chat request tracking\n - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`\n\n### الأمان\n\n- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:\n - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)\n - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)\n - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7\n\n### 📁 New Files\n\n| File | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------ |\n| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |\n| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |\n| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |\n| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |\n| `src/app/api/v1/search/analytics/route.ts` | Search stats API |\n| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |\n| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |\n| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |\n\n---\n\n## [2.7.0] — 2026-03-17\n\n> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.\n\n### ✨ New Models & Pricing\n\n- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported\n- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship\n- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context\n- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks\n- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`\n- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access\n- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output\n\n### 🧠 Routing Intelligence\n\n- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models\n- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context\n- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically\n- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients\n- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core\n\n### 🔧 MCP Server Improvements\n\n- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)\n- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools\n- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing\n\n### 📊 Observability\n\n- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account\n- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields\n- **feat(usage)**: Usage history migration for per-model latency tracking\n\n### 🗄️ DB Migrations\n\n- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users\n\n### 🐛 Bug Fixes / Closures\n\n- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)\n- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)\n- **close(#405)**: Duplicate of #411 — resolved\n\n## [2.6.10] — 2026-03-17\n\n> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).\n\n### 🐛 Bug Fixes\n\n- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.\n\n---\n\n## [2.6.9] — 2026-03-17\n\n> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.\n\n### 🐛 Bug Fixes\n\n- **fix(ci)**: Remove word \"any\" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\bany\b` budget check (false positive from regex counting comments)\n- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:\"file\"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with \"type has to be either 'image_url' or 'text'\"; fix converts `file`/`document` blocks to `text` and drops unknown types)\n\n### 🔧 Workflow\n\n- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together\n\n---\n\n## [2.6.8] — 2026-03-17\n\n> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.\n\n### 🗄️ DB Migrations (zero-breaking — safe for existing users)\n\n- **005_combo_agent_fields.sql**: `ALTER TABLE combos ADD COLUMN system_message TEXT DEFAULT NULL`, `tool_filter_regex TEXT DEFAULT NULL`, `context_cache_protection INTEGER DEFAULT 0`\n- **006_detailed_request_logs.sql**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle\n\n### الميزات\n\n- **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider)\n- **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats)\n- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)\n- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)\n- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)\n- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)\n\n---\n\n## [2.6.7] — 2026-03-17\n\n> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.\n\n### الميزات\n\n- **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR)\n- **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR)\n- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)\n- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)\n- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)\n- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)\n- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)\n- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)\n- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)\n- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)\n- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)\n\n### 📦 Dependencies\n\n- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)\n\n---\n\n## [2.6.6] — 2026-03-17\n\n> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.\n- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.\n\n---\n\n## [2.6.5] — 2026-03-17\n\n> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.\n\n### ✨ New Features\n\n- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)\n\n### 🐛 Bug Fixes\n\n- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)\n- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)\n\n### 📦 Dependencies\n\n- `better-sqlite3` 12.6.2 → 12.8.0\n- `undici` 7.24.2 → 7.24.4\n- `https-proxy-agent` 7 → 8\n- `agent-base` 7 → 8\n\n---\n\n## [2.6.4] — 2026-03-17\n\n### 🐛 Bug Fixes\n\n- **fix(providers)**: Removed non-existent model names across 5 providers:\n - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`\n - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models\n - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`\n - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`\n- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`\n\n---\n\n## [2.6.3] — 2026-03-16\n\n> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Turbopack hash-strip now runs at **compile time** for ALL packages — not just `better-sqlite3`. Step 5.6 in `prepublish.mjs` walks every `.js` in `app/.next/server/` and strips the 16-char hex suffix from any hashed `require()`. Fixes `zod-dcb22c...`, `pino-...`, etc. MODULE_NOT_FOUND on global npm installs. Closes #398\n- **fix(deploy)**: PM2 on both VPS was pointing to stale git-clone directories. Reconfigured to `app/server.js` in the npm global package. Updated `/deploy-vps` workflow to use `npm pack + scp` (npm registry rejects 299MB packages).\n\n### الميزات\n\n- **feat(provider)**: Synthetic ([synthetic.new](https://synthetic.new)) — privacy-focused OpenAI-compatible inference. `passthroughModels: true` for dynamic HuggingFace model catalog. Initial models: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 by @Regis-RCR)\n\n### 📋 Issues Closed\n\n- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish\n- **triage #324**: Bug screenshot without steps — requested reproduction details\n\n---\n\n## [2.6.2] — 2026-03-16\n\n> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Extended webpack `externals` hash-strip to cover ALL `serverExternalPackages`, not just `better-sqlite3`. Next.js 16 Turbopack hashes `zod`, `pino`, and every other server-external package into names like `zod-dcb22c6336e0bc69` that don't exist in `node_modules` at runtime. A HASH_PATTERN regex catch-all now strips the 16-char suffix and falls back to the base package name. Also added `NEXT_PRIVATE_BUILD_WORKER=0` in `prepublish.mjs` to reinforce webpack mode, plus a post-build scan that reports any remaining hashed refs. (#396, #398, PR #403)\n- **fix(chat)**: Anthropic-format tool names (`tool.name` without `.function` wrapper) were silently dropped by the empty-name filter introduced in #346. LiteLLM proxies requests with `anthropic/` prefix in Anthropic Messages API format, causing all tools to be filtered and Anthropic to return `400: tool_choice.any may only be specified while providing tools`. Fixed by falling back to `tool.name` when `tool.function.name` is absent. Added 8 regression unit tests. (PR #397)\n\n### الميزات\n\n- **feat(api)**: Custom endpoint paths for OpenAI-compatible provider nodes — configure `chatPath` and `modelsPath` per node (e.g. `/v4/chat/completions`) in the provider connection UI. Includes a DB migration (`003_provider_node_custom_paths.sql`) and URL path sanitization (no `..` traversal, must start with `/`). (PR #400)\n- **feat(provider)**: Alibaba Cloud DashScope added as OpenAI-compatible provider. International endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1`. 12 models: `qwen-max`, `qwen-plus`, `qwen-turbo`, `qwen3-coder-plus/flash`, `qwq-plus`, `qwq-32b`, `qwen3-32b`, `qwen3-235b-a22b`. Auth: Bearer API key.\n\n### 📋 Issues Closed\n\n- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9\n- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage\n- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround\n\n---\n\n## [2.6.1] — 2026-03-15\n\n> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)\n\n### 🔧 CI\n\n- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)\n- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)\n\n---\n\n## [2.6.0] - 2026-03-15\n\n> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)\n- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)\n- **fix(oauth)**: Qoder (and other providers that redirect to their own UI) no longer leave the OAuth modal stuck at \"Waiting for Authorization\" — popup-closed detector auto-transitions to manual URL input mode (#344)\n- **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378)\n\n### الميزات\n\n- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)\n\n### 🛠 Chores\n\n- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)\n\n---\n\n## [2.5.9] - 2026-03-15\n\n> Codex native passthrough fix + route body validation hardening.\n\n### 🐛 Bug Fixes\n\n- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)\n- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)\n- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)\n\n---\n\n## [2.5.8] - 2026-03-15\n\n> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.\n\n### 🐛 Bug Fixes\n\n- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment\n\n---\n\n## [2.5.7] - 2026-03-15\n\n> Media playground error handling fixes.\n\n### 🐛 Bug Fixes\n\n- **fix(media)**: Transcription \"API Key Required\" false positive when audio contains no speech (music, silence) — now shows \"No speech detected\" instead\n- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient\n- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `\"api key\"` in error messages for accurate credential error classification\n\n---\n\n## [2.5.6] - 2026-03-15\n\n> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.\n\n### 🐛 Bug Fixes\n\n- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `\"client_secret is missing\"` errors for all users without a custom env var. Closes #383.\n- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.\n\n---\n\n## [2.5.5] - 2026-03-15\n\n> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.\n\n### 🐛 Bug Fixes\n\n- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.\n- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.\n\n### ✨ New Features\n\n- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.\n\n## [2.5.4] - 2026-03-15\n\n> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.\n\n### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)\n\n- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).\n- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.\n- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.\n\n### 🔧 CI & Infrastructure\n\n- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.\n- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN \"group\"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.\n- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.\n\n## [2.5.3] - 2026-03-14\n\n> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.\n\n### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)\n\n- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition\n- **fix(i18n) #371**: Replace non-existent `t(\"deleteConnection\")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page\n- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed\n- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database\n\n### 🔧 Code Quality\n\n- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)\n- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`\n- Added `preferredEnv` merge order comment in Electron startup\n\n> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.\n\n### ✨ New Features (PRs #366, #367, #368)\n\n- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.\n- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: \"flex\"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.\n- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.\n\n### 🐛 Bug Fixes\n\n- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.\n\n> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.\n\n### ✨ New Features (PRs #363 & #365)\n\n- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.\n- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.\n- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.\n- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.\n- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.\n\n### 🐛 Bug Fixes\n\n- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.\n- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.\n- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing \"Invalid input[N].name: empty string\" errors.\n\n### 🗑️ Closed Issues\n\n- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.\n\n> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.\n\n### ✨ New Features\n\n- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.\n\n### 📝 Already Implemented (confirmed in audit)\n\n- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.\n- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).\n\n> UI polish, routing strategy additions, and graceful error handling for usage limits.\n\n### ✨ New Features\n\n- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.\n- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.\n- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.\n\n### 🐛 Bug Fixes\n\n- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.\n- **MaintenanceBanner false-positive**: Banner no longer shows \"Server is unreachable\" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.\n- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.\n\n> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.\n\n### ✨ New Features\n\n- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.\n- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.\n- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.\n- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.\n- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.\n- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.\n- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.\n- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.\n\n### 🐛 Bug Fixes\n\n- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.\n- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.\n- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.\n- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.\n- **Media page generation errors**: Image results now render as `` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.\n- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.\n\n### 🔧 Improvements\n\n- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).\n- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.\n- **Quota Cache**: Improved quota cache with TTL-based eviction.\n\n### 📦 Dependencies\n\n- `dompurify` → 3.3.3 (PR #347)\n- `undici` → 7.24.2 (PR #348, #361)\n- `docker/setup-qemu-action` → v4 (PR #342)\n- `docker/setup-buildx-action` → v4 (PR #343)\n\n### 📁 New Files\n\n| File | Purpose |\n| --------------------------------------------- | --------------------------------------- |\n| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |\n| `src/app/api/settings/task-routing/route.ts` | Task routing config API |\n| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |\n| `src/lib/db/readCache.ts` | Efficient DB read cache |\n| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |\n\n## [2.4.1] - 2026-03-13\n\n### 🐛 Fix\n\n- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.\n\n## [2.4.0] - 2026-03-13\n\n> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.\n\n### الميزات\n\n- **Combos: Free Stack template** — New 4th template \"Free Stack ($0)\" using round-robin across Kiro + Qoder + Qwen + Gemini CLI. Suggests the pre-built zero-cost combo on first use.\n- **Media/Transcription: Deepgram as default** — Deepgram (Nova 3, $200 free) is now the default transcription provider. AssemblyAI ($50 free) and Groq Whisper (free forever) shown with free credit badges.\n- **README: \"Start Free\" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.\n- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.\n- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.\n- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.\n\n## [2.3.16] - 2026-03-13\n\n### التوثيق\n\n- **README: 44+ Providers** — Updated all 3 occurrences of \"36+ providers\" to \"44+\" reflecting the actual codebase count (44 providers in providers.ts)\n- **README: New Section \"🆓 Free Models — What You Actually Get\"** — Added 7-provider table with per-model rate limits for: Kiro (Claude unlimited via AWS Builder ID), Qoder (5 models unlimited), Qwen (4 models unlimited), Gemini CLI (180K/mo), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/day / 60K TPM), Groq (30 RPM / 14.4K RPD). Includes the \\/usr/bin/bash Ultimate Free Stack combo recommendation.\n- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from \"1000 credits\" to \"dev-forever free\", updated Qoder/Qwen model counts and names\n- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)\n- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)\n\n## [2.3.15] - 2026-03-13\n\n### الميزات\n\n- **Auto-Combo Dashboard (Tier Priority)**: Added `🏷️ Tier` as the 7th scoring factor label in the `/dashboard/auto-combo` factor breakdown display — all 7 Auto-Combo scoring factors are now visible.\n- **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files.\n\n## [2.3.14] - 2026-03-13\n\n### 🐛 Bug Fixes\n\n- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing \"Bad client credentials\" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).\n- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.\n- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.\n- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.\n\n### ✨ New Models (#334)\n\n- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`\n- **Codex**: `gpt5.4`\n\n### 🔧 Improvements\n\n- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.\n\n### ✨ New Features\n\n- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).\n- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).\n- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)\n- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.\n\n### 🐛 Bug Fixes\n\n- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)\n- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).\n- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.\n- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.\n- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.\n\n### 🔧 Improvements\n\n- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.\n- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.\n- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.\n- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.\n\n### 📁 New Files\n\n| File | Purpose |\n| ------------------------------------------ | -------------------------------------------------------- |\n| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |\n\n### Fixed\n\n- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11\n- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout\n- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants\n- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli\n- **cliRuntime**: Add opencode tool registration and increase timeout for continue\n\n## [2.3.11] - 2026-03-12\n\n### Fixed\n\n- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments\n\n## [2.3.10] - 2026-03-12\n\n### Fixed\n\n- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)\n\n### Docs\n\n- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)\n- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro\n\n## [2.3.8] - 2026-03-12\n\n## [2.3.9] - 2026-03-12\n\n### Added\n\n- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically\n- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions\n- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files\n\n### Fixed\n\n- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)\n- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers\n\n## [2.3.7] - 2026-03-12\n\n### Fixed\n\n- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing \"invalid or expired authorization code\" errors on remote (LAN IP) setups\n- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of \"Account #ID\"\n- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard\n- **OAuth account names**: Removed sequential \"Account N\" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted\n\n## [2.3.6] - 2026-03-12\n\n### Fixed\n\n- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning \"Invalid request\" for all batch tests\n- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`\n- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`\n- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks\n\n## [2.3.5] - 2026-03-11\n\n### Fixed\n\n- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs\n\n## [2.3.4] - 2026-03-10\n\n### Added\n\n- Multiple provider integrations and dashboard improvements\n"}}}}