github diegosouzapw/OmniRoute v3.6.5

22 hours ago

✨ New Features

  • 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)
  • 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)
  • 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)
  • 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
  • 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
  • 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
  • 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
  • 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)
  • Stabilization Settings: Added persistence support for lkgpEnabled and backgroundDegradation settings, integrated into instrumentation-node.ts for improved lifecycle awareness (#1212)
  • xxhash-wasm dependency: Added xxhash-wasm@^1.1.0 for CCH signing (xxHash64 with seed 0x6E52736AC806831E)

🐛 Bug Fixes

  • 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
  • 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)
  • 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)
  • 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)
  • 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
  • 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
  • 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)
  • 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)
  • 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
  • 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
  • API Key Deletion Orphan Cleanup: Deleting an API key now also removes associated domain_budgets and domain_cost_history rows, preventing orphan data accumulation
  • 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
  • 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)
  • 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)

🔧 Internal Improvements

  • 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
  • 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
  • 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
  • Provider Schema Validation: Added openaiStoreEnabled boolean validation to providerSpecificData Zod schema
  • Combo Error Response Normalization: Empty combo targets now return 404 (comboModelNotFoundResponse) instead of generic 503, improving client-side error differentiation
  • 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)

⚠️ Breaking Changes

  • 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).
  • 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

Don't miss a new OmniRoute release

NewReleases is sending notifications on new releases.